From: iceman1001 Date: Fri, 19 Sep 2014 08:50:34 +0000 (+0200) Subject: Merge branch 'master' of https://github.com/Proxmark/proxmark3 X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/75465377b93c9a27450a186342e9cfd2a84b4173?hp=92d255d3dc8fb9e567f3db035918249e6d083c35 Merge branch 'master' of https://github.com/Proxmark/proxmark3 Conflicts: armsrc/appmain.c armsrc/apps.h armsrc/iclass.c client/Makefile client/cmdhficlass.c client/loclass/cipher.c client/loclass/fileutils.c client/loclass/ikeys.h include/usb_cmd.h --- diff --git a/armsrc/LCD.c b/armsrc/LCD.c index 65d64ac9..87be5e3a 100644 --- a/armsrc/LCD.c +++ b/armsrc/LCD.c @@ -6,7 +6,7 @@ // LCD code //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "LCD.h" #include "fonts.h" diff --git a/armsrc/Makefile b/armsrc/Makefile index e10c1001..ea19491a 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -10,7 +10,7 @@ APP_INCLUDES = apps.h #remove one of the following defines and comment out the relevant line #in the next section to remove that particular feature from compilation -APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG +APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG -DWITH_CRC -fno-strict-aliasing #-DWITH_LCD #SRC_LCD = fonts.c LCD.c @@ -18,13 +18,15 @@ SRC_LF = lfops.c hitag2.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443.c -SRC_CRAPTO1 = crapto1.c crypto1.c +SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c +SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c THUMBSRC = start.c \ $(SRC_LCD) \ $(SRC_ISO15693) \ $(SRC_LF) \ - appmain.c printf.c \ + appmain.c \ + printf.c \ util.c \ string.c \ usb_cdc.c \ @@ -33,14 +35,15 @@ THUMBSRC = start.c \ # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ legicrf.c \ - iso14443crc.c \ - crc16.c \ $(SRC_ISO14443a) \ $(SRC_ISO14443b) \ $(SRC_CRAPTO1) \ + $(SRC_CRC) \ legic_prng.c \ iclass.c \ - crc.c + mifaredesfire.c \ + desfire_crypto.c \ + desfire_key.c # stdint.h provided locally until GCC 4.5 becomes C99 compliant APP_CFLAGS += -I. diff --git a/armsrc/aes.c b/armsrc/aes.c new file mode 100644 index 00000000..3df006bb --- /dev/null +++ b/armsrc/aes.c @@ -0,0 +1,1168 @@ +#include "stdio.h" +#include "aes.h" + +static const unsigned int Te0[256] = { + 0xc66363a5UL, 0xf87c7c84UL, 0xee777799UL, 0xf67b7b8dUL, + 0xfff2f20dUL, 0xd66b6bbdUL, 0xde6f6fb1UL, 0x91c5c554UL, + 0x60303050UL, 0x02010103UL, 0xce6767a9UL, 0x562b2b7dUL, + 0xe7fefe19UL, 0xb5d7d762UL, 0x4dababe6UL, 0xec76769aUL, + 0x8fcaca45UL, 0x1f82829dUL, 0x89c9c940UL, 0xfa7d7d87UL, + 0xeffafa15UL, 0xb25959ebUL, 0x8e4747c9UL, 0xfbf0f00bUL, + 0x41adadecUL, 0xb3d4d467UL, 0x5fa2a2fdUL, 0x45afafeaUL, + 0x239c9cbfUL, 0x53a4a4f7UL, 0xe4727296UL, 0x9bc0c05bUL, + 0x75b7b7c2UL, 0xe1fdfd1cUL, 0x3d9393aeUL, 0x4c26266aUL, + 0x6c36365aUL, 0x7e3f3f41UL, 0xf5f7f702UL, 0x83cccc4fUL, + 0x6834345cUL, 0x51a5a5f4UL, 0xd1e5e534UL, 0xf9f1f108UL, + 0xe2717193UL, 0xabd8d873UL, 0x62313153UL, 0x2a15153fUL, + 0x0804040cUL, 0x95c7c752UL, 0x46232365UL, 0x9dc3c35eUL, + 0x30181828UL, 0x379696a1UL, 0x0a05050fUL, 0x2f9a9ab5UL, + 0x0e070709UL, 0x24121236UL, 0x1b80809bUL, 0xdfe2e23dUL, + 0xcdebeb26UL, 0x4e272769UL, 0x7fb2b2cdUL, 0xea75759fUL, + 0x1209091bUL, 0x1d83839eUL, 0x582c2c74UL, 0x341a1a2eUL, + 0x361b1b2dUL, 0xdc6e6eb2UL, 0xb45a5aeeUL, 0x5ba0a0fbUL, + 0xa45252f6UL, 0x763b3b4dUL, 0xb7d6d661UL, 0x7db3b3ceUL, + 0x5229297bUL, 0xdde3e33eUL, 0x5e2f2f71UL, 0x13848497UL, + 0xa65353f5UL, 0xb9d1d168UL, 0x00000000UL, 0xc1eded2cUL, + 0x40202060UL, 0xe3fcfc1fUL, 0x79b1b1c8UL, 0xb65b5bedUL, + 0xd46a6abeUL, 0x8dcbcb46UL, 0x67bebed9UL, 0x7239394bUL, + 0x944a4adeUL, 0x984c4cd4UL, 0xb05858e8UL, 0x85cfcf4aUL, + 0xbbd0d06bUL, 0xc5efef2aUL, 0x4faaaae5UL, 0xedfbfb16UL, + 0x864343c5UL, 0x9a4d4dd7UL, 0x66333355UL, 0x11858594UL, + 0x8a4545cfUL, 0xe9f9f910UL, 0x04020206UL, 0xfe7f7f81UL, + 0xa05050f0UL, 0x783c3c44UL, 0x259f9fbaUL, 0x4ba8a8e3UL, + 0xa25151f3UL, 0x5da3a3feUL, 0x804040c0UL, 0x058f8f8aUL, + 0x3f9292adUL, 0x219d9dbcUL, 0x70383848UL, 0xf1f5f504UL, + 0x63bcbcdfUL, 0x77b6b6c1UL, 0xafdada75UL, 0x42212163UL, + 0x20101030UL, 0xe5ffff1aUL, 0xfdf3f30eUL, 0xbfd2d26dUL, + 0x81cdcd4cUL, 0x180c0c14UL, 0x26131335UL, 0xc3ecec2fUL, + 0xbe5f5fe1UL, 0x359797a2UL, 0x884444ccUL, 0x2e171739UL, + 0x93c4c457UL, 0x55a7a7f2UL, 0xfc7e7e82UL, 0x7a3d3d47UL, + 0xc86464acUL, 0xba5d5de7UL, 0x3219192bUL, 0xe6737395UL, + 0xc06060a0UL, 0x19818198UL, 0x9e4f4fd1UL, 0xa3dcdc7fUL, + 0x44222266UL, 0x542a2a7eUL, 0x3b9090abUL, 0x0b888883UL, + 0x8c4646caUL, 0xc7eeee29UL, 0x6bb8b8d3UL, 0x2814143cUL, + 0xa7dede79UL, 0xbc5e5ee2UL, 0x160b0b1dUL, 0xaddbdb76UL, + 0xdbe0e03bUL, 0x64323256UL, 0x743a3a4eUL, 0x140a0a1eUL, + 0x924949dbUL, 0x0c06060aUL, 0x4824246cUL, 0xb85c5ce4UL, + 0x9fc2c25dUL, 0xbdd3d36eUL, 0x43acacefUL, 0xc46262a6UL, + 0x399191a8UL, 0x319595a4UL, 0xd3e4e437UL, 0xf279798bUL, + 0xd5e7e732UL, 0x8bc8c843UL, 0x6e373759UL, 0xda6d6db7UL, + 0x018d8d8cUL, 0xb1d5d564UL, 0x9c4e4ed2UL, 0x49a9a9e0UL, + 0xd86c6cb4UL, 0xac5656faUL, 0xf3f4f407UL, 0xcfeaea25UL, + 0xca6565afUL, 0xf47a7a8eUL, 0x47aeaee9UL, 0x10080818UL, + 0x6fbabad5UL, 0xf0787888UL, 0x4a25256fUL, 0x5c2e2e72UL, + 0x381c1c24UL, 0x57a6a6f1UL, 0x73b4b4c7UL, 0x97c6c651UL, + 0xcbe8e823UL, 0xa1dddd7cUL, 0xe874749cUL, 0x3e1f1f21UL, + 0x964b4bddUL, 0x61bdbddcUL, 0x0d8b8b86UL, 0x0f8a8a85UL, + 0xe0707090UL, 0x7c3e3e42UL, 0x71b5b5c4UL, 0xcc6666aaUL, + 0x904848d8UL, 0x06030305UL, 0xf7f6f601UL, 0x1c0e0e12UL, + 0xc26161a3UL, 0x6a35355fUL, 0xae5757f9UL, 0x69b9b9d0UL, + 0x17868691UL, 0x99c1c158UL, 0x3a1d1d27UL, 0x279e9eb9UL, + 0xd9e1e138UL, 0xebf8f813UL, 0x2b9898b3UL, 0x22111133UL, + 0xd26969bbUL, 0xa9d9d970UL, 0x078e8e89UL, 0x339494a7UL, + 0x2d9b9bb6UL, 0x3c1e1e22UL, 0x15878792UL, 0xc9e9e920UL, + 0x87cece49UL, 0xaa5555ffUL, 0x50282878UL, 0xa5dfdf7aUL, + 0x038c8c8fUL, 0x59a1a1f8UL, 0x09898980UL, 0x1a0d0d17UL, + 0x65bfbfdaUL, 0xd7e6e631UL, 0x844242c6UL, 0xd06868b8UL, + 0x824141c3UL, 0x299999b0UL, 0x5a2d2d77UL, 0x1e0f0f11UL, + 0x7bb0b0cbUL, 0xa85454fcUL, 0x6dbbbbd6UL, 0x2c16163aUL, +}; +static const unsigned int Te1[256] = { + 0xa5c66363UL, 0x84f87c7cUL, 0x99ee7777UL, 0x8df67b7bUL, + 0x0dfff2f2UL, 0xbdd66b6bUL, 0xb1de6f6fUL, 0x5491c5c5UL, + 0x50603030UL, 0x03020101UL, 0xa9ce6767UL, 0x7d562b2bUL, + 0x19e7fefeUL, 0x62b5d7d7UL, 0xe64dababUL, 0x9aec7676UL, + 0x458fcacaUL, 0x9d1f8282UL, 0x4089c9c9UL, 0x87fa7d7dUL, + 0x15effafaUL, 0xebb25959UL, 0xc98e4747UL, 0x0bfbf0f0UL, + 0xec41adadUL, 0x67b3d4d4UL, 0xfd5fa2a2UL, 0xea45afafUL, + 0xbf239c9cUL, 0xf753a4a4UL, 0x96e47272UL, 0x5b9bc0c0UL, + 0xc275b7b7UL, 0x1ce1fdfdUL, 0xae3d9393UL, 0x6a4c2626UL, + 0x5a6c3636UL, 0x417e3f3fUL, 0x02f5f7f7UL, 0x4f83ccccUL, + 0x5c683434UL, 0xf451a5a5UL, 0x34d1e5e5UL, 0x08f9f1f1UL, + 0x93e27171UL, 0x73abd8d8UL, 0x53623131UL, 0x3f2a1515UL, + 0x0c080404UL, 0x5295c7c7UL, 0x65462323UL, 0x5e9dc3c3UL, + 0x28301818UL, 0xa1379696UL, 0x0f0a0505UL, 0xb52f9a9aUL, + 0x090e0707UL, 0x36241212UL, 0x9b1b8080UL, 0x3ddfe2e2UL, + 0x26cdebebUL, 0x694e2727UL, 0xcd7fb2b2UL, 0x9fea7575UL, + 0x1b120909UL, 0x9e1d8383UL, 0x74582c2cUL, 0x2e341a1aUL, + 0x2d361b1bUL, 0xb2dc6e6eUL, 0xeeb45a5aUL, 0xfb5ba0a0UL, + 0xf6a45252UL, 0x4d763b3bUL, 0x61b7d6d6UL, 0xce7db3b3UL, + 0x7b522929UL, 0x3edde3e3UL, 0x715e2f2fUL, 0x97138484UL, + 0xf5a65353UL, 0x68b9d1d1UL, 0x00000000UL, 0x2cc1ededUL, + 0x60402020UL, 0x1fe3fcfcUL, 0xc879b1b1UL, 0xedb65b5bUL, + 0xbed46a6aUL, 0x468dcbcbUL, 0xd967bebeUL, 0x4b723939UL, + 0xde944a4aUL, 0xd4984c4cUL, 0xe8b05858UL, 0x4a85cfcfUL, + 0x6bbbd0d0UL, 0x2ac5efefUL, 0xe54faaaaUL, 0x16edfbfbUL, + 0xc5864343UL, 0xd79a4d4dUL, 0x55663333UL, 0x94118585UL, + 0xcf8a4545UL, 0x10e9f9f9UL, 0x06040202UL, 0x81fe7f7fUL, + 0xf0a05050UL, 0x44783c3cUL, 0xba259f9fUL, 0xe34ba8a8UL, + 0xf3a25151UL, 0xfe5da3a3UL, 0xc0804040UL, 0x8a058f8fUL, + 0xad3f9292UL, 0xbc219d9dUL, 0x48703838UL, 0x04f1f5f5UL, + 0xdf63bcbcUL, 0xc177b6b6UL, 0x75afdadaUL, 0x63422121UL, + 0x30201010UL, 0x1ae5ffffUL, 0x0efdf3f3UL, 0x6dbfd2d2UL, + 0x4c81cdcdUL, 0x14180c0cUL, 0x35261313UL, 0x2fc3ececUL, + 0xe1be5f5fUL, 0xa2359797UL, 0xcc884444UL, 0x392e1717UL, + 0x5793c4c4UL, 0xf255a7a7UL, 0x82fc7e7eUL, 0x477a3d3dUL, + 0xacc86464UL, 0xe7ba5d5dUL, 0x2b321919UL, 0x95e67373UL, + 0xa0c06060UL, 0x98198181UL, 0xd19e4f4fUL, 0x7fa3dcdcUL, + 0x66442222UL, 0x7e542a2aUL, 0xab3b9090UL, 0x830b8888UL, + 0xca8c4646UL, 0x29c7eeeeUL, 0xd36bb8b8UL, 0x3c281414UL, + 0x79a7dedeUL, 0xe2bc5e5eUL, 0x1d160b0bUL, 0x76addbdbUL, + 0x3bdbe0e0UL, 0x56643232UL, 0x4e743a3aUL, 0x1e140a0aUL, + 0xdb924949UL, 0x0a0c0606UL, 0x6c482424UL, 0xe4b85c5cUL, + 0x5d9fc2c2UL, 0x6ebdd3d3UL, 0xef43acacUL, 0xa6c46262UL, + 0xa8399191UL, 0xa4319595UL, 0x37d3e4e4UL, 0x8bf27979UL, + 0x32d5e7e7UL, 0x438bc8c8UL, 0x596e3737UL, 0xb7da6d6dUL, + 0x8c018d8dUL, 0x64b1d5d5UL, 0xd29c4e4eUL, 0xe049a9a9UL, + 0xb4d86c6cUL, 0xfaac5656UL, 0x07f3f4f4UL, 0x25cfeaeaUL, + 0xafca6565UL, 0x8ef47a7aUL, 0xe947aeaeUL, 0x18100808UL, + 0xd56fbabaUL, 0x88f07878UL, 0x6f4a2525UL, 0x725c2e2eUL, + 0x24381c1cUL, 0xf157a6a6UL, 0xc773b4b4UL, 0x5197c6c6UL, + 0x23cbe8e8UL, 0x7ca1ddddUL, 0x9ce87474UL, 0x213e1f1fUL, + 0xdd964b4bUL, 0xdc61bdbdUL, 0x860d8b8bUL, 0x850f8a8aUL, + 0x90e07070UL, 0x427c3e3eUL, 0xc471b5b5UL, 0xaacc6666UL, + 0xd8904848UL, 0x05060303UL, 0x01f7f6f6UL, 0x121c0e0eUL, + 0xa3c26161UL, 0x5f6a3535UL, 0xf9ae5757UL, 0xd069b9b9UL, + 0x91178686UL, 0x5899c1c1UL, 0x273a1d1dUL, 0xb9279e9eUL, + 0x38d9e1e1UL, 0x13ebf8f8UL, 0xb32b9898UL, 0x33221111UL, + 0xbbd26969UL, 0x70a9d9d9UL, 0x89078e8eUL, 0xa7339494UL, + 0xb62d9b9bUL, 0x223c1e1eUL, 0x92158787UL, 0x20c9e9e9UL, + 0x4987ceceUL, 0xffaa5555UL, 0x78502828UL, 0x7aa5dfdfUL, + 0x8f038c8cUL, 0xf859a1a1UL, 0x80098989UL, 0x171a0d0dUL, + 0xda65bfbfUL, 0x31d7e6e6UL, 0xc6844242UL, 0xb8d06868UL, + 0xc3824141UL, 0xb0299999UL, 0x775a2d2dUL, 0x111e0f0fUL, + 0xcb7bb0b0UL, 0xfca85454UL, 0xd66dbbbbUL, 0x3a2c1616UL, +}; +static const unsigned int Te2[256] = { + 0x63a5c663UL, 0x7c84f87cUL, 0x7799ee77UL, 0x7b8df67bUL, + 0xf20dfff2UL, 0x6bbdd66bUL, 0x6fb1de6fUL, 0xc55491c5UL, + 0x30506030UL, 0x01030201UL, 0x67a9ce67UL, 0x2b7d562bUL, + 0xfe19e7feUL, 0xd762b5d7UL, 0xabe64dabUL, 0x769aec76UL, + 0xca458fcaUL, 0x829d1f82UL, 0xc94089c9UL, 0x7d87fa7dUL, + 0xfa15effaUL, 0x59ebb259UL, 0x47c98e47UL, 0xf00bfbf0UL, + 0xadec41adUL, 0xd467b3d4UL, 0xa2fd5fa2UL, 0xafea45afUL, + 0x9cbf239cUL, 0xa4f753a4UL, 0x7296e472UL, 0xc05b9bc0UL, + 0xb7c275b7UL, 0xfd1ce1fdUL, 0x93ae3d93UL, 0x266a4c26UL, + 0x365a6c36UL, 0x3f417e3fUL, 0xf702f5f7UL, 0xcc4f83ccUL, + 0x345c6834UL, 0xa5f451a5UL, 0xe534d1e5UL, 0xf108f9f1UL, + 0x7193e271UL, 0xd873abd8UL, 0x31536231UL, 0x153f2a15UL, + 0x040c0804UL, 0xc75295c7UL, 0x23654623UL, 0xc35e9dc3UL, + 0x18283018UL, 0x96a13796UL, 0x050f0a05UL, 0x9ab52f9aUL, + 0x07090e07UL, 0x12362412UL, 0x809b1b80UL, 0xe23ddfe2UL, + 0xeb26cdebUL, 0x27694e27UL, 0xb2cd7fb2UL, 0x759fea75UL, + 0x091b1209UL, 0x839e1d83UL, 0x2c74582cUL, 0x1a2e341aUL, + 0x1b2d361bUL, 0x6eb2dc6eUL, 0x5aeeb45aUL, 0xa0fb5ba0UL, + 0x52f6a452UL, 0x3b4d763bUL, 0xd661b7d6UL, 0xb3ce7db3UL, + 0x297b5229UL, 0xe33edde3UL, 0x2f715e2fUL, 0x84971384UL, + 0x53f5a653UL, 0xd168b9d1UL, 0x00000000UL, 0xed2cc1edUL, + 0x20604020UL, 0xfc1fe3fcUL, 0xb1c879b1UL, 0x5bedb65bUL, + 0x6abed46aUL, 0xcb468dcbUL, 0xbed967beUL, 0x394b7239UL, + 0x4ade944aUL, 0x4cd4984cUL, 0x58e8b058UL, 0xcf4a85cfUL, + 0xd06bbbd0UL, 0xef2ac5efUL, 0xaae54faaUL, 0xfb16edfbUL, + 0x43c58643UL, 0x4dd79a4dUL, 0x33556633UL, 0x85941185UL, + 0x45cf8a45UL, 0xf910e9f9UL, 0x02060402UL, 0x7f81fe7fUL, + 0x50f0a050UL, 0x3c44783cUL, 0x9fba259fUL, 0xa8e34ba8UL, + 0x51f3a251UL, 0xa3fe5da3UL, 0x40c08040UL, 0x8f8a058fUL, + 0x92ad3f92UL, 0x9dbc219dUL, 0x38487038UL, 0xf504f1f5UL, + 0xbcdf63bcUL, 0xb6c177b6UL, 0xda75afdaUL, 0x21634221UL, + 0x10302010UL, 0xff1ae5ffUL, 0xf30efdf3UL, 0xd26dbfd2UL, + 0xcd4c81cdUL, 0x0c14180cUL, 0x13352613UL, 0xec2fc3ecUL, + 0x5fe1be5fUL, 0x97a23597UL, 0x44cc8844UL, 0x17392e17UL, + 0xc45793c4UL, 0xa7f255a7UL, 0x7e82fc7eUL, 0x3d477a3dUL, + 0x64acc864UL, 0x5de7ba5dUL, 0x192b3219UL, 0x7395e673UL, + 0x60a0c060UL, 0x81981981UL, 0x4fd19e4fUL, 0xdc7fa3dcUL, + 0x22664422UL, 0x2a7e542aUL, 0x90ab3b90UL, 0x88830b88UL, + 0x46ca8c46UL, 0xee29c7eeUL, 0xb8d36bb8UL, 0x143c2814UL, + 0xde79a7deUL, 0x5ee2bc5eUL, 0x0b1d160bUL, 0xdb76addbUL, + 0xe03bdbe0UL, 0x32566432UL, 0x3a4e743aUL, 0x0a1e140aUL, + 0x49db9249UL, 0x060a0c06UL, 0x246c4824UL, 0x5ce4b85cUL, + 0xc25d9fc2UL, 0xd36ebdd3UL, 0xacef43acUL, 0x62a6c462UL, + 0x91a83991UL, 0x95a43195UL, 0xe437d3e4UL, 0x798bf279UL, + 0xe732d5e7UL, 0xc8438bc8UL, 0x37596e37UL, 0x6db7da6dUL, + 0x8d8c018dUL, 0xd564b1d5UL, 0x4ed29c4eUL, 0xa9e049a9UL, + 0x6cb4d86cUL, 0x56faac56UL, 0xf407f3f4UL, 0xea25cfeaUL, + 0x65afca65UL, 0x7a8ef47aUL, 0xaee947aeUL, 0x08181008UL, + 0xbad56fbaUL, 0x7888f078UL, 0x256f4a25UL, 0x2e725c2eUL, + 0x1c24381cUL, 0xa6f157a6UL, 0xb4c773b4UL, 0xc65197c6UL, + 0xe823cbe8UL, 0xdd7ca1ddUL, 0x749ce874UL, 0x1f213e1fUL, + 0x4bdd964bUL, 0xbddc61bdUL, 0x8b860d8bUL, 0x8a850f8aUL, + 0x7090e070UL, 0x3e427c3eUL, 0xb5c471b5UL, 0x66aacc66UL, + 0x48d89048UL, 0x03050603UL, 0xf601f7f6UL, 0x0e121c0eUL, + 0x61a3c261UL, 0x355f6a35UL, 0x57f9ae57UL, 0xb9d069b9UL, + 0x86911786UL, 0xc15899c1UL, 0x1d273a1dUL, 0x9eb9279eUL, + 0xe138d9e1UL, 0xf813ebf8UL, 0x98b32b98UL, 0x11332211UL, + 0x69bbd269UL, 0xd970a9d9UL, 0x8e89078eUL, 0x94a73394UL, + 0x9bb62d9bUL, 0x1e223c1eUL, 0x87921587UL, 0xe920c9e9UL, + 0xce4987ceUL, 0x55ffaa55UL, 0x28785028UL, 0xdf7aa5dfUL, + 0x8c8f038cUL, 0xa1f859a1UL, 0x89800989UL, 0x0d171a0dUL, + 0xbfda65bfUL, 0xe631d7e6UL, 0x42c68442UL, 0x68b8d068UL, + 0x41c38241UL, 0x99b02999UL, 0x2d775a2dUL, 0x0f111e0fUL, + 0xb0cb7bb0UL, 0x54fca854UL, 0xbbd66dbbUL, 0x163a2c16UL, +}; +static const unsigned int Te3[256] = { + 0x6363a5c6UL, 0x7c7c84f8UL, 0x777799eeUL, 0x7b7b8df6UL, + 0xf2f20dffUL, 0x6b6bbdd6UL, 0x6f6fb1deUL, 0xc5c55491UL, + 0x30305060UL, 0x01010302UL, 0x6767a9ceUL, 0x2b2b7d56UL, + 0xfefe19e7UL, 0xd7d762b5UL, 0xababe64dUL, 0x76769aecUL, + 0xcaca458fUL, 0x82829d1fUL, 0xc9c94089UL, 0x7d7d87faUL, + 0xfafa15efUL, 0x5959ebb2UL, 0x4747c98eUL, 0xf0f00bfbUL, + 0xadadec41UL, 0xd4d467b3UL, 0xa2a2fd5fUL, 0xafafea45UL, + 0x9c9cbf23UL, 0xa4a4f753UL, 0x727296e4UL, 0xc0c05b9bUL, + 0xb7b7c275UL, 0xfdfd1ce1UL, 0x9393ae3dUL, 0x26266a4cUL, + 0x36365a6cUL, 0x3f3f417eUL, 0xf7f702f5UL, 0xcccc4f83UL, + 0x34345c68UL, 0xa5a5f451UL, 0xe5e534d1UL, 0xf1f108f9UL, + 0x717193e2UL, 0xd8d873abUL, 0x31315362UL, 0x15153f2aUL, + 0x04040c08UL, 0xc7c75295UL, 0x23236546UL, 0xc3c35e9dUL, + 0x18182830UL, 0x9696a137UL, 0x05050f0aUL, 0x9a9ab52fUL, + 0x0707090eUL, 0x12123624UL, 0x80809b1bUL, 0xe2e23ddfUL, + 0xebeb26cdUL, 0x2727694eUL, 0xb2b2cd7fUL, 0x75759feaUL, + 0x09091b12UL, 0x83839e1dUL, 0x2c2c7458UL, 0x1a1a2e34UL, + 0x1b1b2d36UL, 0x6e6eb2dcUL, 0x5a5aeeb4UL, 0xa0a0fb5bUL, + 0x5252f6a4UL, 0x3b3b4d76UL, 0xd6d661b7UL, 0xb3b3ce7dUL, + 0x29297b52UL, 0xe3e33eddUL, 0x2f2f715eUL, 0x84849713UL, + 0x5353f5a6UL, 0xd1d168b9UL, 0x00000000UL, 0xeded2cc1UL, + 0x20206040UL, 0xfcfc1fe3UL, 0xb1b1c879UL, 0x5b5bedb6UL, + 0x6a6abed4UL, 0xcbcb468dUL, 0xbebed967UL, 0x39394b72UL, + 0x4a4ade94UL, 0x4c4cd498UL, 0x5858e8b0UL, 0xcfcf4a85UL, + 0xd0d06bbbUL, 0xefef2ac5UL, 0xaaaae54fUL, 0xfbfb16edUL, + 0x4343c586UL, 0x4d4dd79aUL, 0x33335566UL, 0x85859411UL, + 0x4545cf8aUL, 0xf9f910e9UL, 0x02020604UL, 0x7f7f81feUL, + 0x5050f0a0UL, 0x3c3c4478UL, 0x9f9fba25UL, 0xa8a8e34bUL, + 0x5151f3a2UL, 0xa3a3fe5dUL, 0x4040c080UL, 0x8f8f8a05UL, + 0x9292ad3fUL, 0x9d9dbc21UL, 0x38384870UL, 0xf5f504f1UL, + 0xbcbcdf63UL, 0xb6b6c177UL, 0xdada75afUL, 0x21216342UL, + 0x10103020UL, 0xffff1ae5UL, 0xf3f30efdUL, 0xd2d26dbfUL, + 0xcdcd4c81UL, 0x0c0c1418UL, 0x13133526UL, 0xecec2fc3UL, + 0x5f5fe1beUL, 0x9797a235UL, 0x4444cc88UL, 0x1717392eUL, + 0xc4c45793UL, 0xa7a7f255UL, 0x7e7e82fcUL, 0x3d3d477aUL, + 0x6464acc8UL, 0x5d5de7baUL, 0x19192b32UL, 0x737395e6UL, + 0x6060a0c0UL, 0x81819819UL, 0x4f4fd19eUL, 0xdcdc7fa3UL, + 0x22226644UL, 0x2a2a7e54UL, 0x9090ab3bUL, 0x8888830bUL, + 0x4646ca8cUL, 0xeeee29c7UL, 0xb8b8d36bUL, 0x14143c28UL, + 0xdede79a7UL, 0x5e5ee2bcUL, 0x0b0b1d16UL, 0xdbdb76adUL, + 0xe0e03bdbUL, 0x32325664UL, 0x3a3a4e74UL, 0x0a0a1e14UL, + 0x4949db92UL, 0x06060a0cUL, 0x24246c48UL, 0x5c5ce4b8UL, + 0xc2c25d9fUL, 0xd3d36ebdUL, 0xacacef43UL, 0x6262a6c4UL, + 0x9191a839UL, 0x9595a431UL, 0xe4e437d3UL, 0x79798bf2UL, + 0xe7e732d5UL, 0xc8c8438bUL, 0x3737596eUL, 0x6d6db7daUL, + 0x8d8d8c01UL, 0xd5d564b1UL, 0x4e4ed29cUL, 0xa9a9e049UL, + 0x6c6cb4d8UL, 0x5656faacUL, 0xf4f407f3UL, 0xeaea25cfUL, + 0x6565afcaUL, 0x7a7a8ef4UL, 0xaeaee947UL, 0x08081810UL, + 0xbabad56fUL, 0x787888f0UL, 0x25256f4aUL, 0x2e2e725cUL, + 0x1c1c2438UL, 0xa6a6f157UL, 0xb4b4c773UL, 0xc6c65197UL, + 0xe8e823cbUL, 0xdddd7ca1UL, 0x74749ce8UL, 0x1f1f213eUL, + 0x4b4bdd96UL, 0xbdbddc61UL, 0x8b8b860dUL, 0x8a8a850fUL, + 0x707090e0UL, 0x3e3e427cUL, 0xb5b5c471UL, 0x6666aaccUL, + 0x4848d890UL, 0x03030506UL, 0xf6f601f7UL, 0x0e0e121cUL, + 0x6161a3c2UL, 0x35355f6aUL, 0x5757f9aeUL, 0xb9b9d069UL, + 0x86869117UL, 0xc1c15899UL, 0x1d1d273aUL, 0x9e9eb927UL, + 0xe1e138d9UL, 0xf8f813ebUL, 0x9898b32bUL, 0x11113322UL, + 0x6969bbd2UL, 0xd9d970a9UL, 0x8e8e8907UL, 0x9494a733UL, + 0x9b9bb62dUL, 0x1e1e223cUL, 0x87879215UL, 0xe9e920c9UL, + 0xcece4987UL, 0x5555ffaaUL, 0x28287850UL, 0xdfdf7aa5UL, + 0x8c8c8f03UL, 0xa1a1f859UL, 0x89898009UL, 0x0d0d171aUL, + 0xbfbfda65UL, 0xe6e631d7UL, 0x4242c684UL, 0x6868b8d0UL, + 0x4141c382UL, 0x9999b029UL, 0x2d2d775aUL, 0x0f0f111eUL, + 0xb0b0cb7bUL, 0x5454fca8UL, 0xbbbbd66dUL, 0x16163a2cUL, +}; +static const unsigned int Te4[256] = { + 0x63636363UL, 0x7c7c7c7cUL, 0x77777777UL, 0x7b7b7b7bUL, + 0xf2f2f2f2UL, 0x6b6b6b6bUL, 0x6f6f6f6fUL, 0xc5c5c5c5UL, + 0x30303030UL, 0x01010101UL, 0x67676767UL, 0x2b2b2b2bUL, + 0xfefefefeUL, 0xd7d7d7d7UL, 0xababababUL, 0x76767676UL, + 0xcacacacaUL, 0x82828282UL, 0xc9c9c9c9UL, 0x7d7d7d7dUL, + 0xfafafafaUL, 0x59595959UL, 0x47474747UL, 0xf0f0f0f0UL, + 0xadadadadUL, 0xd4d4d4d4UL, 0xa2a2a2a2UL, 0xafafafafUL, + 0x9c9c9c9cUL, 0xa4a4a4a4UL, 0x72727272UL, 0xc0c0c0c0UL, + 0xb7b7b7b7UL, 0xfdfdfdfdUL, 0x93939393UL, 0x26262626UL, + 0x36363636UL, 0x3f3f3f3fUL, 0xf7f7f7f7UL, 0xccccccccUL, + 0x34343434UL, 0xa5a5a5a5UL, 0xe5e5e5e5UL, 0xf1f1f1f1UL, + 0x71717171UL, 0xd8d8d8d8UL, 0x31313131UL, 0x15151515UL, + 0x04040404UL, 0xc7c7c7c7UL, 0x23232323UL, 0xc3c3c3c3UL, + 0x18181818UL, 0x96969696UL, 0x05050505UL, 0x9a9a9a9aUL, + 0x07070707UL, 0x12121212UL, 0x80808080UL, 0xe2e2e2e2UL, + 0xebebebebUL, 0x27272727UL, 0xb2b2b2b2UL, 0x75757575UL, + 0x09090909UL, 0x83838383UL, 0x2c2c2c2cUL, 0x1a1a1a1aUL, + 0x1b1b1b1bUL, 0x6e6e6e6eUL, 0x5a5a5a5aUL, 0xa0a0a0a0UL, + 0x52525252UL, 0x3b3b3b3bUL, 0xd6d6d6d6UL, 0xb3b3b3b3UL, + 0x29292929UL, 0xe3e3e3e3UL, 0x2f2f2f2fUL, 0x84848484UL, + 0x53535353UL, 0xd1d1d1d1UL, 0x00000000UL, 0xededededUL, + 0x20202020UL, 0xfcfcfcfcUL, 0xb1b1b1b1UL, 0x5b5b5b5bUL, + 0x6a6a6a6aUL, 0xcbcbcbcbUL, 0xbebebebeUL, 0x39393939UL, + 0x4a4a4a4aUL, 0x4c4c4c4cUL, 0x58585858UL, 0xcfcfcfcfUL, + 0xd0d0d0d0UL, 0xefefefefUL, 0xaaaaaaaaUL, 0xfbfbfbfbUL, + 0x43434343UL, 0x4d4d4d4dUL, 0x33333333UL, 0x85858585UL, + 0x45454545UL, 0xf9f9f9f9UL, 0x02020202UL, 0x7f7f7f7fUL, + 0x50505050UL, 0x3c3c3c3cUL, 0x9f9f9f9fUL, 0xa8a8a8a8UL, + 0x51515151UL, 0xa3a3a3a3UL, 0x40404040UL, 0x8f8f8f8fUL, + 0x92929292UL, 0x9d9d9d9dUL, 0x38383838UL, 0xf5f5f5f5UL, + 0xbcbcbcbcUL, 0xb6b6b6b6UL, 0xdadadadaUL, 0x21212121UL, + 0x10101010UL, 0xffffffffUL, 0xf3f3f3f3UL, 0xd2d2d2d2UL, + 0xcdcdcdcdUL, 0x0c0c0c0cUL, 0x13131313UL, 0xececececUL, + 0x5f5f5f5fUL, 0x97979797UL, 0x44444444UL, 0x17171717UL, + 0xc4c4c4c4UL, 0xa7a7a7a7UL, 0x7e7e7e7eUL, 0x3d3d3d3dUL, + 0x64646464UL, 0x5d5d5d5dUL, 0x19191919UL, 0x73737373UL, + 0x60606060UL, 0x81818181UL, 0x4f4f4f4fUL, 0xdcdcdcdcUL, + 0x22222222UL, 0x2a2a2a2aUL, 0x90909090UL, 0x88888888UL, + 0x46464646UL, 0xeeeeeeeeUL, 0xb8b8b8b8UL, 0x14141414UL, + 0xdedededeUL, 0x5e5e5e5eUL, 0x0b0b0b0bUL, 0xdbdbdbdbUL, + 0xe0e0e0e0UL, 0x32323232UL, 0x3a3a3a3aUL, 0x0a0a0a0aUL, + 0x49494949UL, 0x06060606UL, 0x24242424UL, 0x5c5c5c5cUL, + 0xc2c2c2c2UL, 0xd3d3d3d3UL, 0xacacacacUL, 0x62626262UL, + 0x91919191UL, 0x95959595UL, 0xe4e4e4e4UL, 0x79797979UL, + 0xe7e7e7e7UL, 0xc8c8c8c8UL, 0x37373737UL, 0x6d6d6d6dUL, + 0x8d8d8d8dUL, 0xd5d5d5d5UL, 0x4e4e4e4eUL, 0xa9a9a9a9UL, + 0x6c6c6c6cUL, 0x56565656UL, 0xf4f4f4f4UL, 0xeaeaeaeaUL, + 0x65656565UL, 0x7a7a7a7aUL, 0xaeaeaeaeUL, 0x08080808UL, + 0xbabababaUL, 0x78787878UL, 0x25252525UL, 0x2e2e2e2eUL, + 0x1c1c1c1cUL, 0xa6a6a6a6UL, 0xb4b4b4b4UL, 0xc6c6c6c6UL, + 0xe8e8e8e8UL, 0xddddddddUL, 0x74747474UL, 0x1f1f1f1fUL, + 0x4b4b4b4bUL, 0xbdbdbdbdUL, 0x8b8b8b8bUL, 0x8a8a8a8aUL, + 0x70707070UL, 0x3e3e3e3eUL, 0xb5b5b5b5UL, 0x66666666UL, + 0x48484848UL, 0x03030303UL, 0xf6f6f6f6UL, 0x0e0e0e0eUL, + 0x61616161UL, 0x35353535UL, 0x57575757UL, 0xb9b9b9b9UL, + 0x86868686UL, 0xc1c1c1c1UL, 0x1d1d1d1dUL, 0x9e9e9e9eUL, + 0xe1e1e1e1UL, 0xf8f8f8f8UL, 0x98989898UL, 0x11111111UL, + 0x69696969UL, 0xd9d9d9d9UL, 0x8e8e8e8eUL, 0x94949494UL, + 0x9b9b9b9bUL, 0x1e1e1e1eUL, 0x87878787UL, 0xe9e9e9e9UL, + 0xcecececeUL, 0x55555555UL, 0x28282828UL, 0xdfdfdfdfUL, + 0x8c8c8c8cUL, 0xa1a1a1a1UL, 0x89898989UL, 0x0d0d0d0dUL, + 0xbfbfbfbfUL, 0xe6e6e6e6UL, 0x42424242UL, 0x68686868UL, + 0x41414141UL, 0x99999999UL, 0x2d2d2d2dUL, 0x0f0f0f0fUL, + 0xb0b0b0b0UL, 0x54545454UL, 0xbbbbbbbbUL, 0x16161616UL, +}; +static const unsigned int Td0[256] = { + 0x51f4a750UL, 0x7e416553UL, 0x1a17a4c3UL, 0x3a275e96UL, + 0x3bab6bcbUL, 0x1f9d45f1UL, 0xacfa58abUL, 0x4be30393UL, + 0x2030fa55UL, 0xad766df6UL, 0x88cc7691UL, 0xf5024c25UL, + 0x4fe5d7fcUL, 0xc52acbd7UL, 0x26354480UL, 0xb562a38fUL, + 0xdeb15a49UL, 0x25ba1b67UL, 0x45ea0e98UL, 0x5dfec0e1UL, + 0xc32f7502UL, 0x814cf012UL, 0x8d4697a3UL, 0x6bd3f9c6UL, + 0x038f5fe7UL, 0x15929c95UL, 0xbf6d7aebUL, 0x955259daUL, + 0xd4be832dUL, 0x587421d3UL, 0x49e06929UL, 0x8ec9c844UL, + 0x75c2896aUL, 0xf48e7978UL, 0x99583e6bUL, 0x27b971ddUL, + 0xbee14fb6UL, 0xf088ad17UL, 0xc920ac66UL, 0x7dce3ab4UL, + 0x63df4a18UL, 0xe51a3182UL, 0x97513360UL, 0x62537f45UL, + 0xb16477e0UL, 0xbb6bae84UL, 0xfe81a01cUL, 0xf9082b94UL, + 0x70486858UL, 0x8f45fd19UL, 0x94de6c87UL, 0x527bf8b7UL, + 0xab73d323UL, 0x724b02e2UL, 0xe31f8f57UL, 0x6655ab2aUL, + 0xb2eb2807UL, 0x2fb5c203UL, 0x86c57b9aUL, 0xd33708a5UL, + 0x302887f2UL, 0x23bfa5b2UL, 0x02036abaUL, 0xed16825cUL, + 0x8acf1c2bUL, 0xa779b492UL, 0xf307f2f0UL, 0x4e69e2a1UL, + 0x65daf4cdUL, 0x0605bed5UL, 0xd134621fUL, 0xc4a6fe8aUL, + 0x342e539dUL, 0xa2f355a0UL, 0x058ae132UL, 0xa4f6eb75UL, + 0x0b83ec39UL, 0x4060efaaUL, 0x5e719f06UL, 0xbd6e1051UL, + 0x3e218af9UL, 0x96dd063dUL, 0xdd3e05aeUL, 0x4de6bd46UL, + 0x91548db5UL, 0x71c45d05UL, 0x0406d46fUL, 0x605015ffUL, + 0x1998fb24UL, 0xd6bde997UL, 0x894043ccUL, 0x67d99e77UL, + 0xb0e842bdUL, 0x07898b88UL, 0xe7195b38UL, 0x79c8eedbUL, + 0xa17c0a47UL, 0x7c420fe9UL, 0xf8841ec9UL, 0x00000000UL, + 0x09808683UL, 0x322bed48UL, 0x1e1170acUL, 0x6c5a724eUL, + 0xfd0efffbUL, 0x0f853856UL, 0x3daed51eUL, 0x362d3927UL, + 0x0a0fd964UL, 0x685ca621UL, 0x9b5b54d1UL, 0x24362e3aUL, + 0x0c0a67b1UL, 0x9357e70fUL, 0xb4ee96d2UL, 0x1b9b919eUL, + 0x80c0c54fUL, 0x61dc20a2UL, 0x5a774b69UL, 0x1c121a16UL, + 0xe293ba0aUL, 0xc0a02ae5UL, 0x3c22e043UL, 0x121b171dUL, + 0x0e090d0bUL, 0xf28bc7adUL, 0x2db6a8b9UL, 0x141ea9c8UL, + 0x57f11985UL, 0xaf75074cUL, 0xee99ddbbUL, 0xa37f60fdUL, + 0xf701269fUL, 0x5c72f5bcUL, 0x44663bc5UL, 0x5bfb7e34UL, + 0x8b432976UL, 0xcb23c6dcUL, 0xb6edfc68UL, 0xb8e4f163UL, + 0xd731dccaUL, 0x42638510UL, 0x13972240UL, 0x84c61120UL, + 0x854a247dUL, 0xd2bb3df8UL, 0xaef93211UL, 0xc729a16dUL, + 0x1d9e2f4bUL, 0xdcb230f3UL, 0x0d8652ecUL, 0x77c1e3d0UL, + 0x2bb3166cUL, 0xa970b999UL, 0x119448faUL, 0x47e96422UL, + 0xa8fc8cc4UL, 0xa0f03f1aUL, 0x567d2cd8UL, 0x223390efUL, + 0x87494ec7UL, 0xd938d1c1UL, 0x8ccaa2feUL, 0x98d40b36UL, + 0xa6f581cfUL, 0xa57ade28UL, 0xdab78e26UL, 0x3fadbfa4UL, + 0x2c3a9de4UL, 0x5078920dUL, 0x6a5fcc9bUL, 0x547e4662UL, + 0xf68d13c2UL, 0x90d8b8e8UL, 0x2e39f75eUL, 0x82c3aff5UL, + 0x9f5d80beUL, 0x69d0937cUL, 0x6fd52da9UL, 0xcf2512b3UL, + 0xc8ac993bUL, 0x10187da7UL, 0xe89c636eUL, 0xdb3bbb7bUL, + 0xcd267809UL, 0x6e5918f4UL, 0xec9ab701UL, 0x834f9aa8UL, + 0xe6956e65UL, 0xaaffe67eUL, 0x21bccf08UL, 0xef15e8e6UL, + 0xbae79bd9UL, 0x4a6f36ceUL, 0xea9f09d4UL, 0x29b07cd6UL, + 0x31a4b2afUL, 0x2a3f2331UL, 0xc6a59430UL, 0x35a266c0UL, + 0x744ebc37UL, 0xfc82caa6UL, 0xe090d0b0UL, 0x33a7d815UL, + 0xf104984aUL, 0x41ecdaf7UL, 0x7fcd500eUL, 0x1791f62fUL, + 0x764dd68dUL, 0x43efb04dUL, 0xccaa4d54UL, 0xe49604dfUL, + 0x9ed1b5e3UL, 0x4c6a881bUL, 0xc12c1fb8UL, 0x4665517fUL, + 0x9d5eea04UL, 0x018c355dUL, 0xfa877473UL, 0xfb0b412eUL, + 0xb3671d5aUL, 0x92dbd252UL, 0xe9105633UL, 0x6dd64713UL, + 0x9ad7618cUL, 0x37a10c7aUL, 0x59f8148eUL, 0xeb133c89UL, + 0xcea927eeUL, 0xb761c935UL, 0xe11ce5edUL, 0x7a47b13cUL, + 0x9cd2df59UL, 0x55f2733fUL, 0x1814ce79UL, 0x73c737bfUL, + 0x53f7cdeaUL, 0x5ffdaa5bUL, 0xdf3d6f14UL, 0x7844db86UL, + 0xcaaff381UL, 0xb968c43eUL, 0x3824342cUL, 0xc2a3405fUL, + 0x161dc372UL, 0xbce2250cUL, 0x283c498bUL, 0xff0d9541UL, + 0x39a80171UL, 0x080cb3deUL, 0xd8b4e49cUL, 0x6456c190UL, + 0x7bcb8461UL, 0xd532b670UL, 0x486c5c74UL, 0xd0b85742UL, +}; +static const unsigned int Td1[256] = { + 0x5051f4a7UL, 0x537e4165UL, 0xc31a17a4UL, 0x963a275eUL, + 0xcb3bab6bUL, 0xf11f9d45UL, 0xabacfa58UL, 0x934be303UL, + 0x552030faUL, 0xf6ad766dUL, 0x9188cc76UL, 0x25f5024cUL, + 0xfc4fe5d7UL, 0xd7c52acbUL, 0x80263544UL, 0x8fb562a3UL, + 0x49deb15aUL, 0x6725ba1bUL, 0x9845ea0eUL, 0xe15dfec0UL, + 0x02c32f75UL, 0x12814cf0UL, 0xa38d4697UL, 0xc66bd3f9UL, + 0xe7038f5fUL, 0x9515929cUL, 0xebbf6d7aUL, 0xda955259UL, + 0x2dd4be83UL, 0xd3587421UL, 0x2949e069UL, 0x448ec9c8UL, + 0x6a75c289UL, 0x78f48e79UL, 0x6b99583eUL, 0xdd27b971UL, + 0xb6bee14fUL, 0x17f088adUL, 0x66c920acUL, 0xb47dce3aUL, + 0x1863df4aUL, 0x82e51a31UL, 0x60975133UL, 0x4562537fUL, + 0xe0b16477UL, 0x84bb6baeUL, 0x1cfe81a0UL, 0x94f9082bUL, + 0x58704868UL, 0x198f45fdUL, 0x8794de6cUL, 0xb7527bf8UL, + 0x23ab73d3UL, 0xe2724b02UL, 0x57e31f8fUL, 0x2a6655abUL, + 0x07b2eb28UL, 0x032fb5c2UL, 0x9a86c57bUL, 0xa5d33708UL, + 0xf2302887UL, 0xb223bfa5UL, 0xba02036aUL, 0x5ced1682UL, + 0x2b8acf1cUL, 0x92a779b4UL, 0xf0f307f2UL, 0xa14e69e2UL, + 0xcd65daf4UL, 0xd50605beUL, 0x1fd13462UL, 0x8ac4a6feUL, + 0x9d342e53UL, 0xa0a2f355UL, 0x32058ae1UL, 0x75a4f6ebUL, + 0x390b83ecUL, 0xaa4060efUL, 0x065e719fUL, 0x51bd6e10UL, + 0xf93e218aUL, 0x3d96dd06UL, 0xaedd3e05UL, 0x464de6bdUL, + 0xb591548dUL, 0x0571c45dUL, 0x6f0406d4UL, 0xff605015UL, + 0x241998fbUL, 0x97d6bde9UL, 0xcc894043UL, 0x7767d99eUL, + 0xbdb0e842UL, 0x8807898bUL, 0x38e7195bUL, 0xdb79c8eeUL, + 0x47a17c0aUL, 0xe97c420fUL, 0xc9f8841eUL, 0x00000000UL, + 0x83098086UL, 0x48322bedUL, 0xac1e1170UL, 0x4e6c5a72UL, + 0xfbfd0effUL, 0x560f8538UL, 0x1e3daed5UL, 0x27362d39UL, + 0x640a0fd9UL, 0x21685ca6UL, 0xd19b5b54UL, 0x3a24362eUL, + 0xb10c0a67UL, 0x0f9357e7UL, 0xd2b4ee96UL, 0x9e1b9b91UL, + 0x4f80c0c5UL, 0xa261dc20UL, 0x695a774bUL, 0x161c121aUL, + 0x0ae293baUL, 0xe5c0a02aUL, 0x433c22e0UL, 0x1d121b17UL, + 0x0b0e090dUL, 0xadf28bc7UL, 0xb92db6a8UL, 0xc8141ea9UL, + 0x8557f119UL, 0x4caf7507UL, 0xbbee99ddUL, 0xfda37f60UL, + 0x9ff70126UL, 0xbc5c72f5UL, 0xc544663bUL, 0x345bfb7eUL, + 0x768b4329UL, 0xdccb23c6UL, 0x68b6edfcUL, 0x63b8e4f1UL, + 0xcad731dcUL, 0x10426385UL, 0x40139722UL, 0x2084c611UL, + 0x7d854a24UL, 0xf8d2bb3dUL, 0x11aef932UL, 0x6dc729a1UL, + 0x4b1d9e2fUL, 0xf3dcb230UL, 0xec0d8652UL, 0xd077c1e3UL, + 0x6c2bb316UL, 0x99a970b9UL, 0xfa119448UL, 0x2247e964UL, + 0xc4a8fc8cUL, 0x1aa0f03fUL, 0xd8567d2cUL, 0xef223390UL, + 0xc787494eUL, 0xc1d938d1UL, 0xfe8ccaa2UL, 0x3698d40bUL, + 0xcfa6f581UL, 0x28a57adeUL, 0x26dab78eUL, 0xa43fadbfUL, + 0xe42c3a9dUL, 0x0d507892UL, 0x9b6a5fccUL, 0x62547e46UL, + 0xc2f68d13UL, 0xe890d8b8UL, 0x5e2e39f7UL, 0xf582c3afUL, + 0xbe9f5d80UL, 0x7c69d093UL, 0xa96fd52dUL, 0xb3cf2512UL, + 0x3bc8ac99UL, 0xa710187dUL, 0x6ee89c63UL, 0x7bdb3bbbUL, + 0x09cd2678UL, 0xf46e5918UL, 0x01ec9ab7UL, 0xa8834f9aUL, + 0x65e6956eUL, 0x7eaaffe6UL, 0x0821bccfUL, 0xe6ef15e8UL, + 0xd9bae79bUL, 0xce4a6f36UL, 0xd4ea9f09UL, 0xd629b07cUL, + 0xaf31a4b2UL, 0x312a3f23UL, 0x30c6a594UL, 0xc035a266UL, + 0x37744ebcUL, 0xa6fc82caUL, 0xb0e090d0UL, 0x1533a7d8UL, + 0x4af10498UL, 0xf741ecdaUL, 0x0e7fcd50UL, 0x2f1791f6UL, + 0x8d764dd6UL, 0x4d43efb0UL, 0x54ccaa4dUL, 0xdfe49604UL, + 0xe39ed1b5UL, 0x1b4c6a88UL, 0xb8c12c1fUL, 0x7f466551UL, + 0x049d5eeaUL, 0x5d018c35UL, 0x73fa8774UL, 0x2efb0b41UL, + 0x5ab3671dUL, 0x5292dbd2UL, 0x33e91056UL, 0x136dd647UL, + 0x8c9ad761UL, 0x7a37a10cUL, 0x8e59f814UL, 0x89eb133cUL, + 0xeecea927UL, 0x35b761c9UL, 0xede11ce5UL, 0x3c7a47b1UL, + 0x599cd2dfUL, 0x3f55f273UL, 0x791814ceUL, 0xbf73c737UL, + 0xea53f7cdUL, 0x5b5ffdaaUL, 0x14df3d6fUL, 0x867844dbUL, + 0x81caaff3UL, 0x3eb968c4UL, 0x2c382434UL, 0x5fc2a340UL, + 0x72161dc3UL, 0x0cbce225UL, 0x8b283c49UL, 0x41ff0d95UL, + 0x7139a801UL, 0xde080cb3UL, 0x9cd8b4e4UL, 0x906456c1UL, + 0x617bcb84UL, 0x70d532b6UL, 0x74486c5cUL, 0x42d0b857UL, +}; +static const unsigned int Td2[256] = { + 0xa75051f4UL, 0x65537e41UL, 0xa4c31a17UL, 0x5e963a27UL, + 0x6bcb3babUL, 0x45f11f9dUL, 0x58abacfaUL, 0x03934be3UL, + 0xfa552030UL, 0x6df6ad76UL, 0x769188ccUL, 0x4c25f502UL, + 0xd7fc4fe5UL, 0xcbd7c52aUL, 0x44802635UL, 0xa38fb562UL, + 0x5a49deb1UL, 0x1b6725baUL, 0x0e9845eaUL, 0xc0e15dfeUL, + 0x7502c32fUL, 0xf012814cUL, 0x97a38d46UL, 0xf9c66bd3UL, + 0x5fe7038fUL, 0x9c951592UL, 0x7aebbf6dUL, 0x59da9552UL, + 0x832dd4beUL, 0x21d35874UL, 0x692949e0UL, 0xc8448ec9UL, + 0x896a75c2UL, 0x7978f48eUL, 0x3e6b9958UL, 0x71dd27b9UL, + 0x4fb6bee1UL, 0xad17f088UL, 0xac66c920UL, 0x3ab47dceUL, + 0x4a1863dfUL, 0x3182e51aUL, 0x33609751UL, 0x7f456253UL, + 0x77e0b164UL, 0xae84bb6bUL, 0xa01cfe81UL, 0x2b94f908UL, + 0x68587048UL, 0xfd198f45UL, 0x6c8794deUL, 0xf8b7527bUL, + 0xd323ab73UL, 0x02e2724bUL, 0x8f57e31fUL, 0xab2a6655UL, + 0x2807b2ebUL, 0xc2032fb5UL, 0x7b9a86c5UL, 0x08a5d337UL, + 0x87f23028UL, 0xa5b223bfUL, 0x6aba0203UL, 0x825ced16UL, + 0x1c2b8acfUL, 0xb492a779UL, 0xf2f0f307UL, 0xe2a14e69UL, + 0xf4cd65daUL, 0xbed50605UL, 0x621fd134UL, 0xfe8ac4a6UL, + 0x539d342eUL, 0x55a0a2f3UL, 0xe132058aUL, 0xeb75a4f6UL, + 0xec390b83UL, 0xefaa4060UL, 0x9f065e71UL, 0x1051bd6eUL, + 0x8af93e21UL, 0x063d96ddUL, 0x05aedd3eUL, 0xbd464de6UL, + 0x8db59154UL, 0x5d0571c4UL, 0xd46f0406UL, 0x15ff6050UL, + 0xfb241998UL, 0xe997d6bdUL, 0x43cc8940UL, 0x9e7767d9UL, + 0x42bdb0e8UL, 0x8b880789UL, 0x5b38e719UL, 0xeedb79c8UL, + 0x0a47a17cUL, 0x0fe97c42UL, 0x1ec9f884UL, 0x00000000UL, + 0x86830980UL, 0xed48322bUL, 0x70ac1e11UL, 0x724e6c5aUL, + 0xfffbfd0eUL, 0x38560f85UL, 0xd51e3daeUL, 0x3927362dUL, + 0xd9640a0fUL, 0xa621685cUL, 0x54d19b5bUL, 0x2e3a2436UL, + 0x67b10c0aUL, 0xe70f9357UL, 0x96d2b4eeUL, 0x919e1b9bUL, + 0xc54f80c0UL, 0x20a261dcUL, 0x4b695a77UL, 0x1a161c12UL, + 0xba0ae293UL, 0x2ae5c0a0UL, 0xe0433c22UL, 0x171d121bUL, + 0x0d0b0e09UL, 0xc7adf28bUL, 0xa8b92db6UL, 0xa9c8141eUL, + 0x198557f1UL, 0x074caf75UL, 0xddbbee99UL, 0x60fda37fUL, + 0x269ff701UL, 0xf5bc5c72UL, 0x3bc54466UL, 0x7e345bfbUL, + 0x29768b43UL, 0xc6dccb23UL, 0xfc68b6edUL, 0xf163b8e4UL, + 0xdccad731UL, 0x85104263UL, 0x22401397UL, 0x112084c6UL, + 0x247d854aUL, 0x3df8d2bbUL, 0x3211aef9UL, 0xa16dc729UL, + 0x2f4b1d9eUL, 0x30f3dcb2UL, 0x52ec0d86UL, 0xe3d077c1UL, + 0x166c2bb3UL, 0xb999a970UL, 0x48fa1194UL, 0x642247e9UL, + 0x8cc4a8fcUL, 0x3f1aa0f0UL, 0x2cd8567dUL, 0x90ef2233UL, + 0x4ec78749UL, 0xd1c1d938UL, 0xa2fe8ccaUL, 0x0b3698d4UL, + 0x81cfa6f5UL, 0xde28a57aUL, 0x8e26dab7UL, 0xbfa43fadUL, + 0x9de42c3aUL, 0x920d5078UL, 0xcc9b6a5fUL, 0x4662547eUL, + 0x13c2f68dUL, 0xb8e890d8UL, 0xf75e2e39UL, 0xaff582c3UL, + 0x80be9f5dUL, 0x937c69d0UL, 0x2da96fd5UL, 0x12b3cf25UL, + 0x993bc8acUL, 0x7da71018UL, 0x636ee89cUL, 0xbb7bdb3bUL, + 0x7809cd26UL, 0x18f46e59UL, 0xb701ec9aUL, 0x9aa8834fUL, + 0x6e65e695UL, 0xe67eaaffUL, 0xcf0821bcUL, 0xe8e6ef15UL, + 0x9bd9bae7UL, 0x36ce4a6fUL, 0x09d4ea9fUL, 0x7cd629b0UL, + 0xb2af31a4UL, 0x23312a3fUL, 0x9430c6a5UL, 0x66c035a2UL, + 0xbc37744eUL, 0xcaa6fc82UL, 0xd0b0e090UL, 0xd81533a7UL, + 0x984af104UL, 0xdaf741ecUL, 0x500e7fcdUL, 0xf62f1791UL, + 0xd68d764dUL, 0xb04d43efUL, 0x4d54ccaaUL, 0x04dfe496UL, + 0xb5e39ed1UL, 0x881b4c6aUL, 0x1fb8c12cUL, 0x517f4665UL, + 0xea049d5eUL, 0x355d018cUL, 0x7473fa87UL, 0x412efb0bUL, + 0x1d5ab367UL, 0xd25292dbUL, 0x5633e910UL, 0x47136dd6UL, + 0x618c9ad7UL, 0x0c7a37a1UL, 0x148e59f8UL, 0x3c89eb13UL, + 0x27eecea9UL, 0xc935b761UL, 0xe5ede11cUL, 0xb13c7a47UL, + 0xdf599cd2UL, 0x733f55f2UL, 0xce791814UL, 0x37bf73c7UL, + 0xcdea53f7UL, 0xaa5b5ffdUL, 0x6f14df3dUL, 0xdb867844UL, + 0xf381caafUL, 0xc43eb968UL, 0x342c3824UL, 0x405fc2a3UL, + 0xc372161dUL, 0x250cbce2UL, 0x498b283cUL, 0x9541ff0dUL, + 0x017139a8UL, 0xb3de080cUL, 0xe49cd8b4UL, 0xc1906456UL, + 0x84617bcbUL, 0xb670d532UL, 0x5c74486cUL, 0x5742d0b8UL, +}; +static const unsigned int Td3[256] = { + 0xf4a75051UL, 0x4165537eUL, 0x17a4c31aUL, 0x275e963aUL, + 0xab6bcb3bUL, 0x9d45f11fUL, 0xfa58abacUL, 0xe303934bUL, + 0x30fa5520UL, 0x766df6adUL, 0xcc769188UL, 0x024c25f5UL, + 0xe5d7fc4fUL, 0x2acbd7c5UL, 0x35448026UL, 0x62a38fb5UL, + 0xb15a49deUL, 0xba1b6725UL, 0xea0e9845UL, 0xfec0e15dUL, + 0x2f7502c3UL, 0x4cf01281UL, 0x4697a38dUL, 0xd3f9c66bUL, + 0x8f5fe703UL, 0x929c9515UL, 0x6d7aebbfUL, 0x5259da95UL, + 0xbe832dd4UL, 0x7421d358UL, 0xe0692949UL, 0xc9c8448eUL, + 0xc2896a75UL, 0x8e7978f4UL, 0x583e6b99UL, 0xb971dd27UL, + 0xe14fb6beUL, 0x88ad17f0UL, 0x20ac66c9UL, 0xce3ab47dUL, + 0xdf4a1863UL, 0x1a3182e5UL, 0x51336097UL, 0x537f4562UL, + 0x6477e0b1UL, 0x6bae84bbUL, 0x81a01cfeUL, 0x082b94f9UL, + 0x48685870UL, 0x45fd198fUL, 0xde6c8794UL, 0x7bf8b752UL, + 0x73d323abUL, 0x4b02e272UL, 0x1f8f57e3UL, 0x55ab2a66UL, + 0xeb2807b2UL, 0xb5c2032fUL, 0xc57b9a86UL, 0x3708a5d3UL, + 0x2887f230UL, 0xbfa5b223UL, 0x036aba02UL, 0x16825cedUL, + 0xcf1c2b8aUL, 0x79b492a7UL, 0x07f2f0f3UL, 0x69e2a14eUL, + 0xdaf4cd65UL, 0x05bed506UL, 0x34621fd1UL, 0xa6fe8ac4UL, + 0x2e539d34UL, 0xf355a0a2UL, 0x8ae13205UL, 0xf6eb75a4UL, + 0x83ec390bUL, 0x60efaa40UL, 0x719f065eUL, 0x6e1051bdUL, + 0x218af93eUL, 0xdd063d96UL, 0x3e05aeddUL, 0xe6bd464dUL, + 0x548db591UL, 0xc45d0571UL, 0x06d46f04UL, 0x5015ff60UL, + 0x98fb2419UL, 0xbde997d6UL, 0x4043cc89UL, 0xd99e7767UL, + 0xe842bdb0UL, 0x898b8807UL, 0x195b38e7UL, 0xc8eedb79UL, + 0x7c0a47a1UL, 0x420fe97cUL, 0x841ec9f8UL, 0x00000000UL, + 0x80868309UL, 0x2bed4832UL, 0x1170ac1eUL, 0x5a724e6cUL, + 0x0efffbfdUL, 0x8538560fUL, 0xaed51e3dUL, 0x2d392736UL, + 0x0fd9640aUL, 0x5ca62168UL, 0x5b54d19bUL, 0x362e3a24UL, + 0x0a67b10cUL, 0x57e70f93UL, 0xee96d2b4UL, 0x9b919e1bUL, + 0xc0c54f80UL, 0xdc20a261UL, 0x774b695aUL, 0x121a161cUL, + 0x93ba0ae2UL, 0xa02ae5c0UL, 0x22e0433cUL, 0x1b171d12UL, + 0x090d0b0eUL, 0x8bc7adf2UL, 0xb6a8b92dUL, 0x1ea9c814UL, + 0xf1198557UL, 0x75074cafUL, 0x99ddbbeeUL, 0x7f60fda3UL, + 0x01269ff7UL, 0x72f5bc5cUL, 0x663bc544UL, 0xfb7e345bUL, + 0x4329768bUL, 0x23c6dccbUL, 0xedfc68b6UL, 0xe4f163b8UL, + 0x31dccad7UL, 0x63851042UL, 0x97224013UL, 0xc6112084UL, + 0x4a247d85UL, 0xbb3df8d2UL, 0xf93211aeUL, 0x29a16dc7UL, + 0x9e2f4b1dUL, 0xb230f3dcUL, 0x8652ec0dUL, 0xc1e3d077UL, + 0xb3166c2bUL, 0x70b999a9UL, 0x9448fa11UL, 0xe9642247UL, + 0xfc8cc4a8UL, 0xf03f1aa0UL, 0x7d2cd856UL, 0x3390ef22UL, + 0x494ec787UL, 0x38d1c1d9UL, 0xcaa2fe8cUL, 0xd40b3698UL, + 0xf581cfa6UL, 0x7ade28a5UL, 0xb78e26daUL, 0xadbfa43fUL, + 0x3a9de42cUL, 0x78920d50UL, 0x5fcc9b6aUL, 0x7e466254UL, + 0x8d13c2f6UL, 0xd8b8e890UL, 0x39f75e2eUL, 0xc3aff582UL, + 0x5d80be9fUL, 0xd0937c69UL, 0xd52da96fUL, 0x2512b3cfUL, + 0xac993bc8UL, 0x187da710UL, 0x9c636ee8UL, 0x3bbb7bdbUL, + 0x267809cdUL, 0x5918f46eUL, 0x9ab701ecUL, 0x4f9aa883UL, + 0x956e65e6UL, 0xffe67eaaUL, 0xbccf0821UL, 0x15e8e6efUL, + 0xe79bd9baUL, 0x6f36ce4aUL, 0x9f09d4eaUL, 0xb07cd629UL, + 0xa4b2af31UL, 0x3f23312aUL, 0xa59430c6UL, 0xa266c035UL, + 0x4ebc3774UL, 0x82caa6fcUL, 0x90d0b0e0UL, 0xa7d81533UL, + 0x04984af1UL, 0xecdaf741UL, 0xcd500e7fUL, 0x91f62f17UL, + 0x4dd68d76UL, 0xefb04d43UL, 0xaa4d54ccUL, 0x9604dfe4UL, + 0xd1b5e39eUL, 0x6a881b4cUL, 0x2c1fb8c1UL, 0x65517f46UL, + 0x5eea049dUL, 0x8c355d01UL, 0x877473faUL, 0x0b412efbUL, + 0x671d5ab3UL, 0xdbd25292UL, 0x105633e9UL, 0xd647136dUL, + 0xd7618c9aUL, 0xa10c7a37UL, 0xf8148e59UL, 0x133c89ebUL, + 0xa927eeceUL, 0x61c935b7UL, 0x1ce5ede1UL, 0x47b13c7aUL, + 0xd2df599cUL, 0xf2733f55UL, 0x14ce7918UL, 0xc737bf73UL, + 0xf7cdea53UL, 0xfdaa5b5fUL, 0x3d6f14dfUL, 0x44db8678UL, + 0xaff381caUL, 0x68c43eb9UL, 0x24342c38UL, 0xa3405fc2UL, + 0x1dc37216UL, 0xe2250cbcUL, 0x3c498b28UL, 0x0d9541ffUL, + 0xa8017139UL, 0x0cb3de08UL, 0xb4e49cd8UL, 0x56c19064UL, + 0xcb84617bUL, 0x32b670d5UL, 0x6c5c7448UL, 0xb85742d0UL, +}; +static const unsigned int Td4[256] = { + 0x52525252UL, 0x09090909UL, 0x6a6a6a6aUL, 0xd5d5d5d5UL, + 0x30303030UL, 0x36363636UL, 0xa5a5a5a5UL, 0x38383838UL, + 0xbfbfbfbfUL, 0x40404040UL, 0xa3a3a3a3UL, 0x9e9e9e9eUL, + 0x81818181UL, 0xf3f3f3f3UL, 0xd7d7d7d7UL, 0xfbfbfbfbUL, + 0x7c7c7c7cUL, 0xe3e3e3e3UL, 0x39393939UL, 0x82828282UL, + 0x9b9b9b9bUL, 0x2f2f2f2fUL, 0xffffffffUL, 0x87878787UL, + 0x34343434UL, 0x8e8e8e8eUL, 0x43434343UL, 0x44444444UL, + 0xc4c4c4c4UL, 0xdedededeUL, 0xe9e9e9e9UL, 0xcbcbcbcbUL, + 0x54545454UL, 0x7b7b7b7bUL, 0x94949494UL, 0x32323232UL, + 0xa6a6a6a6UL, 0xc2c2c2c2UL, 0x23232323UL, 0x3d3d3d3dUL, + 0xeeeeeeeeUL, 0x4c4c4c4cUL, 0x95959595UL, 0x0b0b0b0bUL, + 0x42424242UL, 0xfafafafaUL, 0xc3c3c3c3UL, 0x4e4e4e4eUL, + 0x08080808UL, 0x2e2e2e2eUL, 0xa1a1a1a1UL, 0x66666666UL, + 0x28282828UL, 0xd9d9d9d9UL, 0x24242424UL, 0xb2b2b2b2UL, + 0x76767676UL, 0x5b5b5b5bUL, 0xa2a2a2a2UL, 0x49494949UL, + 0x6d6d6d6dUL, 0x8b8b8b8bUL, 0xd1d1d1d1UL, 0x25252525UL, + 0x72727272UL, 0xf8f8f8f8UL, 0xf6f6f6f6UL, 0x64646464UL, + 0x86868686UL, 0x68686868UL, 0x98989898UL, 0x16161616UL, + 0xd4d4d4d4UL, 0xa4a4a4a4UL, 0x5c5c5c5cUL, 0xccccccccUL, + 0x5d5d5d5dUL, 0x65656565UL, 0xb6b6b6b6UL, 0x92929292UL, + 0x6c6c6c6cUL, 0x70707070UL, 0x48484848UL, 0x50505050UL, + 0xfdfdfdfdUL, 0xededededUL, 0xb9b9b9b9UL, 0xdadadadaUL, + 0x5e5e5e5eUL, 0x15151515UL, 0x46464646UL, 0x57575757UL, + 0xa7a7a7a7UL, 0x8d8d8d8dUL, 0x9d9d9d9dUL, 0x84848484UL, + 0x90909090UL, 0xd8d8d8d8UL, 0xababababUL, 0x00000000UL, + 0x8c8c8c8cUL, 0xbcbcbcbcUL, 0xd3d3d3d3UL, 0x0a0a0a0aUL, + 0xf7f7f7f7UL, 0xe4e4e4e4UL, 0x58585858UL, 0x05050505UL, + 0xb8b8b8b8UL, 0xb3b3b3b3UL, 0x45454545UL, 0x06060606UL, + 0xd0d0d0d0UL, 0x2c2c2c2cUL, 0x1e1e1e1eUL, 0x8f8f8f8fUL, + 0xcacacacaUL, 0x3f3f3f3fUL, 0x0f0f0f0fUL, 0x02020202UL, + 0xc1c1c1c1UL, 0xafafafafUL, 0xbdbdbdbdUL, 0x03030303UL, + 0x01010101UL, 0x13131313UL, 0x8a8a8a8aUL, 0x6b6b6b6bUL, + 0x3a3a3a3aUL, 0x91919191UL, 0x11111111UL, 0x41414141UL, + 0x4f4f4f4fUL, 0x67676767UL, 0xdcdcdcdcUL, 0xeaeaeaeaUL, + 0x97979797UL, 0xf2f2f2f2UL, 0xcfcfcfcfUL, 0xcecececeUL, + 0xf0f0f0f0UL, 0xb4b4b4b4UL, 0xe6e6e6e6UL, 0x73737373UL, + 0x96969696UL, 0xacacacacUL, 0x74747474UL, 0x22222222UL, + 0xe7e7e7e7UL, 0xadadadadUL, 0x35353535UL, 0x85858585UL, + 0xe2e2e2e2UL, 0xf9f9f9f9UL, 0x37373737UL, 0xe8e8e8e8UL, + 0x1c1c1c1cUL, 0x75757575UL, 0xdfdfdfdfUL, 0x6e6e6e6eUL, + 0x47474747UL, 0xf1f1f1f1UL, 0x1a1a1a1aUL, 0x71717171UL, + 0x1d1d1d1dUL, 0x29292929UL, 0xc5c5c5c5UL, 0x89898989UL, + 0x6f6f6f6fUL, 0xb7b7b7b7UL, 0x62626262UL, 0x0e0e0e0eUL, + 0xaaaaaaaaUL, 0x18181818UL, 0xbebebebeUL, 0x1b1b1b1bUL, + 0xfcfcfcfcUL, 0x56565656UL, 0x3e3e3e3eUL, 0x4b4b4b4bUL, + 0xc6c6c6c6UL, 0xd2d2d2d2UL, 0x79797979UL, 0x20202020UL, + 0x9a9a9a9aUL, 0xdbdbdbdbUL, 0xc0c0c0c0UL, 0xfefefefeUL, + 0x78787878UL, 0xcdcdcdcdUL, 0x5a5a5a5aUL, 0xf4f4f4f4UL, + 0x1f1f1f1fUL, 0xddddddddUL, 0xa8a8a8a8UL, 0x33333333UL, + 0x88888888UL, 0x07070707UL, 0xc7c7c7c7UL, 0x31313131UL, + 0xb1b1b1b1UL, 0x12121212UL, 0x10101010UL, 0x59595959UL, + 0x27272727UL, 0x80808080UL, 0xececececUL, 0x5f5f5f5fUL, + 0x60606060UL, 0x51515151UL, 0x7f7f7f7fUL, 0xa9a9a9a9UL, + 0x19191919UL, 0xb5b5b5b5UL, 0x4a4a4a4aUL, 0x0d0d0d0dUL, + 0x2d2d2d2dUL, 0xe5e5e5e5UL, 0x7a7a7a7aUL, 0x9f9f9f9fUL, + 0x93939393UL, 0xc9c9c9c9UL, 0x9c9c9c9cUL, 0xefefefefUL, + 0xa0a0a0a0UL, 0xe0e0e0e0UL, 0x3b3b3b3bUL, 0x4d4d4d4dUL, + 0xaeaeaeaeUL, 0x2a2a2a2aUL, 0xf5f5f5f5UL, 0xb0b0b0b0UL, + 0xc8c8c8c8UL, 0xebebebebUL, 0xbbbbbbbbUL, 0x3c3c3c3cUL, + 0x83838383UL, 0x53535353UL, 0x99999999UL, 0x61616161UL, + 0x17171717UL, 0x2b2b2b2bUL, 0x04040404UL, 0x7e7e7e7eUL, + 0xbabababaUL, 0x77777777UL, 0xd6d6d6d6UL, 0x26262626UL, + 0xe1e1e1e1UL, 0x69696969UL, 0x14141414UL, 0x63636363UL, + 0x55555555UL, 0x21212121UL, 0x0c0c0c0cUL, 0x7d7d7d7dUL, +}; +static const unsigned int rcon[] = { + 0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, + 0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL, + 0x1B000000UL, 0x36000000UL, +}; + +#define GETU32(pt) (((unsigned int)(pt)[0] << 24) ^ \ + ((unsigned int)(pt)[1] << 16) ^ \ + ((unsigned int)(pt)[2] << 8) ^ \ + ((unsigned int)(pt)[3])) + +#define PUTU32(ct, st) { (ct)[0] = (unsigned char)((st) >> 24); \ + (ct)[1] = (unsigned char)((st) >> 16); \ + (ct)[2] = (unsigned char)((st) >> 8); \ + (ct)[3] = (unsigned char)(st); } + +/* +* Expand the cipher key into the encryption key schedule and return the +* number of rounds for the given cipher key size. +*/ +int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBytes) +{ + int i = 0; + unsigned int temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + if (keyBytes == 16) { // 128 bits + for (;;) { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + return 10; + } + rk += 4; + } + } + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + if (keyBytes == 24) { // 192 bits + for (;;) { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) { + return 12; + } + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + } + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + if (keyBytes == 32) { // 256 bits + for (;;) { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ + (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ + (Te4[(temp ) & 0xff] & 0x0000ff00) ^ + (Te4[(temp >> 24) ] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) { + return 14; + } + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te4[(temp >> 24) ] & 0xff000000) ^ + (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(temp ) & 0xff] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + } + return 0; +} + +/* +* Expand the cipher key into encryption and decryption key schedule and +* return the number of rounds for the given cipher key size. +*/ +int AesGenKeySched(unsigned int rk[], unsigned int rrk[], const unsigned char cipherKey[], int keyBytes) +{ + int Nr, i; + + // expand the cipher key + Nr = aes_setkey_enc(rk, cipherKey, keyBytes); + // invert the order of the first round keys + rrk += Nr * 4; + rrk[0] = rk[0]; + rrk[1] = rk[1]; + rrk[2] = rk[2]; + rrk[3] = rk[3]; + + /* + * apply the inverse MixColumn transform to all round keys but the first + * and the last + */ + for (i = 1; i < Nr; i++) { + rrk -= 4; + rk += 4; + rrk[0] = + Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[0] ) & 0xff] & 0xff]; + rrk[1] = + Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[1] ) & 0xff] & 0xff]; + rrk[2] = + Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[2] ) & 0xff] & 0xff]; + rrk[3] = + Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ + Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ + Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ + Td3[Te4[(rk[3] ) & 0xff] & 0xff]; + } + // invert the order of the last round keys + rrk -= 4; + rk += 4; + rrk[0] = rk[0]; + rrk[1] = rk[1]; + rrk[2] = rk[2]; + rrk[3] = rk[3]; + + return Nr; +} + +/* +* Encrypt the plain text into cipher +*/ +void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[]) +{ + unsigned int s0, s1, s2, s3, t0, t1, t2, t3, *iv; + const unsigned int *rk; + int r; + + rk = pCtx->Ek; + iv = pCtx->Iv; + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; + if (pCtx->Mode) { + s0 = s0 ^ iv[0]; + s1 = s1 ^ iv[1]; + s2 = s2 ^ iv[2]; + s3 = s3 ^ iv[3]; + } + /* + * Nr - 1 full rounds: + */ + r = pCtx->Nr >> 1; + for (;;) { + t0 = + Te0[(s0 >> 24) ] ^ + Te1[(s1 >> 16) & 0xff] ^ + Te2[(s2 >> 8) & 0xff] ^ + Te3[(s3 ) & 0xff] ^ + rk[4]; + t1 = + Te0[(s1 >> 24) ] ^ + Te1[(s2 >> 16) & 0xff] ^ + Te2[(s3 >> 8) & 0xff] ^ + Te3[(s0 ) & 0xff] ^ + rk[5]; + t2 = + Te0[(s2 >> 24) ] ^ + Te1[(s3 >> 16) & 0xff] ^ + Te2[(s0 >> 8) & 0xff] ^ + Te3[(s1 ) & 0xff] ^ + rk[6]; + t3 = + Te0[(s3 >> 24) ] ^ + Te1[(s0 >> 16) & 0xff] ^ + Te2[(s1 >> 8) & 0xff] ^ + Te3[(s2 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te0[(t0 >> 24) ] ^ + Te1[(t1 >> 16) & 0xff] ^ + Te2[(t2 >> 8) & 0xff] ^ + Te3[(t3 ) & 0xff] ^ + rk[0]; + s1 = + Te0[(t1 >> 24) ] ^ + Te1[(t2 >> 16) & 0xff] ^ + Te2[(t3 >> 8) & 0xff] ^ + Te3[(t0 ) & 0xff] ^ + rk[1]; + s2 = + Te0[(t2 >> 24) ] ^ + Te1[(t3 >> 16) & 0xff] ^ + Te2[(t0 >> 8) & 0xff] ^ + Te3[(t1 ) & 0xff] ^ + rk[2]; + s3 = + Te0[(t3 >> 24) ] ^ + Te1[(t0 >> 16) & 0xff] ^ + Te2[(t1 >> 8) & 0xff] ^ + Te3[(t2 ) & 0xff] ^ + rk[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Te4[(t0 >> 24) ] & 0xff000000) ^ + (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[0]; + PUTU32(ct , s0); + s1 = + (Te4[(t1 >> 24) ] & 0xff000000) ^ + (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[1]; + PUTU32(ct + 4, s1); + s2 = + (Te4[(t2 >> 24) ] & 0xff000000) ^ + (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[2]; + PUTU32(ct + 8, s2); + s3 = + (Te4[(t3 >> 24) ] & 0xff000000) ^ + (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Te4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[3]; + PUTU32(ct + 12, s3); + + if (pCtx->Mode) { + iv[0] = s0; + iv[1] = s1; + iv[2] = s2; + iv[3] = s3; + } +} + +/* +* Decrypt the cipher into plain text +*/ +void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[]) +{ + unsigned int s0, s1, s2, s3, t0, t1, t2, t3, v0, v1, v2, v3, *iv; + const unsigned int *rk; + int r; + + rk = pCtx->Dk; + iv = pCtx->Iv; + /* + * map byte array block to cipher state + * and add initial round key: + */ + v0 = GETU32(ct ); s0 = v0 ^ rk[0]; + v1 = GETU32(ct + 4); s1 = v1 ^ rk[1]; + v2 = GETU32(ct + 8); s2 = v2 ^ rk[2]; + v3 = GETU32(ct + 12); s3 = v3 ^ rk[3]; + /* + * Nr - 1 full rounds: + */ + r = pCtx->Nr >> 1; + for (;;) { + t0 = + Td0[(s0 >> 24) ] ^ + Td1[(s3 >> 16) & 0xff] ^ + Td2[(s2 >> 8) & 0xff] ^ + Td3[(s1 ) & 0xff] ^ + rk[4]; + t1 = + Td0[(s1 >> 24) ] ^ + Td1[(s0 >> 16) & 0xff] ^ + Td2[(s3 >> 8) & 0xff] ^ + Td3[(s2 ) & 0xff] ^ + rk[5]; + t2 = + Td0[(s2 >> 24) ] ^ + Td1[(s1 >> 16) & 0xff] ^ + Td2[(s0 >> 8) & 0xff] ^ + Td3[(s3 ) & 0xff] ^ + rk[6]; + t3 = + Td0[(s3 >> 24) ] ^ + Td1[(s2 >> 16) & 0xff] ^ + Td2[(s1 >> 8) & 0xff] ^ + Td3[(s0 ) & 0xff] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td0[(t0 >> 24) ] ^ + Td1[(t3 >> 16) & 0xff] ^ + Td2[(t2 >> 8) & 0xff] ^ + Td3[(t1 ) & 0xff] ^ + rk[0]; + s1 = + Td0[(t1 >> 24) ] ^ + Td1[(t0 >> 16) & 0xff] ^ + Td2[(t3 >> 8) & 0xff] ^ + Td3[(t2 ) & 0xff] ^ + rk[1]; + s2 = + Td0[(t2 >> 24) ] ^ + Td1[(t1 >> 16) & 0xff] ^ + Td2[(t0 >> 8) & 0xff] ^ + Td3[(t3 ) & 0xff] ^ + rk[2]; + s3 = + Td0[(t3 >> 24) ] ^ + Td1[(t2 >> 16) & 0xff] ^ + Td2[(t1 >> 8) & 0xff] ^ + Td3[(t0 ) & 0xff] ^ + rk[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = + (Td4[(t0 >> 24) ] & 0xff000000) ^ + (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t1 ) & 0xff] & 0x000000ff) ^ + rk[0]; + s1 = + (Td4[(t1 >> 24) ] & 0xff000000) ^ + (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t2 ) & 0xff] & 0x000000ff) ^ + rk[1]; + s2 = + (Td4[(t2 >> 24) ] & 0xff000000) ^ + (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t3 ) & 0xff] & 0x000000ff) ^ + rk[2]; + s3 = + (Td4[(t3 >> 24) ] & 0xff000000) ^ + (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ + (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ + (Td4[(t0 ) & 0xff] & 0x000000ff) ^ + rk[3]; + + if (pCtx->Mode) { + s0 = s0 ^ iv[0]; iv[0] = v0; + s1 = s1 ^ iv[1]; iv[1] = v1; + s2 = s2 ^ iv[2]; iv[2] = v2; + s3 = s3 ^ iv[3]; iv[3] = v3; + } + + PUTU32(pt , s0); + PUTU32(pt + 4, s1); + PUTU32(pt + 8, s2); + PUTU32(pt + 12, s3); +} + +////////////////////////////////////////////////////////////////////////////// +// API functions // +////////////////////////////////////////////////////////////////////////////// + +/* +* initialize AES context +*/ +int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode) +{ + if (pKey == 0 || pCtx == 0 || (KeyLen != KEY128 && KeyLen != KEY192 && KeyLen != KEY256)) + return -1; + + // generate key schedule + pCtx->Nr = AesGenKeySched(pCtx->Ek, pCtx->Dk, pKey, KeyLen); + + // initialize IV + if (pIV != 0) { + pCtx->Iv[0] = GETU32(pIV ); + pCtx->Iv[1] = GETU32(pIV + 4 ); + pCtx->Iv[2] = GETU32(pIV + 8 ); + pCtx->Iv[3] = GETU32(pIV + 12); + } + + // mode + pCtx->Mode = Mode; + + return 0; +} + +/* +* Encrypt plain text +*/ +int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen) +{ + int i; + + if (pData == 0 || pCipher == 0 || pCtx == 0 || (DataLen & 0xf) != 0) + return -1; + + for (i = 0; i < DataLen; i += BLOCKSZ) { + // encrypt block by block + AesEncBlk(pCtx, pData, pCipher); + pCipher += BLOCKSZ; + pData += BLOCKSZ; + } + return DataLen; +} + +/* +* Decrypt cipher +*/ +int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen) +{ + int i; + + if (pData == 0 || pCipher == 0 || pCtx == 0 || (CipherLen & 0xf) != 0) + return -1; + + for (i = 0; i < CipherLen; i += BLOCKSZ) { + // decrypt block by block + AesDecBlk(pCtx, pCipher, pData); + pCipher += BLOCKSZ; + pData += BLOCKSZ; + } + return CipherLen; +} + +////////////////////////////////////////////////////////////////////////////// +// Sample main program // +////////////////////////////////////////////////////////////////////////////// + +#ifndef EMBEDDED +int main() +{ + AesCtx ctx; + unsigned char iv[] = "INI VECTINI VECT"; + unsigned char key[] = "This is a sample AESKey"; + unsigned char databuf[] = "Data : AES Test"; // must be in multiple of 16 + + // initialize context and encrypt data at one end + + if( AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0) + printf("init error\n"); + + if (AesEncrypt(&ctx, databuf, databuf, sizeof databuf) < 0) + printf("error in encryption\n"); + + // initialize context and decrypt cipher at other end + + if( AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0) + printf("init error\n"); + + if (AesDecrypt(&ctx, databuf, databuf, sizeof databuf) < 0) + printf("error in decryption\n"); + + printf("%s\n", databuf); + + return 0; +} +#endif \ No newline at end of file diff --git a/armsrc/aes.h b/armsrc/aes.h new file mode 100644 index 00000000..85944873 --- /dev/null +++ b/armsrc/aes.h @@ -0,0 +1,30 @@ +/* +* AES Cryptographic Algorithm Header File. Include this header file in +* your source which uses these given APIs. (This source is kept under +* public domain) +*/ + +// AES context structure +typedef struct { + unsigned int Ek[60]; + unsigned int Dk[60]; + unsigned int Iv[4]; + unsigned char Nr; + unsigned char Mode; +} AesCtx; + +// key length in bytes +#define KEY128 16 +#define KEY192 24 +#define KEY256 32 +// block size in bytes +#define BLOCKSZ 16 +// mode +#define EBC 0 +#define CBC 1 + +// AES API function prototype + +int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode); +int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen); +int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen); \ No newline at end of file diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a3f507d6..6fd6cdcc 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -10,10 +10,10 @@ // executes. //----------------------------------------------------------------------------- -#include "usb_cdc.h" -#include "cmd.h" +#include "../common/usb_cdc.h" +#include "../common/cmd.h" -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "printf.h" @@ -22,7 +22,7 @@ #include #include "legicrf.h" -#include +#include "../include/hitag2.h" #ifdef WITH_LCD #include "LCD.h" @@ -81,40 +81,12 @@ void DbpString(char *str) { byte_t len = strlen(str); cmd_send(CMD_DEBUG_PRINT_STRING,len,0,0,(byte_t*)str,len); -// /* this holds up stuff unless we're connected to usb */ -// if (!UsbConnected()) -// return; -// -// UsbCommand c; -// c.cmd = CMD_DEBUG_PRINT_STRING; -// c.arg[0] = strlen(str); -// if(c.arg[0] > sizeof(c.d.asBytes)) { -// c.arg[0] = sizeof(c.d.asBytes); -// } -// memcpy(c.d.asBytes, str, c.arg[0]); -// -// UsbSendPacket((uint8_t *)&c, sizeof(c)); -// // TODO fix USB so stupid things like this aren't req'd -// SpinDelay(50); } #if 0 void DbpIntegers(int x1, int x2, int x3) { cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0); -// /* this holds up stuff unless we're connected to usb */ -// if (!UsbConnected()) -// return; -// -// UsbCommand c; -// c.cmd = CMD_DEBUG_PRINT_INTEGERS; -// c.arg[0] = x1; -// c.arg[1] = x2; -// c.arg[2] = x3; -// -// UsbSendPacket((uint8_t *)&c, sizeof(c)); -// // XXX -// SpinDelay(50); } #endif @@ -199,8 +171,6 @@ void MeasureAntennaTuning(void) int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV -// UsbCommand c; - LED_B_ON(); DbpString("Measuring antenna characteristics, please wait..."); memset(dest,0,sizeof(FREE_BUFFER_SIZE)); @@ -627,7 +597,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { UsbCommand *c = (UsbCommand *)packet; -// Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]); + //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]); switch(c->cmd) { #ifdef WITH_LF @@ -692,7 +662,6 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_PCF7931_READ: // Read PCF7931 tag ReadPCF7931(); cmd_send(CMD_ACK,0,0,0,0,0); -// UsbSendPacket((uint8_t*)&ack, sizeof(ack)); break; case CMD_EM4X_READ_WORD: EM4xReadWord(c->arg[1], c->arg[2],c->d.asBytes[0]); @@ -800,8 +769,17 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_MIFAREU_READBL: MifareUReadBlock(c->arg[0],c->d.asBytes); break; + case CMD_MIFAREUC_AUTH1: + MifareUC_Auth1(c->arg[0],c->d.asBytes); + break; + case CMD_MIFAREUC_AUTH2: + MifareUC_Auth2(c->arg[0],c->d.asBytes); + break; case CMD_MIFAREU_READCARD: - MifareUReadCard(c->arg[0],c->d.asBytes); + MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes); + break; + case CMD_MIFAREUC_READCARD: + MifareUReadCard(c->arg[0],c->arg[1],c->d.asBytes); break; case CMD_MIFARE_READSC: MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); @@ -854,6 +832,28 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_MIFARE_SNIFFER: SniffMifare(c->arg[0]); break; + + // mifare desfire + case CMD_MIFARE_DESFIRE_READBL: + break; + case CMD_MIFARE_DESFIRE_WRITEBL: + break; + case CMD_MIFARE_DESFIRE_AUTH1: + MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_DESFIRE_AUTH2: + MifareDES_Auth2(c->arg[0],c->d.asBytes); + break; + // case CMD_MIFARE_DES_READER: + // ReaderMifareDES(c->arg[0], c->arg[1], c->d.asBytes); + //break; + case CMD_MIFARE_DESFIRE_INFO: + MifareDesfireGetInformation(); + break; + case CMD_MIFARE_DESFIRE: + MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes); + break; + #endif #ifdef WITH_ICLASS @@ -868,7 +868,7 @@ void UsbPacketReceived(uint8_t *packet, int len) ReaderIClass(c->arg[0]); break; case CMD_READER_ICLASS_REPLAY: - ReaderIClass_Replay(c->arg[0], c->d.asBytes); + ReaderIClass_Replay(c->arg[0], c->d.asBytes); break; #endif @@ -899,18 +899,6 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: -// UsbCommand n; -// if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) { -// n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K; -// } else { -// n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE; -// } -// n.arg[0] = c->arg[0]; - // memcpy(n.d.asBytes, BigBuf+c->arg[0], 48); // 12*sizeof(uint32_t) - // LED_B_ON(); - // usb_write((uint8_t *)&n, sizeof(n)); - // UsbSendPacket((uint8_t *)&n, sizeof(n)); - // LED_B_OFF(); LED_B_ON(); for(size_t i=0; iarg[1]; i += USB_CMD_DATA_SIZE) { @@ -926,7 +914,6 @@ void UsbPacketReceived(uint8_t *packet, int len) uint8_t *b = (uint8_t *)BigBuf; memcpy(b+c->arg[0], c->d.asBytes, 48); //Dbprintf("copied 48 bytes to %i",b+c->arg[0]); -// UsbSendPacket((uint8_t*)&ack, sizeof(ack)); cmd_send(CMD_ACK,0,0,0,0,0); break; } @@ -984,7 +971,6 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_DEVICE_INFO: { uint32_t dev_info = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS; if(common_area.flags.bootrom_present) dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT; -// UsbSendPacket((uint8_t*)&c, sizeof(c)); cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0); break; } @@ -1011,9 +997,8 @@ void __attribute__((noreturn)) AppMain(void) LED_B_OFF(); LED_A_OFF(); - // Init USB device` - usb_enable(); -// UsbStart(); + // Init USB device + usb_enable(); // The FPGA gets its clock from us from PCK0 output, so set that up. AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; @@ -1043,14 +1028,12 @@ void __attribute__((noreturn)) AppMain(void) size_t rx_len; for(;;) { - if (usb_poll()) { - rx_len = usb_read(rx,sizeof(UsbCommand)); - if (rx_len) { - UsbPacketReceived(rx,rx_len); - } - } -// UsbPoll(FALSE); - + if (usb_poll()) { + rx_len = usb_read(rx,sizeof(UsbCommand)); + if (rx_len) { + UsbPacketReceived(rx,rx_len); + } + } WDT_HIT(); #ifdef WITH_LF diff --git a/armsrc/apps.h b/armsrc/apps.h index 011ad695..90313aec 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -14,9 +14,27 @@ #include #include -#include "common.h" -#include "hitag2.h" -#include "mifare.h" +#include + +#include +#include +#include + + +#include "../include/common.h" +#include "../include/hitag2.h" +#include "../include/mifare.h" + +//#include +//#include + +//#include "des.h" +//#include "aes.h" +#include "../common/desfire.h" +#include "../common/crc32.h" +//#include "desfire_crypto.h" +//#include "desfire_key.h" + // The large multi-purpose buffer, typically used to hold A/D samples, // maybe processed in some way. @@ -172,7 +190,9 @@ void ReaderMifare(bool first_try); int32_t dist_nt(uint32_t nt1, uint32_t nt2); void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); void MifareUReadBlock(uint8_t arg0,uint8_t *datain); -void MifareUReadCard(uint8_t arg0,uint8_t *datain); +void MifareUC_Auth1(uint8_t arg0, uint8_t *datain); +void MifareUC_Auth2(uint32_t arg0, uint8_t *datain); +void MifareUReadCard(uint8_t arg0,int Pages,uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0,uint8_t *datain); @@ -188,6 +208,47 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); // Work with "magic Chinese" card void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +// mifaredesfire.h +bool InitDesfireCard(); +void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain); +void MifareDesfireGetInformation(); +void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain); +void MifareDES_Auth2(uint32_t arg0, uint8_t *datain); +int mifare_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); +void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain); +int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); +size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout); +void OnSuccess(); +void OnError(); + +// desfire_key.h +desfirekey_t Desfire_des_key_new (const uint8_t value[8]); +desfirekey_t Desfire_3des_key_new (const uint8_t value[16]); +desfirekey_t Desfire_des_key_new_with_version (const uint8_t value[8]); +desfirekey_t Desfire_3des_key_new_with_version (const uint8_t value[16]); +desfirekey_t Desfire_3k3des_key_new (const uint8_t value[24]); +desfirekey_t Desfire_3k3des_key_new_with_version (const uint8_t value[24]); +desfirekey_t Desfire_aes_key_new (const uint8_t value[16]); +desfirekey_t Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version); +uint8_t Desfire_key_get_version (desfirekey_t key); +void Desfire_key_set_version (desfirekey_t key, uint8_t version); +desfirekey_t Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey); + +// desfire_crypto.h +void *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings); +void *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings); +void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size); +void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation); +size_t key_block_size (const desfirekey_t key); +size_t padded_data_length (const size_t nbytes, const size_t block_size); +size_t maced_data_length (const desfirekey_t key, const size_t nbytes); +size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings); +void cmac_generate_subkeys (desfirekey_t key); +void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac); + + + + /// iso15693.h void RecordRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void); diff --git a/armsrc/des.c b/armsrc/des.c new file mode 100644 index 00000000..0a27503e --- /dev/null +++ b/armsrc/des.c @@ -0,0 +1,383 @@ +/* des.c */ +/* + This file is part of the ARM-Crypto-Lib. + Copyright (C) 2006-2010 Daniel Otte (daniel.otte@rub.de) + + 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, see . +*/ +/** + * \file des.c + * \author Daniel Otte + * \email daniel.otte@rub.de + * \date 2007-06-16 + * \brief DES and EDE-DES implementation + * \license GPLv3 or later + * + */ +#include +#include + +const uint8_t sbox[256] = { + /* S-box 1 */ + 0xE4, 0xD1, 0x2F, 0xB8, 0x3A, 0x6C, 0x59, 0x07, + 0x0F, 0x74, 0xE2, 0xD1, 0xA6, 0xCB, 0x95, 0x38, + 0x41, 0xE8, 0xD6, 0x2B, 0xFC, 0x97, 0x3A, 0x50, + 0xFC, 0x82, 0x49, 0x17, 0x5B, 0x3E, 0xA0, 0x6D, + /* S-box 2 */ + 0xF1, 0x8E, 0x6B, 0x34, 0x97, 0x2D, 0xC0, 0x5A, + 0x3D, 0x47, 0xF2, 0x8E, 0xC0, 0x1A, 0x69, 0xB5, + 0x0E, 0x7B, 0xA4, 0xD1, 0x58, 0xC6, 0x93, 0x2F, + 0xD8, 0xA1, 0x3F, 0x42, 0xB6, 0x7C, 0x05, 0xE9, + /* S-box 3 */ + 0xA0, 0x9E, 0x63, 0xF5, 0x1D, 0xC7, 0xB4, 0x28, + 0xD7, 0x09, 0x34, 0x6A, 0x28, 0x5E, 0xCB, 0xF1, + 0xD6, 0x49, 0x8F, 0x30, 0xB1, 0x2C, 0x5A, 0xE7, + 0x1A, 0xD0, 0x69, 0x87, 0x4F, 0xE3, 0xB5, 0x2C, + /* S-box 4 */ + 0x7D, 0xE3, 0x06, 0x9A, 0x12, 0x85, 0xBC, 0x4F, + 0xD8, 0xB5, 0x6F, 0x03, 0x47, 0x2C, 0x1A, 0xE9, + 0xA6, 0x90, 0xCB, 0x7D, 0xF1, 0x3E, 0x52, 0x84, + 0x3F, 0x06, 0xA1, 0xD8, 0x94, 0x5B, 0xC7, 0x2E, + /* S-box 5 */ + 0x2C, 0x41, 0x7A, 0xB6, 0x85, 0x3F, 0xD0, 0xE9, + 0xEB, 0x2C, 0x47, 0xD1, 0x50, 0xFA, 0x39, 0x86, + 0x42, 0x1B, 0xAD, 0x78, 0xF9, 0xC5, 0x63, 0x0E, + 0xB8, 0xC7, 0x1E, 0x2D, 0x6F, 0x09, 0xA4, 0x53, + /* S-box 6 */ + 0xC1, 0xAF, 0x92, 0x68, 0x0D, 0x34, 0xE7, 0x5B, + 0xAF, 0x42, 0x7C, 0x95, 0x61, 0xDE, 0x0B, 0x38, + 0x9E, 0xF5, 0x28, 0xC3, 0x70, 0x4A, 0x1D, 0xB6, + 0x43, 0x2C, 0x95, 0xFA, 0xBE, 0x17, 0x60, 0x8D, + /* S-box 7 */ + 0x4B, 0x2E, 0xF0, 0x8D, 0x3C, 0x97, 0x5A, 0x61, + 0xD0, 0xB7, 0x49, 0x1A, 0xE3, 0x5C, 0x2F, 0x86, + 0x14, 0xBD, 0xC3, 0x7E, 0xAF, 0x68, 0x05, 0x92, + 0x6B, 0xD8, 0x14, 0xA7, 0x95, 0x0F, 0xE2, 0x3C, + /* S-box 8 */ + 0xD2, 0x84, 0x6F, 0xB1, 0xA9, 0x3E, 0x50, 0xC7, + 0x1F, 0xD8, 0xA3, 0x74, 0xC5, 0x6B, 0x0E, 0x92, + 0x7B, 0x41, 0x9C, 0xE2, 0x06, 0xAD, 0xF3, 0x58, + 0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B +}; + +const uint8_t e_permtab[] ={ + 4, 6, /* 4 bytes in 6 bytes out*/ + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 +}; + +const uint8_t p_permtab[] ={ + 4, 4, /* 32 bit -> 32 bit */ + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 +}; + +const uint8_t ip_permtab[] ={ + 8, 8, /* 64 bit -> 64 bit */ + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 +}; + +const uint8_t inv_ip_permtab[] ={ + 8, 8, /* 64 bit -> 64 bit */ + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 +}; + +const uint8_t pc1_permtab[] ={ + 8, 7, /* 64 bit -> 56 bit*/ + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 +}; + +const uint8_t pc2_permtab[] ={ + 7, 6, /* 56 bit -> 48 bit */ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 +}; + +const uint8_t splitin6bitword_permtab[] = { + 8, 8, /* 64 bit -> 64 bit */ + 64, 64, 1, 6, 2, 3, 4, 5, + 64, 64, 7, 12, 8, 9, 10, 11, + 64, 64, 13, 18, 14, 15, 16, 17, + 64, 64, 19, 24, 20, 21, 22, 23, + 64, 64, 25, 30, 26, 27, 28, 29, + 64, 64, 31, 36, 32, 33, 34, 35, + 64, 64, 37, 42, 38, 39, 40, 41, + 64, 64, 43, 48, 44, 45, 46, 47 +}; + +const uint8_t shiftkey_permtab[] = { + 7, 7, /* 56 bit -> 56 bit */ + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 1, + 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 29 +}; + +const uint8_t shiftkeyinv_permtab[] = { + 7, 7, + 28, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, + 56, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55 +}; + +/* +1 0 +1 0 +2 1 +2 1 +2 1 +2 1 +2 1 +2 1 +---- +1 0 +2 1 +2 1 +2 1 +2 1 +2 1 +2 1 +1 0 +*/ +#define ROTTABLE 0x7EFC +#define ROTTABLE_INV 0x3F7E +/******************************************************************************/ + +void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){ + uint8_t ob; /* in-bytes and out-bytes */ + uint8_t byte, bit; /* counter for bit and byte */ + ob = ptable[1]; + ptable = &(ptable[2]); + for(byte=0; byte>(x%8)) ){ + t|=0x01; + } + } + out[byte]=t; + } +} + +/******************************************************************************/ + +void changeendian32(uint32_t * a){ + *a = (*a & 0x000000FF) << 24 | + (*a & 0x0000FF00) << 8 | + (*a & 0x00FF0000) >> 8 | + (*a & 0xFF000000) >> 24; +} + +/******************************************************************************/ +static inline +void shiftkey(uint8_t *key){ + uint8_t k[7]; + memcpy(k, key, 7); + permute((uint8_t*)shiftkey_permtab, k, key); +} + +/******************************************************************************/ +static inline +void shiftkey_inv(uint8_t *key){ + uint8_t k[7]; + memcpy(k, key, 7); + permute((uint8_t*)shiftkeyinv_permtab, k, key); + +} + +/******************************************************************************/ +static inline +uint64_t splitin6bitwords(uint64_t a){ + uint64_t ret=0; + a &= 0x0000ffffffffffffLL; + permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); + return ret; +} + +/******************************************************************************/ + +static inline +uint8_t substitute(uint8_t a, uint8_t * sbp){ + uint8_t x; + x = sbp[a>>1]; + x = (a&1)?x&0x0F:x>>4; + return x; + +} + +/******************************************************************************/ + +uint32_t des_f(uint32_t r, uint8_t* kr){ + uint8_t i; + uint32_t t=0,ret; + uint64_t data; + uint8_t *sbp; /* sboxpointer */ + permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); + for(i=0; i<7; ++i) + ((uint8_t*)&data)[i] ^= kr[i]; + + /* Sbox substitution */ + data = splitin6bitwords(data); + sbp=(uint8_t*)sbox; + for(i=0; i<8; ++i){ + uint8_t x; + x = substitute(((uint8_t*)&data)[i], sbp); + t<<=4; + t |= x; + sbp += 32; + } + changeendian32(&t); + + permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); + + return ret; +} + +/******************************************************************************/ + +void des_enc(void* out, const void* in, const void* key){ +#define R *((uint32_t*)&(data[4])) +#define L *((uint32_t*)&(data[0])) + + uint8_t data[8],kr[6],k[7]; + uint8_t i; + + permute((uint8_t*)ip_permtab, (uint8_t*)in, data); + permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); + for(i=0; i<8; ++i){ + shiftkey(k); + if(ROTTABLE&((1<<((i<<1)+0))) ) + shiftkey(k); + permute((uint8_t*)pc2_permtab, k, kr); + L ^= des_f(R, kr); + + shiftkey(k); + if(ROTTABLE&((1<<((i<<1)+1))) ) + shiftkey(k); + permute((uint8_t*)pc2_permtab, k, kr); + R ^= des_f(L, kr); + + } + /* L <-> R*/ + R ^= L; + L ^= R; + R ^= L; + + permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out); +} + +/******************************************************************************/ + +void des_dec(void* out, const void* in, const uint8_t* key){ +#define R *((uint32_t*)&(data[4])) +#define L *((uint32_t*)&(data[0])) + + uint8_t data[8],kr[6],k[7]; + int8_t i; + permute((uint8_t*)ip_permtab, (uint8_t*)in, data); + permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); + for(i=7; i>=0; --i){ + + permute((uint8_t*)pc2_permtab, k, kr); + L ^= des_f(R, kr); + shiftkey_inv(k); + if(ROTTABLE&((1<<((i<<1)+1))) ){ + shiftkey_inv(k); + } + + permute((uint8_t*)pc2_permtab, k, kr); + R ^= des_f(L, kr); + shiftkey_inv(k); + if(ROTTABLE&((1<<((i<<1)+0))) ){ + shiftkey_inv(k); + } + + } + /* L <-> R*/ + R ^= L; + L ^= R; + R ^= L; + + permute((uint8_t*)inv_ip_permtab, data, (uint8_t*)out); +} + +/******************************************************************************/ + +void tdes_enc(void* out, void* in, const void* key){ + des_enc(out, in, (uint8_t*)key + 0); + des_dec(out, out, (uint8_t*)key + 8); + des_enc(out, out, (uint8_t*)key +16); +} + +/******************************************************************************/ + +void tdes_dec(void* out, void* in, const uint8_t* key){ + des_dec(out, in, (uint8_t*)key +16); + des_enc(out, out, (uint8_t*)key + 8); + des_dec(out, out, (uint8_t*)key + 0); +} + +/******************************************************************************/ + + diff --git a/armsrc/des.h b/armsrc/des.h new file mode 100644 index 00000000..652886fd --- /dev/null +++ b/armsrc/des.h @@ -0,0 +1,107 @@ +/* des.h */ +/* + This file is part of the ARM-Crypto-Lib. + Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) + + 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, see . +*/ +/** + * \file des.h + * \author Daniel Otte + * \date 2007-06-16 + * \brief des and tdes declarations + * \license GPLv3 or later + * + */ +#ifndef DES_H_ +#define DES_H_ + +/* the FIPS 46-3 (1999-10-25) name for triple DES is triple data encryption algorithm so TDEA. + * Also we only implement the three key mode */ + +/** \def tdea_enc + * \brief defining an alias for void tdes_enc(void* out, const void* in, const void* key) + */ + +/** \def tdea_dec + * \brief defining an alias for void tdes_dec(void* out, const void* in, const void* key) + */ + +#define tdea_enc tdes_enc +#define tdea_dec tdes_dec + +/** \fn void des_enc(void* out, const void* in, const void* key) + * \brief encrypt a block with DES + * + * This function encrypts a block of 64 bits (8 bytes) with the DES algorithm. + * Key expansion is done automatically. The key is 64 bits long, but note that + * only 56 bits are used (the LSB of each byte is dropped). The input and output + * blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to + * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from + * \param key pointer to the key (64 bit = 8 byte) + */ +void des_enc(void* out, const void* in, const void* key); + +/** \fn void des_dec(void* out, const void* in, const void* key) + * \brief decrypt a block with DES + * + * This function decrypts a block of 64 bits (8 bytes) with the DES algorithm. + * Key expansion is done automatically. The key is 64 bits long, but note that + * only 56 bits are used (the LSB of each byte is dropped). The input and output + * blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to + * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from + * \param key pointer to the key (64 bit = 8 byte) + */ +void des_dec(void* out, const void* in, const void* key); + +/** \fn void tdes_enc(void* out, const void* in, const void* key) + * \brief encrypt a block with Tripple-DES + * + * This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) + * algorithm. Key expansion is done automatically. The key is 192 bits long, but + * note that only 178 bits are used (the LSB of each byte is dropped). The input + * and output blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to + * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from + * \param key pointer to the key (192 bit = 24 byte) + */ +void tdes_enc(void* out, const void* in, const void* key); + +/** \fn void tdes_dec(void* out, const void* in, const void* key) + * \brief decrypt a block with Tripple-DES + * + * This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) + * algorithm. Key expansion is done automatically. The key is 192 bits long, but + * note that only 178 bits are used (the LSB of each byte is dropped). The input + * and output blocks may overlap. + * + * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to + * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from + * \param key pointer to the key (192 bit = 24 byte) + */ + void tdes_dec(void* out, const void* in, const void* key); + +#endif /*DES_H_*/ + +// Copied from des.h in desfire imp. +typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */ +typedef unsigned long DES3_KS[48][2]; /* Triple-DES key schedule */ + + +extern int Asmversion; /* 1 if we're linked with an asm version, 0 if C */ diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c new file mode 100644 index 00000000..b77ad8ef --- /dev/null +++ b/armsrc/desfire_crypto.c @@ -0,0 +1,642 @@ +/*- + * Copyright (C) 2010, Romain Tartiere. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + +/* + * This implementation was written based on information provided by the + * following documents: + * + * NIST Special Publication 800-38B + * Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication + * May 2005 + */ +#include "desfire_crypto.h" + +static void xor (const uint8_t *ivect, uint8_t *data, const size_t len); + +static size_t key_macing_length (desfirekey_t key); + +static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) { + for (size_t i = 0; i < len; i++) { + data[i] ^= ivect[i]; + } +} + +void cmac_generate_subkeys ( desfirekey_t key) { + int kbs = key_block_size (key); + const uint8_t R = (kbs == 8) ? 0x1B : 0x87; + + uint8_t l[kbs]; + memset (l, 0, kbs); + + uint8_t ivect[kbs]; + memset (ivect, 0, kbs); + + mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER); + + bool xor = false; + + // Used to compute CMAC on complete blocks + memcpy (key->cmac_sk1, l, kbs); + xor = l[0] & 0x80; + lsl (key->cmac_sk1, kbs); + if (xor) + key->cmac_sk1[kbs-1] ^= R; + + // Used to compute CMAC on the last block if non-complete + memcpy (key->cmac_sk2, key->cmac_sk1, kbs); + xor = key->cmac_sk1[0] & 0x80; + lsl (key->cmac_sk2, kbs); + if (xor) + key->cmac_sk2[kbs-1] ^= R; +} + +void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) { + int kbs = key_block_size (key); + uint8_t *buffer = malloc (padded_data_length (len, kbs)); + + memcpy (buffer, data, len); + + if ((!len) || (len % kbs)) { + buffer[len++] = 0x80; + while (len % kbs) { + buffer[len++] = 0x00; + } + xor (key->cmac_sk2, buffer + len - kbs, kbs); + } else { + xor (key->cmac_sk1, buffer + len - kbs, kbs); + } + + mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); + + memcpy (cmac, ivect, kbs); +} + +size_t key_block_size (const desfirekey_t key) { + size_t block_size = 8; + + switch (key->type) { + case T_DES: + case T_3DES: + case T_3K3DES: + block_size = 8; + break; + case T_AES: + block_size = 16; + break; + } + + return block_size; +} + +/* + * Size of MACing produced with the key. + */ +static size_t key_macing_length (const desfirekey_t key) { + size_t mac_length = MAC_LENGTH; + + switch (key->type) { + case T_DES: + case T_3DES: + mac_length = MAC_LENGTH; + break; + case T_3K3DES: + case T_AES: + mac_length = CMAC_LENGTH; + break; + } + + return mac_length; +} + +/* + * Size required to store nbytes of data in a buffer of size n*block_size. + */ +size_t padded_data_length (const size_t nbytes, const size_t block_size) { + if ((!nbytes) || (nbytes % block_size)) + return ((nbytes / block_size) + 1) * block_size; + else + return nbytes; +} + +/* + * Buffer size required to MAC nbytes of data + */ +size_t maced_data_length (const desfirekey_t key, const size_t nbytes) { + return nbytes + key_macing_length (key); +} +/* + * Buffer size required to encipher nbytes of data and a two bytes CRC. + */ +size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) { + size_t crc_length = 0; + if (!(communication_settings & NO_CRC)) { + switch (DESFIRE(tag)->authentication_scheme) { + case AS_LEGACY: + crc_length = 2; + break; + case AS_NEW: + crc_length = 4; + break; + } + } + + size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1; + + return padded_data_length (nbytes + crc_length, block_size); +} + +void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings) { + uint8_t *res = data; + uint8_t mac[4]; + size_t edl; + bool append_mac = true; + desfirekey_t key = DESFIRE(tag)->session_key; + + if (!key) + return data; + + switch (communication_settings & MDCM_MASK) { + case MDCM_PLAIN: + if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) + break; + + /* + * When using new authentication methods, PLAIN data transmission from + * the PICC to the PCD are CMACed, so we have to maintain the + * cryptographic initialisation vector up-to-date to check data + * integrity later. + * + * The only difference with CMACed data transmission is that the CMAC + * is not apended to the data send by the PCD to the PICC. + */ + + append_mac = false; + + /* pass through */ + case MDCM_MACED: + switch (DESFIRE(tag)->authentication_scheme) { + case AS_LEGACY: + if (!(communication_settings & MAC_COMMAND)) + break; + + /* pass through */ + edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset; + + // Fill in the crypto buffer with data ... + memcpy (res, data, *nbytes); + // ... and 0 padding + memset (res + *nbytes, 0, edl - *nbytes); + + mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER); + + memcpy (mac, res + edl - 8, 4); + + // Copy again provided data (was overwritten by mifare_cypher_blocks_chained) + memcpy (res, data, *nbytes); + + if (!(communication_settings & MAC_COMMAND)) + break; + // Append MAC + size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset; + bla++; + + memcpy (res + *nbytes, mac, 4); + + *nbytes += 4; + break; + case AS_NEW: + if (!(communication_settings & CMAC_COMMAND)) + break; + cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac); + + if (append_mac) { + maced_data_length (key, *nbytes); + + memcpy (res, data, *nbytes); + memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH); + *nbytes += CMAC_LENGTH; + } + break; + } + + break; + case MDCM_ENCIPHERED: + /* |<-------------- data -------------->| + * |<--- offset -->| | + * +---------------+--------------------+-----+---------+ + * | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING | + * +---------------+--------------------+-----+---------+ ---------------- + * | |<~~~~v~~~~~~~~~~~~~>| ^ | | (DES / 3DES) + * | | `---- crc16() ----' | | + * | | | ^ | | ----- *or* ----- + * |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>| ^ | | (3K3DES / AES) + * | `---- crc32() ----' | | + * | | ---- *then* ---- + * |<---------------------------------->| + * encypher()/decypher() + */ + + if (!(communication_settings & ENC_COMMAND)) + break; + edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset; + + // Fill in the crypto buffer with data ... + memcpy (res, data, *nbytes); + if (!(communication_settings & NO_CRC)) { + // ... CRC ... + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + AppendCrc14443a(res + offset, *nbytes - offset); + *nbytes += 2; + break; + case AS_NEW: + crc32_append (res, *nbytes); + *nbytes += 4; + break; + } + } + // ... and padding + memset (res + *nbytes, 0, edl - *nbytes); + + *nbytes = edl; + + mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER); + break; + default: + + *nbytes = -1; + res = NULL; + break; + } + + return res; + +} + +void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings) +{ + void *res = data; + size_t edl; + void *edata = NULL; + uint8_t first_cmac_byte = 0x00; + + desfirekey_t key = DESFIRE(tag)->session_key; + + if (!key) + return data; + + // Return directly if we just have a status code. + if (1 == *nbytes) + return res; + + switch (communication_settings & MDCM_MASK) { + case MDCM_PLAIN: + + if (AS_LEGACY == DESFIRE(tag)->authentication_scheme) + break; + + /* pass through */ + case MDCM_MACED: + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + if (communication_settings & MAC_VERIFY) { + *nbytes -= key_macing_length (key); + if (*nbytes <= 0) { + *nbytes = -1; + res = NULL; +#ifdef WITH_DEBUG + printf ("No room for MAC!"); +#endif + break; + } + + edl = enciphered_data_length (tag, *nbytes - 1, communication_settings); + edata = malloc (edl); + + memcpy (edata, data, *nbytes - 1); + memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1); + + mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER); + + if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) { +#ifdef WITH_DEBUG + printf ("MACing not verified"); + hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0); + hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0); +#endif + DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; + *nbytes = -1; + res = NULL; + } + } + break; + case AS_NEW: + if (!(communication_settings & CMAC_COMMAND)) + break; + if (communication_settings & CMAC_VERIFY) { + if (*nbytes < 9) { + *nbytes = -1; + res = NULL; + break; + } + first_cmac_byte = ((uint8_t *)data)[*nbytes - 9]; + ((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1]; + } + + int n = (communication_settings & CMAC_VERIFY) ? 8 : 0; + cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac); + + if (communication_settings & CMAC_VERIFY) { + ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte; + if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) { +#ifdef WITH_DEBUG + printf ("CMAC NOT verified :-("); + hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0); + hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0); +#endif + DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; + *nbytes = -1; + res = NULL; + } else { + *nbytes -= 8; + } + } + break; + } + + free (edata); + + break; + case MDCM_ENCIPHERED: + (*nbytes)--; + bool verified = false; + int crc_pos = 0x00; + int end_crc_pos = 0x00; + uint8_t x; + + /* + * AS_LEGACY: + * ,-----------------+-------------------------------+--------+ + * \ BLOCK n-1 | BLOCK n | STATUS | + * / PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 | + * `-----------------+-------------------------------+--------+ + * + * <------------ DATA ------------> + * FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING + * + * AS_NEW: + * ,-------------------------------+-----------------------------------------------+--------+ + * \ BLOCK n-1 | BLOCK n | STATUS | + * / PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 | + * `-------------------------------+-----------------------------------------------+--------+ + * <----------------------------------- DATA ------------------------------------->| + * + * <----------------- DATA ----------------> + * FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS + * `------------------' + */ + + mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); + + /* + * Look for the CRC and ensure it is followed by NULL padding. We + * can't start by the end because the CRC is supposed to be 0 when + * verified, and accumulating 0's in it should not change it. + */ + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks + if (crc_pos < 0) { + /* Single block */ + crc_pos = 0; + } + break; + case AS_NEW: + /* Move status between payload and CRC */ + res = DESFIRE (tag)->crypto_buffer; + memcpy (res, data, *nbytes); + + crc_pos = (*nbytes) - 16 - 3; + if (crc_pos < 0) { + /* Single block */ + crc_pos = 0; + } + memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos); + ((uint8_t *)res)[crc_pos] = 0x00; + crc_pos++; + *nbytes += 1; + break; + } + + do { + uint16_t crc16 =0x00; + uint32_t crc; + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + end_crc_pos = crc_pos + 2; + AppendCrc14443a (res, end_crc_pos); + + // + + + crc = crc16; + break; + case AS_NEW: + end_crc_pos = crc_pos + 4; + crc32 (res, end_crc_pos, (uint8_t *)&crc); + break; + } + if (!crc) { + verified = true; + for (int n = end_crc_pos; n < *nbytes - 1; n++) { + uint8_t byte = ((uint8_t *)res)[n]; + if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) )) + verified = false; + } + } + if (verified) { + *nbytes = crc_pos; + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + ((uint8_t *)data)[(*nbytes)++] = 0x00; + break; + case AS_NEW: + /* The status byte was already before the CRC */ + break; + } + } else { + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + break; + case AS_NEW: + x = ((uint8_t *)res)[crc_pos - 1]; + ((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos]; + ((uint8_t *)res)[crc_pos] = x; + break; + } + crc_pos++; + } + } while (!verified && (end_crc_pos < *nbytes)); + + if (!verified) { +#ifdef WITH_DEBUG + /* FIXME In some configurations, the file is transmitted PLAIN */ + Dbprintf("CRC not verified in decyphered stream"); +#endif + DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; + *nbytes = -1; + res = NULL; + } + + break; + default: + Dbprintf("Unknown communication settings"); + *nbytes = -1; + res = NULL; + break; + + } + return res; +} + + +void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) +{ + uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE]; + + if (direction == MCD_SEND) { + xor (ivect, data, block_size); + } else { + memcpy (ovect, data, block_size); + } + + uint8_t edata[MAX_CRYPTO_BLOCK_SIZE]; + + switch (key->type) { + case T_DES: + switch (operation) { + case MCO_ENCYPHER: + //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); + des_enc(edata, data, key->data); + break; + case MCO_DECYPHER: + //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); + des_dec(edata, data, key->data); + break; + } + break; + case T_3DES: + switch (operation) { + case MCO_ENCYPHER: + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); + // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); + tdes_enc(edata,data, key->data); + break; + case MCO_DECYPHER: + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); + // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); + tdes_dec(data, edata, key->data); + break; + } + break; + case T_3K3DES: + switch (operation) { + case MCO_ENCYPHER: + tdes_enc(edata,data, key->data); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); + // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT); + break; + case MCO_DECYPHER: + tdes_dec(data, edata, key->data); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT); + // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); + break; + } + break; + case T_AES: + switch (operation) + { + case MCO_ENCYPHER: + { + AesCtx ctx; + AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); + AesEncrypt(&ctx, data, edata, sizeof(data) ); + break; + } + case MCO_DECYPHER: + { + AesCtx ctx; + AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); + AesDecrypt(&ctx, edata, data, sizeof(edata)); + break; + } + } + break; + } + + memcpy (data, edata, block_size); + + if (direction == MCD_SEND) { + memcpy (ivect, data, block_size); + } else { + xor (ivect, data, block_size); + memcpy (ivect, ovect, block_size); + } +} + +/* + * This function performs all CBC cyphering / deciphering. + * + * The tag argument may be NULL, in which case both key and ivect shall be set. + * When using the tag session_key and ivect for processing data, these + * arguments should be set to NULL. + * + * Because the tag may contain additional data, one may need to call this + * function with tag, key and ivect defined. + */ +void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) { + size_t block_size; + + if (tag) { + if (!key) + key = DESFIRE (tag)->session_key; + if (!ivect) + ivect = DESFIRE (tag)->ivect; + + switch (DESFIRE (tag)->authentication_scheme) { + case AS_LEGACY: + memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); + break; + case AS_NEW: + break; + } + } + + block_size = key_block_size (key); + + size_t offset = 0; + while (offset < data_size) { + mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size); + offset += block_size; + } +} \ No newline at end of file diff --git a/armsrc/desfire_crypto.h b/armsrc/desfire_crypto.h new file mode 100644 index 00000000..d580ccc8 --- /dev/null +++ b/armsrc/desfire_crypto.h @@ -0,0 +1,15 @@ +#ifndef __DESFIRE_CRYPTO_H +#define __DESFIRE_CRYPTO_H + +#include +#include +#include +#include "printf.h" + +#include "iso14443a.h" +#include "../common/desfire.h" +#include "des.h" +//#include "aes.h" + + +#endif diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c new file mode 100644 index 00000000..b829013e --- /dev/null +++ b/armsrc/desfire_key.c @@ -0,0 +1,158 @@ +/*- + * Copyright (C) 2010, Romain Tartiere. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + + #include "desfire_key.h" + +static inline void update_key_schedules (desfirekey_t key); + +static inline void update_key_schedules (desfirekey_t key) { + // DES_set_key ((DES_cblock *)key->data, &(key->ks1)); + // DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2)); + // if (T_3K3DES == key->type) { + // DES_set_key ((DES_cblock *)(key->data + 16), &(key->ks3)); + // } +} + +desfirekey_t Desfire_des_key_new (const uint8_t value[8]) { + uint8_t data[8]; + memcpy (data, value, 8); + for (int n=0; n < 8; n++) + data[n] &= 0xfe; + return Desfire_des_key_new_with_version (data); +} + +desfirekey_t Desfire_des_key_new_with_version (const uint8_t value[8]) { + desfirekey_t key = NULL; + key->type = T_DES; + memcpy (key->data, value, 8); + memcpy (key->data+8, value, 8); + update_key_schedules (key); + return key; +} + +desfirekey_t Desfire_3des_key_new (const uint8_t value[16]) { + uint8_t data[16]; + memcpy (data, value, 16); + for (int n=0; n < 8; n++) + data[n] &= 0xfe; + for (int n=8; n < 16; n++) + data[n] |= 0x01; + return Desfire_3des_key_new_with_version (data); +} + +desfirekey_t Desfire_3des_key_new_with_version (const uint8_t value[16]) { + desfirekey_t key = NULL; + key->type = T_3DES; + memcpy (key->data, value, 16); + update_key_schedules (key); + return key; +} + +desfirekey_t Desfire_3k3des_key_new (const uint8_t value[24]) { + uint8_t data[24]; + memcpy (data, value, 24); + for (int n=0; n < 8; n++) + data[n] &= 0xfe; + return Desfire_3k3des_key_new_with_version (data); +} + +desfirekey_t Desfire_3k3des_key_new_with_version (const uint8_t value[24]) { + desfirekey_t key = NULL; + key->type = T_3K3DES; + memcpy (key->data, value, 24); + update_key_schedules (key); + return key; +} + +desfirekey_t Desfire_aes_key_new (const uint8_t value[16]) { + return Desfire_aes_key_new_with_version (value, 0); +} + +desfirekey_t Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version) { + desfirekey_t key = NULL; + memcpy (key->data, value, 16); + key->type = T_AES; + key->aes_version = version; + return key; +} + +uint8_t Desfire_key_get_version (desfirekey_t key) { + uint8_t version = 0; + + for (int n = 0; n < 8; n++) { + version |= ((key->data[n] & 1) << (7 - n)); + } + + return version; +} + +void Desfire_key_set_version (desfirekey_t key, uint8_t version) +{ + for (int n = 0; n < 8; n++) { + uint8_t version_bit = ((version & (1 << (7-n))) >> (7-n)); + key->data[n] &= 0xfe; + key->data[n] |= version_bit; + if (key->type == T_DES) { + key->data[n+8] = key->data[n]; + } else { + // Write ~version to avoid turning a 3DES key into a DES key + key->data[n+8] &= 0xfe; + key->data[n+8] |= ~version_bit; + } + } +} + +desfirekey_t Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey) { + + desfirekey_t key = NULL; + + uint8_t buffer[24]; + + switch (authkey->type) { + case T_DES: + memcpy (buffer, rnda, 4); + memcpy (buffer+4, rndb, 4); + key = Desfire_des_key_new_with_version (buffer); + break; + case T_3DES: + memcpy (buffer, rnda, 4); + memcpy (buffer+4, rndb, 4); + memcpy (buffer+8, rnda+4, 4); + memcpy (buffer+12, rndb+4, 4); + key = Desfire_3des_key_new_with_version (buffer); + break; + case T_3K3DES: + memcpy (buffer, rnda, 4); + memcpy (buffer+4, rndb, 4); + memcpy (buffer+8, rnda+6, 4); + memcpy (buffer+12, rndb+6, 4); + memcpy (buffer+16, rnda+12, 4); + memcpy (buffer+20, rndb+12, 4); + key = Desfire_3k3des_key_new (buffer); + break; + case T_AES: + memcpy (buffer, rnda, 4); + memcpy (buffer+4, rndb, 4); + memcpy (buffer+8, rnda+12, 4); + memcpy (buffer+12, rndb+12, 4); + key = Desfire_aes_key_new (buffer); + break; + } + return key; +} \ No newline at end of file diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h new file mode 100644 index 00000000..ae1249b4 --- /dev/null +++ b/armsrc/desfire_key.h @@ -0,0 +1,10 @@ +#ifndef __DESFIRE_KEY_H +#define __DESFIRE_KEY_H + +#include +#include +#include + +#include "iso14443a.h" +#include "../common/desfire.h" +#endif \ No newline at end of file diff --git a/armsrc/epa.c b/armsrc/epa.c index b0ae5e0d..565019ce 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -13,7 +13,7 @@ #include "iso14443a.h" #include "epa.h" -#include "cmd.h" +#include "../common/cmd.h" // Protocol and Parameter Selection Request // use regular (1x) speed in both directions diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 077b378a..32e0500e 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -9,7 +9,8 @@ // Routines to load the FPGA image, and then to configure the FPGA's major // mode once it is configured. //----------------------------------------------------------------------------- -#include "proxmark3.h" + +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 9181a62e..7d6668eb 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -16,10 +16,10 @@ // (c) 2012 Roel Verdult //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" -#include "hitag2.h" +#include "../include/hitag2.h" #include "string.h" static bool bQuiet; diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 0ff24bfd..6ceb436b 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -36,7 +36,7 @@ // //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" @@ -45,9 +45,11 @@ // Needed for CRC in emulation mode; // same construction as in ISO 14443; // different initial value (CRC_ICLASS) -#include "iso14443crc.h" +#include "../common/iso14443crc.h" +#include "../common/iso15693tools.h" #include "iso15693tools.h" + static int timeout = 4096; @@ -1493,15 +1495,15 @@ void setupIclassReader() // Reader iClass Anticollission void ReaderIClass(uint8_t arg0) { - uint8_t act_all[] = { 0x0a }; - uint8_t identify[] = { 0x0c }; - uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t act_all[] = { 0x0a }; + uint8_t identify[] = { 0x0c }; + uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t readcheck_cc[]= { 0x88, 0x02 }; uint8_t card_data[24]={0}; uint8_t last_csn[8]={0}; - uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes + uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes int read_status= 0; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; @@ -1714,7 +1716,7 @@ void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_ uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes // Reset trace buffer - memset(trace, 0x44, RECV_CMD_OFFSET); + memset(trace, 0x44, RECV_CMD_OFFSET); traceLen = 0; // Setup SSC diff --git a/armsrc/iso14443.c b/armsrc/iso14443.c index 7a445bcb..bc7b9b16 100644 --- a/armsrc/iso14443.c +++ b/armsrc/iso14443.c @@ -10,12 +10,12 @@ // supported. //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" -#include "iso14443crc.h" +#include "../common/iso14443crc.h" //static void GetSamplesFor14443(int weTx, int n); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 9a80a177..f87527ea 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -10,13 +10,12 @@ // Routines to support ISO 14443 type A. //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" -#include "cmd.h" - -#include "iso14443crc.h" +#include "../common/cmd.h" +#include "../common/iso14443crc.h" #include "iso14443a.h" #include "crapto1.h" #include "mifareutil.h" @@ -1787,7 +1786,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { DemodReset(); UartReset(); NextTransferTime = 2*DELAY_ARM2AIR_AS_READER; - iso14a_set_timeout(1050); // 10ms default + iso14a_set_timeout(1050); // 10ms default 10*105 = } int iso14_apdu(uint8_t * cmd, size_t cmd_len, void * data) { @@ -1825,8 +1824,8 @@ void ReaderIso14443a(UsbCommand *c) { iso14a_command_t param = c->arg[0]; uint8_t *cmd = c->d.asBytes; - size_t len = c->arg[1]; - size_t lenbits = c->arg[2]; + size_t len = c->arg[1] & 0xFFFF; + size_t lenbits = c->arg[1] >> 16; uint32_t arg0 = 0; byte_t buf[USB_CMD_DATA_SIZE]; @@ -1850,7 +1849,7 @@ void ReaderIso14443a(UsbCommand *c) } if(param & ISO14A_SET_TIMEOUT) { - iso14a_timeout = c->arg[2]; + iso14a_set_timeout(c->arg[2]); } if(param & ISO14A_APDU) { @@ -1862,9 +1861,10 @@ void ReaderIso14443a(UsbCommand *c) if(param & ISO14A_APPEND_CRC) { AppendCrc14443a(cmd,len); len += 2; - if (lenbits) lenbits += 16; + lenbits += 16; } if(lenbits>0) { + ReaderTransmitBitsPar(cmd,lenbits,GetParity(cmd,lenbits/8), NULL); } else { ReaderTransmit(cmd,len, NULL); @@ -2206,12 +2206,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (MF_DBGLEVEL >= 1) { if (!_7BUID) { - Dbprintf("4B UID: %02x%02x%02x%02x", - rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); + Dbprintf("4B UID: %02x%02x%02x%02x",rUIDBCC1[0] , rUIDBCC1[1] , rUIDBCC1[2] , rUIDBCC1[3]); } else { - Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x", - rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], - rUIDBCC2[0], rUIDBCC2[1] ,rUIDBCC2[2], rUIDBCC2[3]); + Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x",rUIDBCC1[0] , rUIDBCC1[1] , rUIDBCC1[2] , rUIDBCC1[3],rUIDBCC2[0],rUIDBCC2[1] ,rUIDBCC2[2] , rUIDBCC2[3]); } } @@ -2321,9 +2318,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // test if auth OK if (cardRr != prng_successor(nonce, 64)){ - if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x", - cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', - cardRr, prng_successor(nonce, 64)); + if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED. cardRr=%08x, succ=%08x",cardRr, prng_successor(nonce, 64)); // Shouldn't we respond anything here? // Right now, we don't nack or anything, which causes the // reader to do a WUPA after a while. /Martin diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 6d18515f..3c3993ba 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -12,7 +12,7 @@ #ifndef __ISO14443A_H #define __ISO14443A_H -#include "common.h" +#include "../include/common.h" #include "mifaresniff.h" // mifare reader over DMA buffer (SnoopIso14443a())!!! diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index ed7beb6f..39d9effb 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -58,12 +58,12 @@ // *) document all the functions -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "util.h" #include "apps.h" #include "string.h" -#include "iso15693tools.h" -#include "cmd.h" +#include "../common/iso15693tools.h" +#include "../common/cmd.h" #define arraylen(x) (sizeof(x)/sizeof((x)[0])) @@ -1275,12 +1275,8 @@ void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8 recvlen=SendDataTag(data,datalen,1,speed,(recv?&recvbuf:NULL)); if (recv) { -// n.cmd=/* CMD_ISO_15693_COMMAND_DONE */ CMD_ACK; -// n.arg[0]=recvlen>48?48:recvlen; -// memcpy(n.d.asBytes, recvbuf, 48); LED_B_ON(); cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48); -// UsbSendPacket((uint8_t *)&n, sizeof(n)); LED_B_OFF(); if (DEBUG) { diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 3fbdf5cb..0e63ef5e 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -8,14 +8,14 @@ // LEGIC RF simulation code //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" #include "legicrf.h" -#include "legic_prng.h" -#include "crc.h" +#include "../include/legic_prng.h" +#include "../common/crc.h" static struct legic_frame { int bits; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 6b131c26..11fc8c50 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -8,12 +8,14 @@ // Also routines for raw mode reading/simulating of LF waveform //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" -#include "hitag2.h" -#include "crc16.h" +#include "../include/hitag2.h" +#include "../common/crc16.h" #include "string.h" +#include "crapto1.h" +#include "mifareutil.h" void LFSetupFPGAForADC(int divisor, bool lf_field) { @@ -1146,6 +1148,15 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) #define WRITE_0 144 // 192 #define WRITE_1 400 // 432 for T55x7; 448 for E5550 +// VALUES TAKEN FROM EM4x function: SendForward +// START_GAP = 440; //(55*8) +// WRITE_GAP = 128; //(16*8) +// WRITE_1 = 256 32*8; //32 cycles at 125Khz (8us each) 1 +// //These timings work for 4469/4269/4305 (with the 55*8 above) +// WRITE_0 = 23*8 , 9*8 SpinDelayUs(23*8); // (8us each) 0 + + + // Write one bit to card void T55xxWriteBit(int bit) { @@ -1207,13 +1218,15 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod // Read one card block in page 0 void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode) { - uint8_t *dest = (uint8_t *)BigBuf; - int m=0, i=0; + uint8_t *dest = mifare_get_bigbufptr(); + uint16_t bufferlength = 16000; + uint32_t i = 0; + + // Clear destination buffer before sending the command 0x80 = average. + memset(dest, 0x80, bufferlength); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - m = sizeof(BigBuf); - // Clear destination buffer before sending the command - memset(dest, 128, m); + // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Now set up the SSC to get the ADC samples that are now streaming at us. @@ -1254,31 +1267,33 @@ void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode) for(;;) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = 0x43; + LED_D_ON(); } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - // we don't care about actual value, only if it's more or less than a - // threshold essentially we capture zero crossings for later analysis - // if(dest[i] < 127) dest[i] = 0; else dest[i] = 1; - i++; - if (i >= m) break; + LED_D_OFF(); + ++i; + if (i > bufferlength) break; } } + + cmd_send(CMD_ACK,0,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); - DbpString("DONE!"); } // Read card traceability data (page 1) void T55xxReadTrace(void){ - uint8_t *dest = (uint8_t *)BigBuf; - int m=0, i=0; + uint8_t *dest = mifare_get_bigbufptr(); + uint16_t bufferlength = 16000; + int i=0; + + // Clear destination buffer before sending the command 0x80 = average + memset(dest, 0x80, bufferlength); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - m = sizeof(BigBuf); - // Clear destination buffer before sending the command - memset(dest, 128, m); + // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Now set up the SSC to get the ADC samples that are now streaming at us. @@ -1309,17 +1324,20 @@ void T55xxReadTrace(void){ for(;;) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = 0x43; + LED_D_ON(); } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - if (i >= m) break; + LED_D_OFF(); + ++i; + if (i >= bufferlength) break; } } + cmd_send(CMD_ACK,0,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); - DbpString("DONE!"); } /*-------------- Cloning routines -----------*/ @@ -1763,7 +1781,6 @@ int IsBlock1PCF7931(uint8_t *Block) { return 0; } - #define ALLOC 16 void ReadPCF7931() { @@ -2023,6 +2040,7 @@ void SendForward(uint8_t fwd_bit_count) { } } + void EM4xLogin(uint32_t Password) { uint8_t fwd_bit_count; @@ -2040,9 +2058,14 @@ void EM4xLogin(uint32_t Password) { void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { + uint8_t *dest = mifare_get_bigbufptr(); + uint16_t bufferlength = 16000; + uint32_t i = 0; + + // Clear destination buffer before sending the command 0x80 = average. + memset(dest, 0x80, bufferlength); + uint8_t fwd_bit_count; - uint8_t *dest = (uint8_t *)BigBuf; - int m=0, i=0; //If password mode do login if (PwdMode == 1) EM4xLogin(Pwd); @@ -2051,9 +2074,6 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { fwd_bit_count = Prepare_Cmd( FWD_CMD_READ ); fwd_bit_count += Prepare_Addr( Address ); - m = sizeof(BigBuf); - // Clear destination buffer before sending the command - memset(dest, 128, m); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Now set up the SSC to get the ADC samples that are now streaming at us. @@ -2069,10 +2089,12 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) { } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - if (i >= m) break; + ++i; + if (i >= bufferlength) break; } } + + cmd_send(CMD_ACK,0,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off LED_D_OFF(); } diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 42dee56e..7e3e9293 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2,6 +2,9 @@ // Merlok - June 2011, 2012 // Gerhard de Koning Gans - May 2008 // Hagen Fritsch - June 2010 +// Midnitesnake - Dec 2013 +// Andy Davies - Apr 2014 +// Iceman - May 2014 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -12,9 +15,12 @@ #include "mifarecmd.h" #include "apps.h" +#include "util.h" +#include "desfire.h" +#include "../common/crc.h" //----------------------------------------------------------------------------- -// Select, Authenticate, Read a MIFARE tag. +// Select, Authenticaate, Read an MIFARE tag. // read block //----------------------------------------------------------------------------- void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) @@ -36,8 +42,6 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // clear trace iso14a_clear_trace(); -// iso14a_set_tracing(false); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); LED_A_ON(); @@ -78,11 +82,71 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); LED_B_OFF(); - // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); -// iso14a_set_tracing(TRUE); +} + + +void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){ + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16]; + uint8_t uid[10]; + uint32_t cuid; + + // clear trace + iso14a_clear_trace(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + + if(!iso14443a_select_card(uid, NULL, &cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card, something went wrong before auth"); + }; + + if(mifare_ultra_auth1(cuid, dataoutbuf)){ + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part1: Fail."); + } + isOK=1; + if (MF_DBGLEVEL >= 2) DbpString("AUTH 1 FINISHED"); + + LED_B_ON(); + cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11); + LED_B_OFF(); + + // Thats it... + LEDsoff(); +} +void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){ + // params + uint32_t cuid = arg0; + uint8_t key[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16]; + + memcpy(key, datain, 16); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + if(mifare_ultra_auth2(cuid, key, dataoutbuf)){ + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part2: Fail..."); + } + isOK=1; + if (MF_DBGLEVEL >= 2) DbpString("AUTH 2 FINISHED"); + + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } void MifareUReadBlock(uint8_t arg0,uint8_t *datain) @@ -126,20 +190,13 @@ void MifareUReadBlock(uint8_t arg0,uint8_t *datain) if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); - // add trace trailer - memset(uid, 0x44, 4); - LogTrace(uid, 4, 0, 0, TRUE); LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); LED_B_OFF(); - - - // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } - //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) @@ -153,7 +210,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) ui64Key = bytes_to_num(datain, 6); // variables - byte_t isOK; + byte_t isOK = 0; byte_t dataoutbuf[16 * 16]; uint8_t uid[10]; uint32_t cuid; @@ -163,7 +220,6 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // clear trace iso14a_clear_trace(); -// iso14a_set_tracing(false); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -195,7 +251,6 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); } - // ----------------------------- crypto1 destroy crypto1_destroy(pcs); @@ -208,40 +263,40 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); -// iso14a_set_tracing(TRUE); } - -void MifareUReadCard(uint8_t arg0, uint8_t *datain) +void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain) { // params uint8_t sectorNo = arg0; - + int Pages=arg1; + int count_Pages=0; // variables byte_t isOK = 0; - byte_t dataoutbuf[16 * 4]; + byte_t dataoutbuf[44 * 4]; uint8_t uid[10]; uint32_t cuid; // clear trace iso14a_clear_trace(); -// iso14a_set_tracing(false); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - + Dbprintf("Pages %d",Pages); while (true) { if(!iso14443a_select_card(uid, NULL, &cuid)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); break; }; - for(int sec=0;sec<16;sec++){ + for(int sec=0;sec= 1) Dbprintf("Read block %d error",sec); break; + }else{ + count_Pages++; }; } if(mifare_ultra_halt(cuid)) { @@ -252,11 +307,13 @@ void MifareUReadCard(uint8_t arg0, uint8_t *datain) isOK = 1; break; } - + Dbprintf("Pages read %d",count_Pages); if (MF_DBGLEVEL >= 2) DbpString("READ CARD FINISHED"); LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64); + if (Pages==16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64); + if (Pages==44 && count_Pages==16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,64); + if (Pages==44 && count_Pages>16) cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,176); LED_B_OFF(); // Thats it... @@ -291,7 +348,6 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // clear trace iso14a_clear_trace(); -// iso14a_set_tracing(false); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -337,11 +393,8 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); -// iso14a_set_tracing(TRUE); - } - void MifareUWriteBlock(uint8_t arg0, uint8_t *datain) { // params @@ -358,7 +411,6 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t *datain) // clear trace iso14a_clear_trace(); - // iso14a_set_tracing(false); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -399,7 +451,6 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t *datain) // iso14a_set_tracing(TRUE); } - void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) { // params @@ -415,7 +466,6 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) // clear trace iso14a_clear_trace(); - // iso14a_set_tracing(false); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -449,15 +499,11 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain) cmd_send(CMD_ACK,isOK,0,0,0,0); LED_B_OFF(); - // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); -// iso14a_set_tracing(TRUE); - } - // Return 1 if the nonce is invalid else return 0 int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) { return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ @@ -757,7 +803,6 @@ void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai Dbprintf("Debug level: %d", MF_DBGLEVEL); } - //----------------------------------------------------------------------------- // Work with emulator memory // @@ -766,14 +811,11 @@ void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) emlClearMem(); } - void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ emlSetMem(datain, arg0, arg1); // data, block num, blocks count } - void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - byte_t buf[48]; emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) @@ -782,7 +824,6 @@ void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) LED_B_OFF(); } - //----------------------------------------------------------------------------- // Load a card into the emulator memory // diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 3c00a343..2c5a7e3f 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -13,16 +13,15 @@ #ifndef __MIFARECMD_H #define __MIFARECMD_H -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" -#include "iso14443crc.h" +#include "../common/iso14443crc.h" #include "iso14443a.h" #include "crapto1.h" #include "mifareutil.h" -#include "common.h" - +#include "../include/common.h" #endif \ No newline at end of file diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c new file mode 100644 index 00000000..60f5ec03 --- /dev/null +++ b/armsrc/mifaredesfire.c @@ -0,0 +1,585 @@ +#include "mifaredesfire.h" + +#define MAX_APPLICATION_COUNT 28 +#define MAX_FILE_COUNT 16 +#define MAX_FRAME_SIZE 60 +#define NOT_YET_AUTHENTICATED 255 +#define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5) + +// the block number for the ISO14443-4 PCB +uint8_t pcb_blocknum = 0; +// Deselect card by sending a s-block. the crc is precalced for speed +static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; + +//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 }; +/* PCB CID CMD PAYLOAD */ +//static uint8_t __res[MAX_FRAME_SIZE]; + +bool InitDesfireCard(){ + + // Make sure it is off. +// FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +// SpinDelay(300); + + byte_t cardbuf[USB_CMD_DATA_SIZE]; + memset(cardbuf,0,sizeof(cardbuf)); + + iso14a_set_tracing(TRUE); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf; + int len = iso14443a_select_card(NULL,card,NULL); + + if (!len) { + if (MF_DBGLEVEL >= 1) { + Dbprintf("Can't select card"); + } + OnError(); + return false; + } + return true; +} + +// ARG0 flag enums +enum { + NONE = 0x00, + INIT = 0x01, + DISCONNECT = 0x02, + FOO = 0x04, + BAR = 0x08, +} CmdOptions ; + +void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ + + /* ARG0 contains flags. + 0x01 = init card. + 0x02 = No Disconnect + 0x03 + */ + uint8_t flags = arg0; + size_t datalen = arg1; + uint8_t resp[RECV_RES_SIZE]; + memset(resp,0,sizeof(resp)); + + if (MF_DBGLEVEL >= 4) { + Dbprintf(" flags : %02X", flags); + Dbprintf(" len : %02X", datalen); + print_result(" RX : ", datain, datalen); + } + + if ( flags & INIT ){ + if ( !InitDesfireCard() ) + return; + } + + int len = DesfireAPDU(datain, datalen, resp); + print_result(" <--: ", resp, len); + if ( !len ) { + if (MF_DBGLEVEL >= 4) { + print_result("ERR <--: ", resp, len); + } + OnError(); + return; + } + + // reset the pcb_blocknum, + pcb_blocknum = 0; + + if ( flags & DISCONNECT ) + OnSuccess(); + + cmd_send(CMD_ACK,1,len,0,resp,len); +} + +void MifareDesfireGetInformation(){ + + int len = 0; + uint8_t resp[USB_CMD_DATA_SIZE]; + uint8_t dataout[USB_CMD_DATA_SIZE]; + byte_t cardbuf[USB_CMD_DATA_SIZE]; + + memset(resp,0,sizeof(resp)); + memset(dataout,0, sizeof(dataout)); + memset(cardbuf,0,sizeof(cardbuf)); + + /* + 1 = PCB 1 + 2 = cid 2 + 3 = desfire command 3 + 4-5 = crc 4 key + 5-6 crc + PCB == 0x0A because sending CID byte. + CID == 0x00 first card? + */ + iso14a_clear_trace(); + iso14a_set_tracing(TRUE); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // card select - information + iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf; + byte_t isOK = iso14443a_select_card(NULL, card, NULL); + if (isOK != 1) { + if (MF_DBGLEVEL >= 1) { + Dbprintf("Can't select card"); + } + OnError(); + return; + } + + memcpy(dataout,card->uid,7); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + uint8_t cmd[] = {GET_VERSION}; + size_t cmd_len = sizeof(cmd); + + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { + print_result("ERROR <--: ", resp, len); + OnError(); + return; + } + + LED_A_OFF(); + LED_B_ON(); + memcpy(dataout+7,resp+3,7); + + // ADDITION_FRAME 1 + cmd[0] = ADDITIONAL_FRAME; + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { + print_result("ERROR <--: ", resp, len); + OnError(); + return; + } + + LED_B_OFF(); + LED_C_ON(); + memcpy(dataout+7+7,resp+3,7); + + // ADDITION_FRAME 2 + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { + print_result("ERROR <--: ", resp, len); + OnError(); + return; + } + + memcpy(dataout+7+7+7,resp+3,14); + + cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); + + // reset the pcb_blocknum, + pcb_blocknum = 0; + OnSuccess(); +} + +void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){ + + uint8_t null_key_data[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + //uint8_t new_key_data[8] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; + int res = 0; + + desfirekey_t default_key = Desfire_des_key_new_with_version (null_key_data); + + // res = Desfire_select_application (tags[i], aid); + if (res < 0) { + print_result("default key: ", default_key->data, 24 ); + return; + } + + return; + // pcb cid cmd key crc1 cr2 + //uint8_t cmd2[] = {0x02,0x00,GET_KEY_VERSION, 0x00, 0x00, 0x00 }; + + //uint8_t* bigbuffer = mifare_get_bigbufptr(); + byte_t isOK = 1; + uint8_t resp[256]; + uint8_t key[24]; + uint8_t IV[16]; + + // första byten håller keylength. + uint8_t keylen = datain[0]; + memcpy(key, datain+1, keylen); + + if (MF_DBGLEVEL >= 1) { + + Dbprintf("MODE: %d", mode); + Dbprintf("ALGO: %d", algo); + Dbprintf("KEYNO: %d", keyno); + Dbprintf("KEYLEN: %d", keylen); + + print_result("KEY", key, keylen); + } + + // card select - information + byte_t buf[USB_CMD_DATA_SIZE]; + iso14a_card_select_t *card = (iso14a_card_select_t*)buf; + + // test of DES on ARM side. + /* + if ( mode == 1){ + uint8_t IV[8]; + uint8_t plain[16]; + uint8_t encData[16]; + + uint8_t tmpData[8]; + uint8_t tmpPlain[8]; + + memset(IV, 0, 8); + memset(tmpData, 0 ,8); + memset(tmpPlain,0 ,8); + memcpy(key, datain, 8); + memcpy(plain, datain+30, 16); + + for(uint8_t i=0; i< sizeof(plain); i=i+8 ){ + + memcpy(tmpPlain, plain+i, 8); + des_enc( &tmpData, &tmpPlain, &key); + memcpy(encData+i, tmpData, 8); + } + } +*/ + + iso14a_clear_trace(); + + iso14a_set_tracing(TRUE); + + // power up the field + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // select the card + isOK = iso14443a_select_card(resp, card, NULL); + if (isOK != 1) { + if (MF_DBGLEVEL >= 1) { + Dbprintf("CAN'T SELECT CARD, SOMETHING WENT WRONG BEFORE AUTH"); + } + OnError(); + return; + } + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) + // 4 olika crypto algo DES, 3DES, 3K3DES, AES + // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO + + // des, nyckel 0, + switch (mode){ + case 1: + // if ( SendDesfireCommand(AUTHENTICATE, &keyno, resp) > 0 ){ + // // fick nonce från kortet + // } + break; + case 2: + //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); + break; + case 3:{ + AesCtx ctx; + if ( AesCtxIni(&ctx, IV, key, KEY128, CBC) < 0 ){ + if (MF_DBGLEVEL >= 1) { + Dbprintf("AES context failed to init"); + } + OnError(); + return; + } + uint8_t real_cmd[6]; + real_cmd[0] = 0x90; + real_cmd[1] = 0x02; + real_cmd[2] = AUTHENTICATE_AES; + real_cmd[3] = keyno; + + AppendCrc14443a(real_cmd, 4); + ReaderTransmit(real_cmd, sizeof(real_cmd), NULL); + + int len = ReaderReceive(resp); + if(!len) { + OnError(); + return; + } + + print_result("RX:", resp, len); + + enum DESFIRE_STATUS status = resp[1]; + if ( status != ADDITIONAL_FRAME) { + OnError(); + return; + } + + // tags enc nonce + uint8_t encRndB[16]; + uint8_t decRndB[16]; + uint8_t nonce[16]; + uint8_t both[32]; + uint8_t encBoth[32]; + + memset(nonce, 0, 16); + memcpy( encRndB, resp+2, 16); + + // dekryptera tagnonce. + AesDecrypt(&ctx, encRndB, decRndB, 16); + + rol(decRndB,16); + + memcpy(both, nonce,16); + memcpy(both+16, decRndB ,16 ); + + AesEncrypt(&ctx, both, encBoth, 32 ); + + uint8_t real_cmd_A[36]; + real_cmd_A[0] = 0x03; + real_cmd_A[1] = ADDITIONAL_FRAME; + + memcpy(real_cmd_A+2, encBoth, sizeof(encBoth) ); + AppendCrc14443a(real_cmd_A, 34); + ReaderTransmit(real_cmd_A, sizeof(real_cmd_A), NULL); + + len = ReaderReceive(resp); + + print_result("Auth1a ", resp, 36); + + status = resp[1]; + if ( status != OPERATION_OK) { + Dbprintf("Cmd Error: %02x Len: %d", status,len); + OnError(); + return; + } + + break; + } + + } + + OnSuccess(resp); +} + +// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) +// cmd = cmd bytes to send +// cmd_len = length of cmd +// dataout = pointer to response data array +int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ + + uint32_t status = 0; + size_t wrappedLen = 0; + uint8_t wCmd[USB_CMD_DATA_SIZE]; + + wrappedLen = CreateAPDU( cmd, cmd_len, wCmd); + + if (MF_DBGLEVEL >= 4) { + print_result("WCMD <--: ", wCmd, wrappedLen); + } + ReaderTransmit( wCmd, wrappedLen, NULL); + + status = ReaderReceive(dataout); + + if(!status){ + return FALSE; //DATA LINK ERROR + } + // if we received an I- or R(ACK)-Block with a block number equal to the + // current block number, toggle the current block number + else if (status >= 4 // PCB+CID+CRC = 4 bytes + && ((dataout[0] & 0xC0) == 0 // I-Block + || (dataout[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 + && (dataout[0] & 0x01) == pcb_blocknum) // equal block numbers + { + pcb_blocknum ^= 1; //toggle next block + } + return status; +} + +// CreateAPDU +size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){ + + size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); + + uint8_t cmd[cmdlen]; + memset(cmd, 0, cmdlen); + + cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar // + cmd[0] |= pcb_blocknum; // OR the block number into the PCB + cmd[1] = 0x00; // CID: 0x00 //FIXME: allow multiple selected cards + + memcpy(cmd+2, datain, len); + AppendCrc14443a(cmd, len+2); + + memcpy(dataout, cmd, cmdlen); + + return cmdlen; +} + + // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ + // crc_update(&desfire_crc32, addr, addr_sz); + // crc_update(&desfire_crc32, byte, 8); + // uint32_t crc = crc_finish(&desfire_crc32); + + + /* Version + + //uint8_t versionCmd1[] = {0x02, 0x60}; + //uint8_t versionCmd2[] = {0x03, 0xaf}; + //uint8_t versionCmd3[] = {0x02, 0xaf}; + + // AUTH 1 - CMD: 0x02, 0x0A, 0x00 = Auth + // 0x02 = status byte för simpla svar?!? + // 0x0a = krypto typ + // 0x00 = key nr + //uint8_t initAuthCmdDES[] = {0x02, 0x0a, 0x00}; // DES + //uint8_t initAuthCmd3DES[] = {0x02, 0x1a, 0x00}; // 3DES + //uint8_t initAuthCmdAES[] = {0x02, 0xaa, 0x00}; // AES + // auth 1 - answer command + // 0x03 = status byte för komplexa typer? + // 0xaf = additional frame + // LEN = 1+1+32+2 = 36 + //uint8_t answerAuthCmd[34] = {0x03, 0xaf}; + + // Lägg till CRC + //AppendCrc14443a(versionCmd1,sizeof(versionCmd1)); +*/ + + // Sending commands + /*ReaderTransmit(versionCmd1,sizeof(versionCmd1)+2, NULL); + len = ReaderReceive(buffer); + print_result("Get Version 3", buffer, 9); + */ + + // for( int i = 0; i < 8; i++){ + // // Auth 1 - Request authentication + // ReaderTransmit(initAuthCmdAES,sizeof(initAuthCmdAES)+2, NULL); + // //len = ReaderReceive(buffer); + + // // 0xAE = authentication error + // if (buffer[1] == 0xae) { + // Dbprintf("Cmd Error: %02x", buffer[1]); + // OnError(); + // return; + // } + + // // tags enc nonce + // memcpy(encRndB, buffer+2, 16); + + // // dekryptera svaret från tag. + // AesDecrypt(&ctx, encRndB, decRndB, 16); + + // rol8(decRndB,16); + // memcpy(RndARndB, RndA,16); + // memcpy(RndARndB+16, decRndB ,16 ); + + // AesEncrypt(&ctx, RndARndB, encRndARndB, 32 ); + + // memcpy(answerAuthCmd+2, encRndARndB, 32); + // AppendCrc14443a(answerAuthCmd,sizeof(answerAuthCmd)); + + // ReaderTransmit(answerAuthCmd,sizeof(answerAuthCmd)+2, NULL); + + // len = ReaderReceive(buffer); + + // print_result("Auth1a ", buffer, 8); + // Dbprintf("Rx len: %02x", len); + + // if (buffer[1] == 0xCA) { + // Dbprintf("Cmd Error: %02x Len: %d", buffer[1],len); + // cmd_send(CMD_ACK,0,0,0,0,0); + // key[1] = i; + // AesCtxIni(&ctx, iv, key, KEY128, CBC); + // } + // } + + //des_dec(decRndB, encRndB, key); + + //Do crypto magic + /* + DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0); + memcpy(RndARndB,RndA,8); + memcpy(RndARndB+8,RndB,8); + PrintAndLog(" RA+B:%s",sprint_hex(RndARndB, 16)); + DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1); + PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB, 16)); + */ + + +int mifare_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ + + uint8_t* buffer = mifare_get_bigbufptr(); + uint8_t dcmd[19]; + + dcmd[0] = 0xAF; + memcpy(dcmd+1,key,16); + AppendCrc14443a(dcmd, 17); + + + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(buffer); + if(!len) { + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); + len = ReaderReceive(buffer); + } + + if(len==1) { + if (MF_DBGLEVEL >= 1) { + Dbprintf("NAK - Authentication failed."); + Dbprintf("Cmd Error: %02x", buffer[0]); + } + return 1; + } + + if (len == 11){ + if (MF_DBGLEVEL >= 1) { + Dbprintf("Auth2 Resp: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + buffer[0],buffer[1],buffer[2],buffer[3],buffer[4], + buffer[5],buffer[6],buffer[7],buffer[8],buffer[9], + buffer[10]); + } + return 0; + } + return 1; +} + +void MifareDES_Auth2(uint32_t arg0, uint8_t *datain){ + + return; + uint32_t cuid = arg0; + uint8_t key[16]; + + byte_t isOK = 0; + byte_t dataoutbuf[16]; + + memset(key, 0, 16); + memcpy(key, datain, 16); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + if(mifare_des_auth2(cuid, key, dataoutbuf)){ + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication part2: Fail..."); + } + isOK=1; + if (MF_DBGLEVEL >= 2) DbpString("AUTH 2 FINISHED"); + + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11); + LED_B_OFF(); + + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +void OnSuccess(){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +void OnError(){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,0,0,0,0); + LEDsoff(); +} diff --git a/armsrc/mifaredesfire.h b/armsrc/mifaredesfire.h new file mode 100644 index 00000000..fc661f22 --- /dev/null +++ b/armsrc/mifaredesfire.h @@ -0,0 +1,15 @@ +#ifndef __MIFAREDESFIRE_H +#define __MIFAREDESFIRE_H + +#include "../include/proxmark3.h" +#include "apps.h" +#include "util.h" +#include "string.h" + +#include "../common/iso14443crc.h" +#include "iso14443a.h" +#include "crapto1.h" +#include "mifareutil.h" +#include "../include/common.h" + +#endif diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index 1065fa61..3ee64f35 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -11,16 +11,16 @@ #ifndef __MIFARESNIFF_H #define __MIFARESNIFF_H -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" -#include "iso14443crc.h" +#include "../common/iso14443crc.h" #include "iso14443a.h" #include "crapto1.h" #include "mifareutil.h" -#include "common.h" +#include "../include/common.h" #define SNF_INIT 0 #define SNF_NO_FIELD 1 diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 0b93db8f..537720df 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -9,12 +9,12 @@ // Work with mifare cards. //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" #include "util.h" #include "string.h" -#include "iso14443crc.h" +#include "../common/iso14443crc.h" #include "iso14443a.h" #include "crapto1.h" #include "mifareutil.h" @@ -84,26 +84,36 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *timing) { - uint8_t dcmd[8];//, ecmd[4]; - //uint32_t par=0; - + uint8_t dcmd[8]; dcmd[0] = cmd; - dcmd[1] = data[0]; - dcmd[2] = data[1]; - dcmd[3] = data[2]; - dcmd[4] = data[3]; - dcmd[5] = data[4]; + memcpy(dcmd+1,data,5); AppendCrc14443a(dcmd, 6); - //Dbprintf("Data command: %02x", dcmd[0]); - //Dbprintf("Data R: %02x %02x %02x %02x %02x %02x %02x", dcmd[1],dcmd[2],dcmd[3],dcmd[4],dcmd[5],dcmd[6],dcmd[7]); - - //memcpy(ecmd, dcmd, sizeof(dcmd)); ReaderTransmit(dcmd, sizeof(dcmd), NULL); int len = ReaderReceive(answer); - if(!len) - { + if(!len) { if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); return 2; + } + return len; +} + +int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint32_t *timing) +{ + uint8_t dcmd[19]; + int len; + dcmd[0] = cmd; + memcpy(dcmd+1,data,16); + AppendCrc14443a(dcmd, 17); + + ReaderTransmit(dcmd, sizeof(dcmd), timing); + len = ReaderReceive(answer); + if(!len) { + if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout."); + len = ReaderReceive(answer); + } + if(len==1) { + if (MF_DBGLEVEL >= 1) Dbprintf("NAK - Authentication failed."); + return 1; } return len; } @@ -280,6 +290,55 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo memcpy(blockData, receivedAnswer, 16); return 0; +} + +int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){ + // variables + int len; + + uint8_t* receivedAnswer = mifare_get_bigbufptr(); + + // command MIFARE_CLASSIC_READBLOCK + len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,NULL); + if (len == 1) { + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len == 11) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], + receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], + receivedAnswer[10]); + memcpy(blockData, receivedAnswer, 11); + return 0; + } + //else something went wrong??? + return 1; +} + +int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ + // variables + int len; + + uint8_t* receivedAnswer = mifare_get_bigbufptr(); + + + // command MIFARE_CLASSIC_READBLOCK + len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer,NULL); + if (len == 1) { + if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len == 11){ + if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], + receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], + receivedAnswer[10]); + memcpy(blockData, receivedAnswer, 11); + return 0; + } + //something went wrong? + return 1; } int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 8708d3dd..f9d74384 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -56,6 +56,7 @@ extern int MF_DBGLEVEL; uint8_t* mifare_get_bigbufptr(void); int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing); int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* amswer, uint8_t *timing); +int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* amswer, uint32_t *timing); int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \ @@ -63,6 +64,8 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, \ uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_ultra_auth1(uint32_t cuid, uint8_t *blockData); +int mifare_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData); int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData); diff --git a/armsrc/start.c b/armsrc/start.c index d7332bda..3f5dc676 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -9,7 +9,7 @@ // with the linker script. //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "apps.h" extern char __data_start__, __data_src_start__, __data_end__, __bss_start__, __bss_end__; diff --git a/armsrc/string.c b/armsrc/string.c index cc71276c..945a4cf6 100644 --- a/armsrc/string.c +++ b/armsrc/string.c @@ -48,6 +48,11 @@ int memcmp(const void *av, const void *bv, int len) return 0; } +void memxor(uint8_t * dest, uint8_t * src, size_t len) { + for( ; len > 0; len--,dest++,src++) + *dest ^= *src; +} + int strlen(const char *str) { int l = 0; diff --git a/armsrc/string.h b/armsrc/string.h index 46ee218d..1067b91f 100644 --- a/armsrc/string.h +++ b/armsrc/string.h @@ -12,10 +12,14 @@ #ifndef __STRING_H #define __STRING_H +#include +#include + int strlen(const char *str); void *memcpy(void *dest, const void *src, int len); void *memset(void *dest, int c, int len); int memcmp(const void *av, const void *bv, int len); +void memxor(uint8_t * dest, uint8_t * src, size_t len); char *strncat(char *dest, const char *src, unsigned int n); char *strcat(char *dest, const char *src); void strreverse(char s[]); diff --git a/armsrc/util.c b/armsrc/util.c index 2d3aab9c..f20e4b42 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -8,11 +8,31 @@ // Utility functions used in many places, not specific to any piece of code. //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include "util.h" #include "string.h" #include "apps.h" + + +void print_result(char *name, uint8_t *buf, size_t len) { + uint8_t *p = buf; + + if ( len % 16 == 0 ) { + for(; p-buf < len; p += 16) + Dbprintf("[%s:%02x/%02x] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + name, + p-buf, + len, + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] + ); + } + else { + for(; p-buf < len; p += 8) + Dbprintf("[%s:%02x/%02x] %02x %02x %02x %02x %02x %02x %02x %02x", name, p-buf, len, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + } +} + size_t nbytes(size_t nbits) { return (nbits/8)+((nbits%8)>0); } @@ -45,6 +65,26 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) return num; } +// RotateLeft - Ultralight, Desfire +void rol(uint8_t *data, const size_t len){ + uint8_t first = data[0]; + for (size_t i = 0; i < len-1; i++) { + data[i] = data[i+1]; + } + data[len-1] = first; +} +void lsl (uint8_t *data, size_t len) { + for (size_t n = 0; n < len - 1; n++) { + data[n] = (data[n] << 1) | (data[n+1] >> 7); + } + data[len - 1] <<= 1; +} + +int32_t le24toh (uint8_t data[3]) +{ + return (data[2] << 16) | (data[1] << 8) | data[0]; +} + void LEDsoff() { LED_A_OFF(); diff --git a/armsrc/util.h b/armsrc/util.h index e8b9cdff..c6503395 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -13,7 +13,7 @@ #include #include -#include +#include "../include/common.h" #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) @@ -27,10 +27,14 @@ #define BUTTON_DOUBLE_CLICK -2 #define BUTTON_ERROR -99 +void print_result(char *name, uint8_t *buf, size_t len); size_t nbytes(size_t nbits); uint32_t SwapBits(uint32_t value, int nrbits); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); +void rol(uint8_t *data, const size_t len); +void lsl (uint8_t *data, size_t len); +int32_t le24toh (uint8_t data[3]); void SpinDelay(int ms); void SpinDelayUs(int us); diff --git a/client/Makefile b/client/Makefile index 05ffc667..1aa801ee 100644 --- a/client/Makefile +++ b/client/Makefile @@ -13,14 +13,14 @@ CXX=g++ VPATH = ../common OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread ../liblua/liblua.a +LDLIBS = -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lcrypto -lgdi32 LDFLAGS = $(COMMON_FLAGS) -CFLAGS = -std=c99 -lcrypto -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 +CFLAGS = -std=c99 -I. -I../include -I../common -I/mingw/include -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4 $(ICE_FLAGS) LUAPLATFORM = generic ifneq (,$(findstring MINGW,$(platform))) -CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4 +CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets +QTLDLIBS = -L$(QTDIR)/lib -lQt5Core -lQt5Gui -lQt5Widgets MOC = $(QTDIR)/bin/moc LUAPLATFORM = mingw else ifeq ($(platform),Darwin) @@ -56,12 +56,12 @@ CORESRCS = uart.c \ CMDSRCS = nonce2key/crapto1.c\ nonce2key/crypto1.c\ nonce2key/nonce2key.c\ - loclass/cipher.c \ - loclass/cipherutils.c \ - loclass/des.c \ - loclass/ikeys.c \ - loclass/elite_crack.c\ - loclass/fileutils.c\ + loclass/cipher.c \ + loclass/cipherutils.c \ + loclass/des.c \ + loclass/ikeys.c \ + loclass/elite_crack.c\ + loclass/fileutils.c\ mifarehost.c\ crc16.c \ iso14443crc.c \ @@ -78,6 +78,9 @@ CMDSRCS = nonce2key/crapto1.c\ cmdhflegic.c \ cmdhficlass.c \ cmdhfmf.c \ + cmdhfmfu.c \ + cmdhfmfdes.c \ + cmdhfdes.c \ cmdhw.c \ cmdlf.c \ cmdlfio.c \ diff --git a/client/cmddata.c b/client/cmddata.c index fa54d01a..72bc52e6 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -588,13 +588,16 @@ int CmdManchesterDemod(const char *Cmd) } } + PrintAndLog("Clock: %d", clock); + /* If we're not working with 1/0s, demod based off clock */ if (high != 1) { + PrintAndLog("Entering path A"); bit = 0; /* We assume the 1st bit is zero, it may not be * the case: this routine (I think) has an init problem. * Ed. - */ + */ for (; i < (int)(GraphTraceLen / clock); i++) { hithigh = 0; diff --git a/client/cmdhf.c b/client/cmdhf.c index d955fc83..dda0a669 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -22,6 +22,9 @@ #include "cmdhflegic.h" #include "cmdhficlass.h" #include "cmdhfmf.h" +#include "cmdhfmfu.h" +#include "cmdhfmfdes.h" +#include "cmdhfdes.h" static int CmdHelp(const char *Cmd); @@ -42,6 +45,9 @@ static command_t CommandTable[] = {"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"des", CmdHFDES, 0, "{ MIFARE DESfire}"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 39bdcf40..bd19cee4 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -14,15 +14,15 @@ #include #include #include "util.h" -#include "iso14443crc.h" +#include "../common/iso14443crc.h" #include "data.h" #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" #include "cmdhf14a.h" -#include "common.h" +#include "../include/common.h" #include "cmdmain.h" -#include "mifare.h" +#include "../include/mifare.h" static int CmdHelp(const char *Cmd); static void waitCmd(uint8_t iLen); @@ -183,27 +183,24 @@ void iso14a_set_timeout(uint32_t timeout) { int CmdHF14AReader(const char *Cmd) { - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; SendCommand(&c); UsbCommand resp; WaitForResponse(CMD_ACK,&resp); - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes; - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS - - if(select_status == 0) { + if(resp.arg[0] == 0) { PrintAndLog("iso14443a card select failed"); return 0; } - PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]); + PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]); + PrintAndLog(" UID : %s", sprint_hex(card->uid, card->uidlen)); + PrintAndLog(" SAK : %02x [%d]", card->sak, resp.arg[0]); - switch (card.sak) { + switch (card->sak) { case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break; case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break; case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break; @@ -219,107 +216,67 @@ int CmdHF14AReader(const char *Cmd) case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break; default: ; } - - - // try to request ATS even if tag claims not to support it - if (select_status == 2) { - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; - c.arg[1] = 2; - c.arg[2] = 0; - memcpy(c.d.asBytes, rats, 2); - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); - - memcpy(&card.ats, resp.d.asBytes, resp.arg[0]); - card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes - } - - // disconnect - c.arg[0] = 0; - c.arg[1] = 0; - c.arg[2] = 0; - SendCommand(&c); - - - if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + if(resp.arg[0] == 1) { bool ta1 = 0, tb1 = 0, tc1 = 0; int pos; - if (select_status == 2) { - PrintAndLog("SAK incorrectly claims that card doesn't support RATS"); + PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len)); + if (card->ats_len > 0) { + PrintAndLog(" - TL : length is %d bytes", card->ats[0]); } - PrintAndLog(" ATS : %s", sprint_hex(card.ats, card.ats_len)); - PrintAndLog(" - TL : length is %d bytes", card.ats[0]); - if (card.ats[0] != card.ats_len - 2) { - PrintAndLog("ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); - } - - if (card.ats[0] > 1) { // there is a format byte (T0) - ta1 = (card.ats[1] & 0x10) == 0x10; - tb1 = (card.ats[1] & 0x20) == 0x20; - tc1 = (card.ats[1] & 0x40) == 0x40; - int16_t fsci = card.ats[1] & 0x0f; + if (card->ats_len > 1) { + ta1 = (card->ats[1] & 0x10) == 0x10; + tb1 = (card->ats[1] & 0x20) == 0x20; + tc1 = (card->ats[1] & 0x40) == 0x40; PrintAndLog(" - T0 : TA1 is%s present, TB1 is%s present, " - "TC1 is%s present, FSCI is %d (FSC = %ld)", + "TC1 is%s present, FSCI is %d", (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"), - fsci, - fsci < 5 ? (fsci - 2) * 8 : - fsci < 8 ? (fsci - 3) * 32 : - fsci == 8 ? 256 : - -1 - ); + (card->ats[1] & 0x0f)); } pos = 2; - if (ta1) { + if (ta1 && card->ats_len > pos) { char dr[16], ds[16]; dr[0] = ds[0] = '\0'; - if (card.ats[pos] & 0x10) strcat(ds, "2, "); - if (card.ats[pos] & 0x20) strcat(ds, "4, "); - if (card.ats[pos] & 0x40) strcat(ds, "8, "); - if (card.ats[pos] & 0x01) strcat(dr, "2, "); - if (card.ats[pos] & 0x02) strcat(dr, "4, "); - if (card.ats[pos] & 0x04) strcat(dr, "8, "); + if (card->ats[pos] & 0x10) strcat(ds, "2, "); + if (card->ats[pos] & 0x20) strcat(ds, "4, "); + if (card->ats[pos] & 0x40) strcat(ds, "8, "); + if (card->ats[pos] & 0x01) strcat(dr, "2, "); + if (card->ats[pos] & 0x02) strcat(dr, "4, "); + if (card->ats[pos] & 0x04) strcat(dr, "8, "); if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; PrintAndLog(" - TA1 : different divisors are%s supported, " "DR: [%s], DS: [%s]", - (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); + (card->ats[pos] & 0x80 ? " NOT" : ""), dr, ds); pos++; } - if (tb1) { - uint32_t sfgi = card.ats[pos] & 0x0F; - uint32_t fwi = card.ats[pos] >> 4; - PrintAndLog(" - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", - (sfgi), - sfgi ? "" : "(not needed) ", - sfgi ? (1 << 12) << sfgi : 0, - fwi, - (1 << 12) << fwi - ); + if (tb1 && card->ats_len > pos) { + PrintAndLog(" - TB1 : SFGI = %d, FWI = %d", + (card->ats[pos] & 0x08), + (card->ats[pos] & 0x80) >> 4); pos++; } - if (tc1) { + if (tc1 && card->ats_len > pos) { PrintAndLog(" - TC1 : NAD is%s supported, CID is%s supported", - (card.ats[pos] & 0x01) ? "" : " NOT", - (card.ats[pos] & 0x02) ? "" : " NOT"); + (card->ats[pos] & 0x01) ? "" : " NOT", + (card->ats[pos] & 0x02) ? "" : " NOT"); pos++; } - if (card.ats[0] > pos) { + if (card->ats_len > pos) { char *tip = ""; - if (card.ats[0] - pos >= 7) { - if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { + if (card->ats_len - pos > 7) { + if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { tip = "-> MIFARE Plus X 2K or 4K"; - } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { + } else if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { tip = "-> MIFARE Plus S 2K or 4K"; } } - PrintAndLog(" - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); - if (card.ats[pos] == 0xC1) { + PrintAndLog(" - HB : %s%s", sprint_hex(card->ats + pos, card->ats_len - pos - 2), tip); + if (card->ats[pos] == 0xC1) { PrintAndLog(" c1 -> Mifare or (multiple) virtual cards of various type"); PrintAndLog(" %02x -> Length is %d bytes", - card.ats[pos + 1], card.ats[pos + 1]); - switch (card.ats[pos + 2] & 0xf0) { + card->ats[pos + 1], card->ats[pos + 1]); + switch (card->ats[pos + 2] & 0xf0) { case 0x10: PrintAndLog(" 1x -> MIFARE DESFire"); break; @@ -327,7 +284,7 @@ int CmdHF14AReader(const char *Cmd) PrintAndLog(" 2x -> MIFARE Plus"); break; } - switch (card.ats[pos + 2] & 0x0f) { + switch (card->ats[pos + 2] & 0x0f) { case 0x00: PrintAndLog(" x0 -> <1 kByte"); break; @@ -344,7 +301,7 @@ int CmdHF14AReader(const char *Cmd) PrintAndLog(" x0 -> 8 kByte"); break; } - switch (card.ats[pos + 3] & 0xf0) { + switch (card->ats[pos + 3] & 0xf0) { case 0x00: PrintAndLog(" 0x -> Engineering sample"); break; @@ -352,7 +309,7 @@ int CmdHF14AReader(const char *Cmd) PrintAndLog(" 2x -> Released"); break; } - switch (card.ats[pos + 3] & 0x0f) { + switch (card->ats[pos + 3] & 0x0f) { case 0x00: PrintAndLog(" x0 -> Generation 1"); break; @@ -363,7 +320,7 @@ int CmdHF14AReader(const char *Cmd) PrintAndLog(" x2 -> Generation 3"); break; } - switch (card.ats[pos + 4] & 0x0f) { + switch (card->ats[pos + 4] & 0x0f) { case 0x00: PrintAndLog(" x0 -> Only VCSL supported"); break; @@ -377,10 +334,10 @@ int CmdHF14AReader(const char *Cmd) } } } else { - PrintAndLog("proprietary non iso14443-4 card found, RATS not supported"); + PrintAndLog("proprietary non iso14443a-4 card found, RATS not supported"); } - return select_status; + return resp.arg[0]; } // Collect ISO14443 Type A UIDs @@ -402,17 +359,20 @@ int CmdHF14ACUIDs(const char *Cmd) UsbCommand resp; WaitForResponse(CMD_ACK,&resp); - iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes; + uint8_t *uid = resp.d.asBytes; + iso14a_card_select_t *card = (iso14a_card_select_t *)(uid + 12); // check if command failed if (resp.arg[0] == 0) { PrintAndLog("Card select failed."); } else { - char uid_string[20]; - for (uint16_t i = 0; i < card->uidlen; i++) { - sprintf(&uid_string[2*i], "%02X", card->uid[i]); + // check if UID is 4 bytes + if ((card->atqa[1] & 0xC0) == 0) { + PrintAndLog("%02X%02X%02X%02X", + *uid, *(uid + 1), *(uid + 2), *(uid + 3)); + } else { + PrintAndLog("UID longer than 4 bytes"); } - PrintAndLog("%s", uid_string); } } PrintAndLog("End: %u", time(NULL)); @@ -466,10 +426,6 @@ int CmdHF14ASim(const char *Cmd) // At lease save the mandatory first part of the UID c.arg[0] = long_uid & 0xffffffff; - - // At lease save the mandatory first part of the UID - c.arg[0] = long_uid & 0xffffffff; - if (c.arg[1] == 0) { PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]); } @@ -537,19 +493,22 @@ int CmdHF14ACmdRaw(const char *cmd) { uint8_t active=0; uint8_t active_select=0; uint16_t numbits=0; + uint16_t timeout=0; + uint8_t bTimeout=0; char buf[5]=""; int i=0; - uint8_t data[100]; + uint8_t data[USB_CMD_DATA_SIZE]; unsigned int datalen=0, temp; if (strlen(cmd)<2) { - PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] <0A 0B 0C ... hex>"); + PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] [-t] <0A 0B 0C ... hex>"); PrintAndLog(" -r do not read response"); PrintAndLog(" -c calculate and append CRC"); PrintAndLog(" -p leave the signal field ON after receive"); PrintAndLog(" -a active signal field ON without select"); PrintAndLog(" -s active signal field ON with select"); PrintAndLog(" -b number of bits to send. Useful for send partial byte"); + PrintAndLog(" -t timeout"); return 0; } @@ -582,6 +541,14 @@ int CmdHF14ACmdRaw(const char *cmd) { while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } i-=2; break; + case 't': + bTimeout=1; + sscanf(cmd+i+2,"%d",&temp); + timeout = temp & 0xFFFF; + i+=3; + while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } + i+=2; + break; default: PrintAndLog("Invalid option"); return 0; @@ -599,15 +566,19 @@ int CmdHF14ACmdRaw(const char *cmd) { if (strlen(buf)>=2) { sscanf(buf,"%x",&temp); data[datalen]=(uint8_t)(temp & 0xff); - datalen++; *buf=0; + if (++datalen>sizeof(data)){ + if (crc) + PrintAndLog("Buffer is full, we can't add CRC to your data"); + break; + } } continue; } PrintAndLog("Invalid char on input"); return 0; } - if(crc && datalen>0) + if(crc && datalen>0 && datalenMAX_TIMEOUT) { + c.arg[2] = MAX_TIMEOUT; + PrintAndLog("Set timeout to 624 ms. The max we can wait for response"); + } + } if(power) c.arg[0] |= ISO14A_NO_DISCONNECT; if(datalen>0) c.arg[0] |= ISO14A_RAW; - c.arg[1] = datalen; - c.arg[2] = numbits; + // Max buffer is USB_CMD_DATA_SIZE + c.arg[1] = (datalen & 0xFFFF) | (numbits << 16); memcpy(c.d.asBytes,data,datalen); SendCommand(&c); diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index c42d54c5..25a452e6 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -13,8 +13,7 @@ #include #include #include -#include "iso14443crc.h" -//#include "proxusb.h" +#include "../common/iso14443crc.h" #include "proxmark3.h" #include "data.h" #include "graph.h" diff --git a/client/cmdhf15.c b/client/cmdhf15.c index cc61d289..195560ed 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -33,7 +33,7 @@ #include "ui.h" #include "cmdparser.h" #include "cmdhf15.h" -#include "iso15693tools.h" +#include "../common/iso15693tools.h" #include "cmdmain.h" #define FrameSOF Iso15693FrameSOF diff --git a/client/cmdhfdes.c b/client/cmdhfdes.c new file mode 100644 index 00000000..1876e5c1 --- /dev/null +++ b/client/cmdhfdes.c @@ -0,0 +1,69 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2012 nuit +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE DESfire commands +//----------------------------------------------------------------------------- + +#include "cmdhfdes.h" +#include "proxmark3.h" +#include "cmdmain.h" + +static int CmdHelp(const char *Cmd); + +int CmdHFDESReader(const char *Cmd) +{ + UsbCommand c ={CMD_MIFARE_DES_READER, {3, 0x60, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponseTimeout(CMD_ACK,&resp,2000); + return 0; +} + +int CmdHFDESDbg(const char *Cmd) +{ + int dbgMode = param_get32ex(Cmd, 0, 0, 10); + if (dbgMode > 4) { + PrintAndLog("Max debud mode parameter is 4 \n"); + } + + if (strlen(Cmd) < 1 || !param_getchar(Cmd, 0) || dbgMode > 4) { + PrintAndLog("Usage: hf des dbg "); + PrintAndLog(" 0 - no debug messages"); + PrintAndLog(" 1 - error messages"); + PrintAndLog(" 2 - all messages"); + PrintAndLog(" 4 - extended debug mode"); + return 0; + } + + UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; + SendCommand(&c); + + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"dbg", CmdHFDESDbg, 0, "Set default debug mode"}, + {"reader", CmdHFDESReader, 0, "Reader"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFDES(const char *Cmd) +{ + //flush + WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhfdes.h b/client/cmdhfdes.h new file mode 100644 index 00000000..e51797cb --- /dev/null +++ b/client/cmdhfdes.h @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2012 nuit +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE DESfire commands +//----------------------------------------------------------------------------- + +#ifndef CMDHFDES_H__ +#define CMDHFDES_H__ + +#include +#include +#include +#include +#include "proxmark3.h" +#include "data.h" +#include "ui.h" +#include "cmdparser.h" +#include "common.h" +#include "util.h" +int CmdHFDES(const char *Cmd); +int CmdHFDESReader(const char *Cmd); +int CmdHFDESDbg(const char *Cmd); +#endif diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 8a36d6ae..92e61c68 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -13,7 +13,7 @@ #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" -#include "common.h" +#include "../include/common.h" #include "cmdmain.h" #include "sleep.h" #include "cmdhfepa.h" diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 7156b118..bd215a61 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -16,12 +16,11 @@ #include #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type #include "data.h" -//#include "proxusb.h" #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" #include "cmdhficlass.h" -#include "common.h" +#include "../include/common.h" #include "util.h" #include "cmdmain.h" #include "loclass/des.h" @@ -35,11 +34,11 @@ static int CmdHelp(const char *Cmd); int xorbits_8(uint8_t val) { - uint8_t res = val ^ (val >> 1); //1st pass - res = res ^ (res >> 1); // 2nd pass - res = res ^ (res >> 2); // 3rd pass - res = res ^ (res >> 4); // 4th pass - return res & 1; + uint8_t res = val ^ (val >> 1); //1st pass + res = res ^ (res >> 1); // 2nd pass + res = res ^ (res >> 2); // 3rd pass + res = res ^ (res >> 4); // 4th pass + return res & 1; } int CmdHFiClassList(const char *Cmd) @@ -88,7 +87,7 @@ int CmdHFiClassList(const char *Cmd) timestamp = *((uint32_t *)(got+i)); parityBits = *((uint32_t *)(got+i+4)); len = got[i+8]; - frame = (got+i+9); + frame = (got+i+9); uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff; tagToReader = timestamp & 0x80000000; @@ -437,7 +436,7 @@ int CmdHFiClassReader_Replay(const char *Cmd) if (strlen(Cmd)<1) { PrintAndLog("Usage: hf iclass replay "); PrintAndLog(" sample: hf iclass replay 00112233"); - return 0; + return 0; } if (param_gethex(Cmd, 0, MAC, 8)) { @@ -647,14 +646,17 @@ int CmdHFiClass_iso14443A_write(const char *Cmd) static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHFiClassList, 0, "List iClass history"}, - {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, - {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHFiClassList, 0, "List iClass history"}, + {"snoop", CmdHFiClassSnoop, 0, "Eavesdrop iClass communication"}, + {"sim", CmdHFiClassSim, 0, "Simulate iClass tag"}, {"reader",CmdHFiClassReader, 0, "Read an iClass tag"}, {"replay",CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"}, {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, + {"replay", CmdHFiClassReader_Replay, 0, "Read an iClass tag via Reply Attack"}, + {"dump", CmdHFiClassReader_Dump, 0, "Authenticate and Dump iClass tag"}, + {"write", CmdHFiClass_iso14443A_write, 0, "Authenticate and Write iClass block"}, {NULL, NULL, 0, NULL} }; @@ -667,5 +669,5 @@ int CmdHFiClass(const char *Cmd) int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); - return 0; + return 0; } diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 8366b09b..340fd2b0 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -10,7 +10,6 @@ #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "data.h" #include "ui.h" diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index b66aa3a6..8448731e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -7,7 +7,7 @@ //----------------------------------------------------------------------------- // High frequency MIFARE commands //----------------------------------------------------------------------------- - +#include "../include/mifare.h" #include "cmdhfmf.h" static int CmdHelp(const char *Cmd); @@ -140,6 +140,7 @@ int CmdHF14AMfWrBl(const char *Cmd) return 0; } +/* dublett finns i CMDHFMFU.C int CmdHF14AMfUWrBl(const char *Cmd) { uint8_t blockNo = 0; @@ -249,8 +250,7 @@ int CmdHF14AMfUWrBl(const char *Cmd) } return 0; } - - +*/ int CmdHF14AMfRdBl(const char *Cmd) { uint8_t blockNo = 0; @@ -299,6 +299,7 @@ int CmdHF14AMfRdBl(const char *Cmd) return 0; } +/* dublett finns i CMDHFMFU.C int CmdHF14AMfURdBl(const char *Cmd) { uint8_t blockNo = 0; @@ -330,8 +331,9 @@ int CmdHF14AMfURdBl(const char *Cmd) return 0; } +*/ - +/* dublett finns i CMDHFMFU.C int CmdHF14AMfURdCard(const char *Cmd) { int i; @@ -422,7 +424,7 @@ int CmdHF14AMfURdCard(const char *Cmd) } return 0; } - +*/ int CmdHF14AMfRdSc(const char *Cmd) { @@ -517,7 +519,16 @@ int CmdHF14AMfDump(const char *Cmd) UsbCommand resp; + int size = GetCardSize(); char cmdp = param_getchar(Cmd, 0); + + PrintAndLog("Got %d",size); + + return 0; + + if ( size > -1) + cmdp = (char)48+size; + switch (cmdp) { case '0' : numSectors = 5; break; case '1' : @@ -541,8 +552,7 @@ int CmdHF14AMfDump(const char *Cmd) return 1; } - // Read key file - + // Read keys A from file for (sectorNo=0; sectorNo|<*card memory> [t|d] [] []"); + PrintAndLog(" * - all sectors"); + PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLog("d - write keys to binary file\n"); + PrintAndLog("t - write keys to emulator memory"); + PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); + PrintAndLog(" hf mf chk *1 ? t"); + PrintAndLog(" hf mf chk *1 ? d"); + return 0; + } + FILE * f; char filename[256]={0}; char buf[13]; @@ -1047,16 +1082,6 @@ int CmdHF14AMfChk(const char *Cmd) num_to_bytes(defaultKeys[defaultKeyCounter], 6, (uint8_t*)(keyBlock + defaultKeyCounter * 6)); } - if (strlen(Cmd)<3) { - PrintAndLog("Usage: hf mf chk |<*card memory> [t] [] []"); - PrintAndLog(" * - all sectors"); - PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLog("d - write keys to binary file\n"); - PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic"); - PrintAndLog(" hf mf chk *1 ? t"); - return 0; - } - if (param_getchar(Cmd, 0)=='*') { blockNo = 3; switch(param_getchar(Cmd+1, 0)) { @@ -1157,8 +1182,8 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("No key specified, trying default keys"); for (;keycnt < defaultKeysSize; keycnt++) PrintAndLog("chk default key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], - (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); + (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); } // initialize storage for found keys @@ -1203,13 +1228,13 @@ int CmdHF14AMfChk(const char *Cmd) for (uint16_t t = 0; t < 2; t++) { if (validKey[t][sectorNo]) { memcpy(block + t*10, foundKey[t][sectorNo], 6); - } - } + } + } mfEmlSetMem(block, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); } } PrintAndLog("Found keys have been transferred to the emulator memory"); - } + } if (createDumpFile) { FILE *fkeys = fopen("dumpkeys.bin","wb"); @@ -1217,7 +1242,7 @@ int CmdHF14AMfChk(const char *Cmd) PrintAndLog("Could not create file dumpkeys.bin"); free(keyBlock); return 1; - } + } for (uint16_t t = 0; t < 2; t++) { fwrite(foundKey[t], 1, 6*SectorsCnt, fkeys); } @@ -1227,7 +1252,7 @@ int CmdHF14AMfChk(const char *Cmd) free(keyBlock); - return 0; + return 0; } @@ -1321,7 +1346,6 @@ int CmdHF14AMfDbg(const char *Cmd) return 0; } - int CmdHF14AMfEGet(const char *Cmd) { uint8_t blockNo = 0; @@ -1618,7 +1642,6 @@ int CmdHF14AMfCSetUID(const char *Cmd) return 0; } - int CmdHF14AMfCSetBlk(const char *Cmd) { uint8_t uid[8]; @@ -1744,7 +1767,7 @@ int CmdHF14AMfCLoad(const char *Cmd) } fclose(f); - if (blockNum != 16 * 4){ + if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){ PrintAndLog("File content error. There must be 64 blocks"); return 4; } @@ -1753,7 +1776,6 @@ int CmdHF14AMfCLoad(const char *Cmd) } } - int CmdHF14AMfCGetBlk(const char *Cmd) { uint8_t memBlock[16]; uint8_t blockNo = 0; @@ -2015,30 +2037,128 @@ int CmdHF14AMfSniff(const char *Cmd){ FillFileNameByUID(logHexFileName, uid + (7 - uid_len), ".log", uid_len); AddLogCurrentDT(logHexFileName); } - if (wantDecrypt) mfTraceInit(uid, atqa, sak, wantSaveToEmlFile); + if (wantDecrypt) + mfTraceInit(uid, atqa, sak, wantSaveToEmlFile); } else { PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len)); - if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len); - if (wantDecrypt) mfTraceDecode(bufPtr, len, parity, wantSaveToEmlFile); + if (wantLogToFile) + AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len); + if (wantDecrypt) + mfTraceDecode(bufPtr, len, parity, wantSaveToEmlFile); } bufPtr += len; num++; } } - } // resp not NILL + } // resp not NULL } // while (true) return 0; } +// Tries to identify cardsize. +// Returns where num is: +// -1 unidentified +// 0 - MINI (320bytes) +// 1 - 1K +// 2 - 2K +// 4 - 4K +int GetCardSize() +{ + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + if(resp.arg[0] == 0) { + PrintAndLog("iso14443a card select failed"); + return -1; + } + + iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes; + + PrintAndLog("Trying to detect card size."); + + uint16_t atqa = 0; + uint8_t sak = 0; + atqa = (card->atqa[1] & 0xff) << 8; + atqa += card->atqa[0] & 0xff; + sak = card->sak; + + // https://code.google.com/p/libnfc/source/browse/libnfc/target-subr.c + + PrintAndLog("found ATAQ: %04X SAK: %02X", atqa, sak); + + + // NXP MIFARE Mini 0.3k + if ( ( (atqa & 0xff0f) == 0x0004) && (sak == 0x09) ) return 0; + + // MIFARE Classic 1K + if ( ((atqa & 0xff0f) == 0x0004) && (sak == 0x08) ) return 1; + + // MIFARE Classik 4K + if ( ((atqa & 0xff0f) == 0x0002) && (sak == 0x18) ) return 4; + + // SmartMX with MIFARE 1K emulation + if ( ((atqa & 0xf0ff) == 0x0004) ) return 1; + + // SmartMX with MIFARE 4K emulation + if ( ((atqa & 0xf0ff) == 0x0002) ) return 4; + + // Infineon MIFARE CLASSIC 1K + if ( ((atqa & 0xffff) == 0x0004) && (sak == 0x88) ) return 1; + + // MFC 4K emulated by Nokia 6212 Classic + if ( ((atqa & 0xffff) == 0x0002) && (sak == 0x38) ) return 4; + + // MFC 4K emulated by Nokia 6131 NFC + if ( ((atqa & 0xffff) == 0x0008) && (sak == 0x38) ) return 4; + + + PrintAndLog("BEFOOO 1K %02X", (atqa & 0xff0f)); + + // MIFARE Plus (4 Byte UID or 4 Byte RID) + // MIFARE Plus (7 Byte UID) + if ( + ((atqa & 0xffff) == 0x0002) | + ((atqa & 0xffff) == 0x0004) | + ((atqa & 0xffff) == 0x0042) | + ((atqa & 0xffff) == 0x0044) + ) + { + switch(sak){ + case 0x08: + case 0x10: { + //case 0x20: + PrintAndLog("2"); + return 2; + break; + } + case 0x11: + case 0x18:{ + //case 0x20: + PrintAndLog("4"); + return 4; + break; + } + } + } + + return -1; +} + + + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, - {"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"}, - {"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"}, - {"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"}, + //{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"}, + //{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"}, + //{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"}, {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index 62e856ad..45ba7cb1 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -16,12 +16,11 @@ #include #include #include "proxmark3.h" -#include "iso14443crc.h" +#include "../common/iso14443crc.h" #include "data.h" -//#include "proxusb.h" #include "ui.h" #include "cmdparser.h" -#include "common.h" +#include "../include/common.h" #include "util.h" #include "mifarehost.h" @@ -54,5 +53,5 @@ int CmdHF14AMfCGetBlk(const char* cmd); int CmdHF14AMfCGetSc(const char* cmd); int CmdHF14AMfCLoad(const char* cmd); int CmdHF14AMfCSave(const char* cmd); - +int GetCardSize(); #endif diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c new file mode 100644 index 00000000..f3217df2 --- /dev/null +++ b/client/cmdhfmfdes.c @@ -0,0 +1,538 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2014 Iceman +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE Desfire commands +//----------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include "cmdmain.h" +#include "proxmark3.h" +#include "../include/common.h" +#include "../include/mifare.h" +#include "../common/iso14443crc.h" +#include "data.h" +#include "ui.h" +#include "cmdparser.h" +#include "util.h" +#include "cmdhfmfdes.h" + + +uint8_t key_zero_data[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; +uint8_t key_ones_data[16] = { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }; + + +static int CmdHelp(const char *Cmd); +static void xor(unsigned char * dst, unsigned char * src, size_t len); +static int32_t le24toh (uint8_t data[3]); + + +int CmdHF14ADesWb(const char *Cmd) +{ +/* uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + char cmdp = 0x00; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mf wrbl "); + PrintAndLog(" sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); + return 0; + } + + blockNo = param_get8(Cmd, 0); + cmdp = param_getchar(Cmd, 1); + if (cmdp == 0x00) { + PrintAndLog("Key type must be A or B"); + return 1; + } + if (cmdp != 'A' && cmdp != 'a') keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLog("Key must include 12 HEX symbols"); + return 1; + } + if (param_gethex(Cmd, 3, bldata, 32)) { + PrintAndLog("Block data must include 32 HEX symbols"); + return 1; + } + PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6)); + PrintAndLog("--data: %s", sprint_hex(bldata, 16)); + + UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + memcpy(c.d.asBytes + 10, bldata, 16); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + */ + return 0; +} + +int CmdHF14ADesRb(const char *Cmd) +{ + // uint8_t blockNo = 0; + // uint8_t keyType = 0; + // uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + + // char cmdp = 0x00; + + + // if (strlen(Cmd)<3) { + // PrintAndLog("Usage: hf mf rdbl "); + // PrintAndLog(" sample: hf mf rdbl 0 A FFFFFFFFFFFF "); + // return 0; + // } + + // blockNo = param_get8(Cmd, 0); + // cmdp = param_getchar(Cmd, 1); + // if (cmdp == 0x00) { + // PrintAndLog("Key type must be A or B"); + // return 1; + // } + // if (cmdp != 'A' && cmdp != 'a') keyType = 1; + // if (param_gethex(Cmd, 2, key, 12)) { + // PrintAndLog("Key must include 12 HEX symbols"); + // return 1; + // } + // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); + + // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; + // memcpy(c.d.asBytes, key, 6); + // SendCommand(&c); + + // UsbCommand resp; + // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + // uint8_t isOK = resp.arg[0] & 0xff; + // uint8_t * data = resp.d.asBytes; + + // if (isOK) + // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16)); + // else + // PrintAndLog("isOk:%02x", isOK); + // } else { + // PrintAndLog("Command execute timeout"); + // } + + return 0; +} + +int CmdHF14ADesInfo(const char *Cmd){ + + UsbCommand c = {CMD_MIFARE_DESFIRE_INFO}; + SendCommand(&c); + UsbCommand resp; + + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + PrintAndLog("Command execute timeout"); + return 0; + } + uint8_t isOK = resp.arg[0] & 0xff; + if ( !isOK ){ + PrintAndLog("Command unsuccessful"); + return 0; + } + + PrintAndLog("---Desfire Information---------------------------------------"); + PrintAndLog("-------------------------------------------------------------"); + PrintAndLog(" UID : %s",sprint_hex(resp.d.asBytes, 7)); + PrintAndLog(" Batch number : %s",sprint_hex(resp.d.asBytes+28,5)); + PrintAndLog(" Production date : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]); + PrintAndLog("-------------------------------------------------------------"); + PrintAndLog(" Hardware Information"); + PrintAndLog(" Vendor Id : %s", GetVendorStr(resp.d.asBytes[7])); + PrintAndLog(" Type : 0x%02X",resp.d.asBytes[8]); + PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[9]); + PrintAndLog(" Version : %d.%d",resp.d.asBytes[10], resp.d.asBytes[11]); + PrintAndLog(" Storage size : %s",GetCardSizeStr(resp.d.asBytes[12])); + PrintAndLog(" Protocol : %s",GetProtocolStr(resp.d.asBytes[13])); + PrintAndLog("-------------------------------------------------------------"); + PrintAndLog(" Software Information"); + PrintAndLog(" Vendor Id : %s",GetVendorStr(resp.d.asBytes[14])); + PrintAndLog(" Type : 0x%02X",resp.d.asBytes[15]); + PrintAndLog(" Subtype : 0x%02X",resp.d.asBytes[16]); + PrintAndLog(" Version : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]); + PrintAndLog(" storage size : %s", GetCardSizeStr(resp.d.asBytes[19])); + PrintAndLog(" Protocol : %s", GetProtocolStr(resp.d.asBytes[20])); + PrintAndLog("-------------------------------------------------------------"); + + + UsbCommand c1 = {CMD_MIFARE_DESFIRE, { 0x03, 0x01 }}; + c1.d.asBytes[0] = GET_KEY_SETTINGS; + SendCommand(&c1); + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + return 0; + } + + PrintAndLog(" Master Key settings"); + if ( resp.d.asBytes[3] & (1 << 3 ) ) + PrintAndLog(" 0x08 Configuration changeable"); + else + PrintAndLog(" 0x08 Configuration NOT changeable"); + + if ( resp.d.asBytes[3] & (1 << 2 ) ) + PrintAndLog(" 0x04 PICC Master Key not required for create / delete"); + else + PrintAndLog(" 0x04 PICC Master Key required for create / delete"); + + if ( resp.d.asBytes[3] & (1 << 1 ) ) + PrintAndLog(" 0x02 Free directory list access without PICC Master Key"); + else + PrintAndLog(" 0x02 Directory list access with PICC Master Key"); + + if ( resp.d.asBytes[3] & (1 << 0 ) ) + PrintAndLog(" 0x01 Allow changing the Master Key"); + else + PrintAndLog(" 0x01 Master Key is not changeable anymore"); + + // init len + UsbCommand c2 = {CMD_MIFARE_DESFIRE, { 0x03, 0x02 }}; + c2.d.asBytes[0] = GET_KEY_VERSION; + c2.d.asBytes[1] = 0x00; + SendCommand(&c2); + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + return 0; + } + + PrintAndLog(""); + PrintAndLog(" Max number of keys : %d", resp.d.asBytes[4]); + PrintAndLog(" Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]); + PrintAndLog("-------------------------------------------------------------"); + + + UsbCommand c3 = {CMD_MIFARE_DESFIRE, { 0x03, 0x01 }}; + c3.d.asBytes[0] = GET_FREE_MEMORY; + SendCommand(&c3); + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + return 0; + } + + uint8_t tmp[3]; + memcpy(tmp, resp.d.asBytes+3,3); + + PrintAndLog(" Free memory on card : %d bytes", le24toh( tmp )); + PrintAndLog("-------------------------------------------------------------"); + + /* + Card Master key (CMK) 0x00 AID = 00 00 00 (card level) + Application Master Key (AMK) 0x00 AID != 00 00 00 + Application keys (APK) 0x01-0x0D + Application free 0x0E + Application never 0x0F + + ACCESS RIGHTS: + keys 0,1,2,3 C + keys 4,5,6,7 RW + keys 8,9,10,11 W + keys 12,13,14,15 R + + Session key: + 16 : RndA(byte0-byte3) + RndB(byte0-byte3) + RndA(byte4-byte7) + RndB(byte4-byte7) + 8 : RndA(byte0-byte3) + RndB(byte0-byte3) + + AES 16 : RndA(byte0-byte3) + RndB(byte0-byte3) + RndA(byte12-byte15) + RndB(byte12-byte15) + */ + + return 1; +} + +char * GetVendorStr( uint8_t id){ + static char buf[30]; + char *retStr = buf; + + if ( id == 0x04 ) + sprintf(retStr, "0x%02X (NXP)",id); + else + sprintf(retStr,"0x%02X (Unknown)",id); + return buf; +} + +/* + The 7 MSBits (= n) code the storage size itself based on 2^n, + the LSBit is set to '0' if the size is exactly 2^n + and set to '1' if the storage size is between 2^n and 2^(n+1). + For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'. +*/ +char * GetCardSizeStr( uint8_t fsize ){ + + static char buf[30]; + char *retStr = buf; + + uint16_t usize = 1 << ((fsize >>1) + 1); + uint16_t lsize = 1 << (fsize >>1); + + // is LSB set? + if ( fsize & (1 << 0 ) ) + sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize); + else + sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize); + return buf; +} + +char * GetProtocolStr(uint8_t id){ + + static char buf[30]; + char *retStr = buf; + + if ( id == 0x05) + sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id); + else + sprintf(retStr,"0x%02X", id); + return buf; +} + +int CmdHF14ADesEnumApplications(const char *Cmd){ + + uint32_t options = 0x00; + + options |= INIT; + options |= DISCONNECT; + + UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }}; + c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a + SendCommand(&c); + UsbCommand resp; + + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { + return 0; + } + + uint8_t isOK = resp.arg[0] & 0xff; + if ( !isOK ){ + PrintAndLog("Command unsuccessful"); + return 0; + } + + PrintAndLog("---Desfire Enum Applications --------------------------------"); + PrintAndLog("-------------------------------------------------------------"); + + UsbCommand respAid; + UsbCommand respFiles; + + uint8_t num = 0; + int max = resp.arg[1] -3 -2; + + for(int i=3; i<=max; i+=3){ + PrintAndLog(" Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]); + num++; + + options = INIT; + + UsbCommand cAid = {CMD_MIFARE_DESFIRE, { options, 0x04 }}; + cAid.d.asBytes[0] = SELECT_APPLICATION; // 0x5a + cAid.d.asBytes[1] = resp.d.asBytes[i]; + cAid.d.asBytes[2] = resp.d.asBytes[i+1]; + cAid.d.asBytes[3] = resp.d.asBytes[i+2]; + SendCommand(&cAid); + + if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) { + PrintAndLog(" Timed-out"); + continue; + } + uint8_t isOK = respAid.arg[0] & 0xff; + if ( !isOK ){ + PrintAndLog(" Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3)); + continue; + } + + options = DISCONNECT; + UsbCommand cFiles = {CMD_MIFARE_DESFIRE, { options, 0x01 }}; + cFiles.d.asBytes[0] = GET_FILE_IDS; // 0x6f + SendCommand(&cFiles); + + if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) { + PrintAndLog(" Timed-out"); + continue; + } else { + + uint8_t isOK = respFiles.arg[0] & 0xff; + if ( !isOK ){ + PrintAndLog(" No files found"); + continue; + } + + int respfileLen = resp.arg[1]-3-2; + for (int j=0; j< respfileLen; ++j){ + PrintAndLog(" Fileid %d :", resp.d.asBytes[j+3]); + } + } + + } + PrintAndLog("-------------------------------------------------------------"); + + + return 1; +} + +int CmdHF14ADesNonces(const char *Cmd){ + return 1; +} + +// +// MIAFRE DesFire Authentication +// +#define BUFSIZE 64 +int CmdHF14ADesAuth(const char *Cmd){ + + // NR DESC KEYLENGHT + // ------------------------ + // 1 = DES 8 + // 2 = 3DES 16 + // 3 = 3K 3DES 24 + // 4 = AES 16 + + // AUTHENTICTION MODES: + // 1 Normal + // 2 ISO + // 3 AES + + uint8_t keylength = 8; + //unsigned char testinput[] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00}; + unsigned char key[24]; // = { 0x75,0x28,0x78,0x39,0x74,0x93,0xCB,0x70}; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mfdes auth <1|2|3> <1|2|3|4> "); + PrintAndLog(" AUTH modes 1 = normal, 2 = iso, 3 = aes"); + PrintAndLog(" Crypto: 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES"); + PrintAndLog(" keynumber"); + PrintAndLog(" sample: hf mfdes auth 1 1 0 11223344"); + return 0; + } + uint8_t cmdAuthMode = param_get8(Cmd,0); + uint8_t cmdAuthAlgo = param_get8(Cmd,1); + uint8_t cmdKeyNo = param_get8(Cmd,2); + + switch (cmdAuthMode) + { + case 1: + if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { + PrintAndLog("Crypto algo not valid for the auth mode"); + return 1; + } + break; + case 2: + if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) { + PrintAndLog("Crypto algo not valid for the auth mode"); + return 1; + } + break; + case 3: + if ( cmdAuthAlgo != 4) { + PrintAndLog("Crypto algo not valid for the auth mode"); + return 1; + } + break; + default: + PrintAndLog("Wrong Auth mode"); + return 1; + break; + } + + switch (cmdAuthAlgo){ + case 2: + keylength = 16; + PrintAndLog("3DES selected"); + break; + case 3: + keylength = 24; + PrintAndLog("3 key 3DES selected"); + break; + case 4: + keylength = 16; + PrintAndLog("AES selected"); + break; + default: + cmdAuthAlgo = 1; + keylength = 8; + PrintAndLog("DES selected"); + break; + } + + // key + if (param_gethex(Cmd, 3, key, keylength*2)) { + PrintAndLog("Key must include %d HEX symbols", keylength); + return 1; + } + // algo, nyckellängd, + UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }}; + + c.d.asBytes[0] = keylength; + memcpy(c.d.asBytes+1, key, keylength); + //memcpy(c.d.asBytes + 30, testinput, keylength); + + SendCommand(&c); + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK,&resp,3000)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + + } else { + PrintAndLog("Command execute timeout"); + return 0; + } + + uint8_t * data= resp.d.asBytes; + + // PrintAndLog("-------------------------------------------------------------"); + PrintAndLog(" Key :%s",sprint_hex(key, keylength)); + // PrintAndLog(" Plain :%s",sprint_hex(testinput, keylength)); + PrintAndLog(" Encoded :%s",sprint_hex(data, keylength)); + PrintAndLog("-------------------------------------------------------------"); + //PrintAndLog(" Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); + + return 1; +} + + +static void xor(unsigned char * dst, unsigned char * src, size_t len) { + for( ; len > 0; len--,dst++,src++) + *dst ^= *src; +} + +static int32_t le24toh (uint8_t data[3]) { + return (data[2] << 16) | (data[1] << 8) | data[0]; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"auth", CmdHF14ADesAuth, 0, "Tries a MIFARE DesFire Authentication"}, + {"rb", CmdHF14ADesRb, 0, "Read MIFARE DesFire block"}, + {"wb", CmdHF14ADesWb, 0, "write MIFARE DesFire block"}, + {"info", CmdHF14ADesInfo, 0, "Get MIFARE DesFire information"}, + {"enum", CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"}, + {"nonce", CmdHF14ADesNonces, 0, " Collect n>0 nonces"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFMFDes(const char *Cmd) +{ + // flush + WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) +{ + CmdsHelp(CommandTable); + return 0; +} + + diff --git a/client/cmdhfmfdes.h b/client/cmdhfmfdes.h new file mode 100644 index 00000000..8ecf36d3 --- /dev/null +++ b/client/cmdhfmfdes.h @@ -0,0 +1,73 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2014 Iceman +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE Desfire commands +//----------------------------------------------------------------------------- + +int CmdHFMFDes(const char *Cmd); +int CmdHF14ADesAuth(const char* cmd); +int CmdHF14ADesRb(const char* cmd); +int CmdHF14ADesWb(const char* cmd); +int CmdHF14ADesInfo(const char *Cmd); +int CmdHF14ADesEnumApplications(const char *Cmd); +int CmdHF14ADesNonces(const char *Cmd); +char * GetCardSizeStr( uint8_t fsize ); +char * GetVendorStr( uint8_t id); +char * GetProtocolStr(uint8_t id); + +// Command options for Desfire behavior. +enum { + NONE = 0x00, + INIT = 0x01, + DISCONNECT = 0x02, + FOO = 0x04, + BAR = 0x08, +} CmdOptions ; + + +#define CREATE_APPLICATION 0xca +#define DELETE_APPLICATION 0xda +#define GET_APPLICATION_IDS 0x6a +#define SELECT_APPLICATION 0x5a +#define FORMAT_PICC 0xfc +#define GET_VERSION 0x60 +#define READ_DATA 0xbd +#define WRITE_DATA 0x3d +#define GET_VALUE 0x6c +#define CREDIT 0x0c +#define DEBIT 0xdc +#define LIMITED_CREDIT 0x1c +#define WRITE_RECORD 0x3b +#define READ_RECORDS 0xbb +#define CLEAR_RECORD_FILE 0xeb +#define COMMIT_TRANSACTION 0xc7 +#define ABORT_TRANSACTION 0xa7 +#define GET_FREE_MEMORY 0x6e +#define GET_FILE_IDS 0x6f +#define GET_FILE_SETTINGS 0xf5 +#define CHANGE_FILE_SETTINGS 0x5f +#define CREATE_STD_DATA_FILE 0xcd +#define CREATE_BACKUP_DATA_FILE 0xcb +#define CREATE_VALUE_FILE 0xcc +#define CREATE_LINEAR_RECORD_FILE 0xc1 +#define CREATE_CYCLIC_RECORD_FILE 0xc0 +#define DELETE_FILE 0xdf +#define AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE +#define AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD +#define AUTHENTICATE_AES 0xaa +#define CHANGE_KEY_SETTINGS 0x54 +#define GET_KEY_SETTINGS 0x45 +#define CHANGE_KEY 0xc4 +#define GET_KEY_VERSION 0x64 +#define AUTHENTICATION_FRAME 0xAF + + +#define MAX_APPLICATION_COUNT 28 +#define MAX_FILE_COUNT 16 +#define MAX_FRAME_SIZE 60 +#define NOT_YET_AUTHENTICATED 255 +#define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5) \ No newline at end of file diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c new file mode 100644 index 00000000..3b9f2e6d --- /dev/null +++ b/client/cmdhfmfu.c @@ -0,0 +1,1159 @@ +//----------------------------------------------------------------------------- +// Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE ULTRALIGHT (C) commands +//----------------------------------------------------------------------------- +#include +#include "cmdhfmf.h" + +uint8_t MAX_ULTRA_BLOCKS= 0x0f; +uint8_t MAX_ULTRAC_BLOCKS= 0x2c; +uint8_t key1_blnk_data[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +uint8_t key2_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; +uint8_t key3_3des_data[16] = { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 }; +uint8_t key4_nfc_data[16] = { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 }; +uint8_t key5_ones_data[16] = { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }; + +static int CmdHelp(const char *Cmd); + +// +// Mifare Ultralight Write Single Block +// +int CmdHF14AMfUWrBl(const char *Cmd){ + uint8_t blockNo = 0; + bool chinese_card=0; + uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + UsbCommand resp; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mfu uwrbl [w]"); + PrintAndLog(" sample: hf mfu uwrbl 0 01020304"); + return 0; + } + blockNo = param_get8(Cmd, 0); + if (blockNo>MAX_ULTRA_BLOCKS){ + PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); + return 1; + } + if (param_gethex(Cmd, 1, bldata, 8)) { + PrintAndLog("Block data must include 8 HEX symbols"); + return 1; + } + if (strchr(Cmd,'w') != 0) { + chinese_card=1; + } + switch(blockNo){ + case 0: + if (!chinese_card){ + PrintAndLog("Access Denied"); + }else{ + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(d.d.asBytes,bldata, 4); + SendCommand(&d); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + break; + case 1: + if (!chinese_card){ + PrintAndLog("Access Denied"); + }else{ + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(d.d.asBytes,bldata, 4); + SendCommand(&d); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + break; + case 2: + if (!chinese_card){ + PrintAndLog("Access Denied"); + }else{ + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(c.d.asBytes, bldata, 4); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + break; + case 3: + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(d.d.asBytes,bldata, 4); + SendCommand(&d); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + break; + default: + PrintAndLog("--block no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(e.d.asBytes,bldata, 4); + SendCommand(&e); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + break; + } + return 0; +} + +// +// Mifare Ultralight Read Single Block +// +int CmdHF14AMfURdBl(const char *Cmd){ + + uint8_t blockNo = 0; + + if (strlen(Cmd)<1) { + PrintAndLog("Usage: hf mfu urdbl "); + PrintAndLog(" sample: hfu mfu urdbl 0"); + return 0; + } + + blockNo = param_get8(Cmd, 0); + // if (blockNo>MAX_ULTRA_BLOCKS){ + // PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!"); + // return 1; + // } + PrintAndLog("--block no:%02x", (int)blockNo); + UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + uint8_t * data = resp.d.asBytes; + + if (isOK) + PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4)); + else + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + return 0; +} + +// +// Mifare Ultralight Read (Dump) Card Contents +// +int CmdHF14AMfURdCard(const char *Cmd){ + int i; + uint8_t BlockNo = 0; + int Pages=16; + uint8_t *lockbytes_t=NULL; + uint8_t lockbytes[2]={0,0}; + bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool dump=false; + uint8_t datatemp[5]={0,0,0,0,0}; + + uint8_t isOK = 0; + uint8_t * data = NULL; + FILE *fout = NULL; + + if (strchr(Cmd,'x') != 0){ + dump=true; + if ((fout = fopen("dump_ultralight_data.bin","wb")) == NULL) { + PrintAndLog("Could not create file name dumpdata.bin"); + return 1; + } + PrintAndLog("Dumping Ultralight Card Data..."); + } + PrintAndLog("Attempting to Read Ultralight... "); + UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo, Pages}}; + SendCommand(&c); + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + isOK = resp.arg[0] & 0xff; + data = resp.d.asBytes; + PrintAndLog("isOk:%02x", isOK); + if (isOK) { + + // UID + memcpy( datatemp, data,3); + memcpy( datatemp+3, data+4, 4); + PrintAndLog(" UID :%s ", sprint_hex(datatemp, 7)); + // BBC + // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 + int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; + if ( data[3] == crc0 ) { + PrintAndLog(" BCC0 :%02x - Ok", data[3]); + } + else{ + PrintAndLog(" BCC0 :%02x - crc should be %02x", data[3], crc0); + } + + int crc1 = data[4] ^ data[5] ^ data[6] ^data[7]; + if ( data[8] == crc1 ){ + PrintAndLog(" BCC1 :%02x - Ok", data[8]); + } + else{ + PrintAndLog(" BCC1 :%02x - crc should be %02x", data[8], crc1 ); + } + + PrintAndLog(" Internal :%s ", sprint_hex(data + 9, 1)); + + memcpy(datatemp, data+10, 2); + PrintAndLog(" Lock :%s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) ); + + PrintAndLog(" OneTimePad :%s ", sprint_hex(data + 3*4, 4)); + PrintAndLog(""); + + for (i = 0; i < Pages; i++) { + switch(i){ + case 2: + //process lock bytes + lockbytes_t=data+(i*4); + lockbytes[0]=lockbytes_t[2]; + lockbytes[1]=lockbytes_t[3]; + for(int j=0; j<16; j++){ + bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8)); + } + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 3: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 4: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 5: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 6: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 7: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 8: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 9: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 10: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 11: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 12: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 13: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 14: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 15: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + default: + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + } + } + } + } else { + PrintAndLog("Command1 execute timeout"); + } + if (dump) fclose(fout); + return 0; +} + +int CmdHF14AMfUDump(const char *Cmd){ + int i; + uint8_t BlockNo = 0; + int Pages=16; + uint8_t *lockbytes_t=NULL; + uint8_t lockbytes[2]={0,0}; + bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool dump=false; + uint8_t datatemp[5]={0,0,0,0,0}; + + uint8_t isOK = 0; + uint8_t * data = NULL; + FILE *fout; + + dump=true; + if ((fout = fopen("dump_ultralight_data.bin","wb")) == NULL) { + PrintAndLog("Could not create file name dumpdata.bin"); + return 1; + } + PrintAndLog("Dumping Ultralight Card Data..."); + + PrintAndLog("Attempting to Read Ultralight... "); + UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}}; + SendCommand(&c); + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + isOK = resp.arg[0] & 0xff; + data = resp.d.asBytes; + PrintAndLog("isOk:%02x", isOK); + if (isOK) + for (i = 0; i < Pages; i++) { + switch(i){ + case 2: + //process lock bytes + lockbytes_t=data+(i*4); + lockbytes[0]=lockbytes_t[2]; + lockbytes[1]=lockbytes_t[3]; + for(int j=0; j<16; j++){ + bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8)); + } + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 3: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 4: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 5: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 6: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 7: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 8: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 9: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 10: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 11: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 12: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 13: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 14: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 15: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + default: + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + } + } + } else { + PrintAndLog("Command1 execute timeout"); + } + if (dump) fclose(fout); + return 0; +} + +// Needed to Authenticate to Ultralight C tags +void rol (uint8_t *data, const size_t len){ + uint8_t first = data[0]; + for (size_t i = 0; i < len-1; i++) { + data[i] = data[i+1]; + } + data[len-1] = first; +} + +//------------------------------------------------------------------------------- +// Ultralight C Methods +//------------------------------------------------------------------------------- + +// +// Ultralight C Authentication Demo {currently uses hard-coded key} +// +int CmdHF14AMfucAuth(const char *Cmd){ + + uint8_t blockNo = 0, keyNo=0; + uint8_t e_RndB[8]; + uint32_t cuid=0; + unsigned char RndARndB[16]; + uint8_t key[16]; + DES_cblock RndA, RndB; + DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + DES_key_schedule ks1,ks2; + DES_cblock key1,key2; + + if (strlen(Cmd)<1) { + PrintAndLog("Usage: hf mfu auth k "); + PrintAndLog(" sample: hf mfu auth k 0"); + return 0; + } + + //Change key to user defined one + if (strchr(Cmd,'k') != 0){ + //choose a key + keyNo = param_get8(Cmd, 1); + switch(keyNo){ + case 0: + memcpy(key,key1_blnk_data,16); + break; + case 1: + memcpy(key,key2_defa_data,16); + break; + case 2: + memcpy(key,key4_nfc_data,16); + break; + case 3: + memcpy(key,key5_ones_data,16); + break; + default: + memcpy(key,key3_3des_data,16); + break; + } + }else{ + memcpy(key,key3_3des_data,16); + } + memcpy(key1,key,8); + memcpy(key2,key+8,8); + DES_set_key((DES_cblock *)key1,&ks1); + DES_set_key((DES_cblock *)key2,&ks2); + + //Auth1 + UsbCommand c = {CMD_MIFAREUC_AUTH1, {blockNo}}; + SendCommand(&c); + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + cuid = resp.arg[1]; + uint8_t * data= resp.d.asBytes; + + if (isOK){ + PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8)); + memcpy(e_RndB,data+1,8); + } + } else { + PrintAndLog("Command execute timeout"); + } + + //Do crypto magic + DES_random_key(&RndA); + DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0); + PrintAndLog(" RndB:%s",sprint_hex(RndB, 8)); + PrintAndLog(" RndA:%s",sprint_hex(RndA, 8)); + rol(RndB,8); + memcpy(RndARndB,RndA,8); + memcpy(RndARndB+8,RndB,8); + PrintAndLog(" RA+B:%s",sprint_hex(RndARndB, 16)); + DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1); + PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB, 16)); + + //Auth2 + UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}}; + memcpy(d.d.asBytes,RndARndB, 16); + SendCommand(&d); + + UsbCommand respb; + if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) { + uint8_t isOK = respb.arg[0] & 0xff; + uint8_t * data2= respb.d.asBytes; + + if (isOK){ + PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8)); + } + + } else { + PrintAndLog("Command execute timeout"); + } + return 1; +} + +// +// Ultralight C Read Single Block +// +int CmdHF14AMfUCRdBl(const char *Cmd) +{ + + uint8_t blockNo = 0; + + if (strlen(Cmd)<1) { + PrintAndLog("Usage: hf mfu ucrdbl "); + PrintAndLog(" sample: hf mfu ucrdbl 0"); + return 0; + } + + blockNo = param_get8(Cmd, 0); + if (blockNo>MAX_ULTRAC_BLOCKS){ + PrintAndLog("Error: Maximum number of readable blocks is 44 for Ultralight Cards!"); + return 1; + } + PrintAndLog("--block no:%02x", (int)blockNo); + + //Read Block + UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}}; + SendCommand(&e); + UsbCommand resp_c; + if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) { + uint8_t isOK = resp_c.arg[0] & 0xff; + uint8_t * data = resp_c.d.asBytes; + if (isOK) + PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4)); + else + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + return 0; +} + +// +// Ultralight C Read (or Dump) Card Contents +// +int CmdHF14AMfUCRdCard(const char *Cmd){ + int i; + uint8_t BlockNo = 0; + int Pages=44; + uint8_t *lockbytes_t=NULL; + uint8_t lockbytes[2]={0,0}; + uint8_t *lockbytes_t2=NULL; + uint8_t lockbytes2[2]={0,0}; + bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool bit2[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool dump=false; + uint8_t datatemp[5]={0,0,0,0,0}; + + uint8_t isOK = 0; + uint8_t * data = NULL; + FILE *fout = NULL; + + if (strchr(Cmd,'x') != 0){ + dump=true; + if ((fout = fopen("dump_ultralightc_data.bin","wb")) == NULL) { + PrintAndLog("Could not create file name dumpdata.bin"); + return 1; + } + PrintAndLog("Dumping Ultralight C Card Data..."); + } + PrintAndLog("Attempting to Read Ultralight C... "); + UsbCommand c = {CMD_MIFAREUC_READCARD, {BlockNo, Pages}}; + SendCommand(&c); + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + isOK = resp.arg[0] & 0xff; + data = resp.d.asBytes; + //Pages=sizeof(data)/sizeof(data[0]); + PrintAndLog("isOk:%02x", isOK); + if (isOK) + for (i = 0; i < Pages; i++) { + switch(i){ + case 2: + //process lock bytes + lockbytes_t=data+(i*4); + lockbytes[0]=lockbytes_t[2]; + lockbytes[1]=lockbytes_t[3]; + for(int j=0; j<16; j++){ + bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8)); + } + //might as well read bottom lockbytes too + lockbytes_t2=data+(40*4); + lockbytes2[0]=lockbytes_t2[2]; + lockbytes2[1]=lockbytes_t2[3]; + for(int j=0; j<16; j++){ + bit2[j]=lockbytes2[j/8] & ( 1 <<(7-j%8)); + } + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 3: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 4: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 5: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 6: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 7: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 8: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 9: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 10: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 11: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 12: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 13: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 14: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 15: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 16: + case 17: + case 18: + case 19: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[6]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 20: + case 21: + case 22: + case 23: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[5]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 24: + case 25: + case 26: + case 27: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[4]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 28: + case 29: + case 30: + case 31: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[2]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 32: + case 33: + case 34: + case 35: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[1]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 36: + case 37: + case 38: + case 39: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[0]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 40: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[12]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 41: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[11]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 42: + //auth0 + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[10]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 43: + //auth1 + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[9]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + default: + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + } + } + + } else { + PrintAndLog("Command1 execute timeout"); + } + if (dump) fclose(fout); + return 0; +} + +// +// Ultralight C Dump Card Contents to file +// +int CmdHF14AMfUCDump(const char *Cmd){ + int i; + uint8_t BlockNo = 0; + int Pages=44; + uint8_t *lockbytes_t=NULL; + uint8_t lockbytes[2]={0,0}; + uint8_t *lockbytes_t2=NULL; + uint8_t lockbytes2[2]={0,0}; + bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool bit2[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + bool dump=false; + uint8_t datatemp[5]={0,0,0,0,0}; + + uint8_t isOK = 0; + uint8_t * data = NULL; + FILE *fout; + + dump=true; + if ((fout = fopen("dump_ultralightc_data.bin","wb")) == NULL) { + PrintAndLog("Could not create file name dumpdata.bin"); + return 1; + } + PrintAndLog("Dumping Ultralight C Card Data..."); + PrintAndLog("Attempting to Read Ultralight C... "); + UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}}; + SendCommand(&c); + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + isOK = resp.arg[0] & 0xff; + data = resp.d.asBytes; + PrintAndLog("isOk:%02x", isOK); + if (isOK) + for (i = 0; i < Pages; i++) { + switch(i){ + case 2: + //process lock bytes + lockbytes_t=data+(i*4); + lockbytes[0]=lockbytes_t[2]; + lockbytes[1]=lockbytes_t[3]; + for(int j=0; j<16; j++){ + bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8)); + + } + //might as well read bottom lockbytes too + lockbytes_t2=data+(40*4); + lockbytes2[0]=lockbytes_t2[2]; + lockbytes2[1]=lockbytes_t2[3]; + for(int j=0; j<16; j++){ + bit2[j]=lockbytes2[j/8] & ( 1 <<(7-j%8)); + } + + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 3: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[4]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 4: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[3]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 5: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[2]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 6: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[1]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 7: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[0]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 8: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[15]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 9: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[14]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 10: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[13]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 11: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[12]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 12: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[11]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 13: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[10]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 14: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[9]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 15: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[8]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 16: + case 17: + case 18: + case 19: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[6]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 20: + case 21: + case 22: + case 23: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[5]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 24: + case 25: + case 26: + case 27: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[4]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 28: + case 29: + case 30: + case 31: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[2]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 32: + case 33: + case 34: + case 35: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[1]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 36: + case 37: + case 38: + case 39: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[0]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 40: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[12]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 41: + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[11]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 42: + //auth0 + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[10]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + case 43: + //auth1 + PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),bit2[9]); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + default: + PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4)); + memcpy(datatemp,data + i * 4,4); + if (dump) fwrite ( datatemp, 1, 4, fout ); + break; + } + } + + } else { + PrintAndLog("Command1 execute timeout"); + } + if (dump) fclose(fout); + return 0; +} + +// +// Mifare Ultralight C Write Single Block +// +int CmdHF14AMfUCWrBl(const char *Cmd){ + + uint8_t blockNo = 0; + bool chinese_card=0; + uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + UsbCommand resp; + + if (strlen(Cmd)<3) { + PrintAndLog("Usage: hf mfu ucwrbl [w]"); + PrintAndLog(" sample: hf mfu uwrbl 0 01020304"); + return 0; + } + blockNo = param_get8(Cmd, 0); + if (blockNo>(MAX_ULTRAC_BLOCKS+4)){ + PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight Cards!"); + return 1; + } + if (param_gethex(Cmd, 1, bldata, 8)) { + PrintAndLog("Block data must include 8 HEX symbols"); + return 1; + } + if (strchr(Cmd,'w') != 0) { + chinese_card=1; + } + switch(blockNo){ + case 0: + if (!chinese_card){ + PrintAndLog("Access Denied"); + }else{ + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(d.d.asBytes,bldata, 4); + SendCommand(&d); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + break; + case 1: + if (!chinese_card){ + PrintAndLog("Access Denied"); + }else{ + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(d.d.asBytes,bldata, 4); + SendCommand(&d); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + break; + case 2: + if (!chinese_card){ + PrintAndLog("Access Denied"); + }else{ + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(c.d.asBytes, bldata, 4); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + } + break; + case 3: + PrintAndLog("--specialblock no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(d.d.asBytes,bldata, 4); + SendCommand(&d); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + break; + default: + PrintAndLog("--block no:%02x", blockNo); + PrintAndLog("--data: %s", sprint_hex(bldata, 4)); + UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}}; + memcpy(e.d.asBytes,bldata, 4); + SendCommand(&e); + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLog("isOk:%02x", isOK); + } else { + PrintAndLog("Command execute timeout"); + } + break; + } + return 0; +} + +//------------------------------------ +// Menu Stuff +//------------------------------------ +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1,"This help"}, + {"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"}, + {"urdbl", CmdHF14AMfURdBl, 0,"Read MIFARE Ultralight block"}, + {"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"}, + {"udump", CmdHF14AMfUDump, 0,"Dump MIFARE Ultralight tag to binary file"}, + {"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"}, + {"ucrdbl", CmdHF14AMfUCRdBl, 0,"Read MIFARE Ultralight C block"}, + {"ucrdcard",CmdHF14AMfUCRdCard, 0,"Read MIFARE Ultralight C Card"}, + {"ucdump", CmdHF14AMfUCDump, 0,"Dump MIFARE Ultralight C tag to binary file"}, + {"ucwrbl", CmdHF14AMfUCWrBl, 0,"Write MIFARE Ultralight C block"}, + {"auth", CmdHF14AMfucAuth, 0,"Ultralight C Authentication"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFMFUltra(const char *Cmd){ + // flush + WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd){ + CmdsHelp(CommandTable); + return 0; +} \ No newline at end of file diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h new file mode 100644 index 00000000..20f25d1d --- /dev/null +++ b/client/cmdhfmfu.h @@ -0,0 +1,16 @@ +#include "cmdhfmf.h" + +//standard ultralight +int CmdHF14AMfUWrBl(const char *Cmd); +int CmdHF14AMfURdBl(const char *Cmd); +int CmdHF14AMfURdCard(const char *Cmd); +int CmdHF14AMfUDump(const char *Cmd); +//Crypto Cards +int CmdHF14AMfUCRdBl(const char *Cmd); +int CmdHF14AMfUCRdCard(const char *Cmd); +int CmdHF14AMfUCDump(const char *Cmd); +int CmdHF14AMfucAuth(const char *Cmd); +void rol (uint8_t *data, const size_t len); + +//general stuff +int CmdHFMFUltra(const char *Cmd); diff --git a/client/cmdhw.c b/client/cmdhw.c index 4f0f3e38..a526fe86 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -13,7 +13,6 @@ #include #include #include "ui.h" -//#include "proxusb.h" #include "proxmark3.h" #include "cmdparser.h" #include "cmdhw.h" diff --git a/client/cmdlf.c b/client/cmdlf.c index 22aa1e05..71d87f16 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -12,7 +12,6 @@ #include #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "data.h" #include "graph.h" diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index a7312d21..3c46d3b1 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -11,14 +11,19 @@ #include #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "ui.h" #include "graph.h" +#include "cmdmain.h" #include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" #include "cmdlfem4x.h" +#include "util.h" +#include "data.h" +#define LF_TRACE_BUFF_SIZE 16000 + +char *global_em410xId; static int CmdHelp(const char *Cmd); @@ -139,6 +144,8 @@ retest: PrintAndLog("EM410x Tag ID: %s", id); PrintAndLog("Unique Tag ID: %s", id2); + global_em410xId = id; + /* Stop any loops */ return 1; } @@ -167,8 +174,9 @@ retest: } /* if we've already retested after flipping bits, return */ - if (retested++) + if (retested++){ return 0; + } /* if this didn't work, try flipping bits */ for (i = 0; i < bit2idx; i++) @@ -252,6 +260,7 @@ int CmdEM410xSim(const char *Cmd) int CmdEM410xWatch(const char *Cmd) { int read_h = (*Cmd == 'h'); + //char k; do { CmdLFRead(read_h ? "h" : ""); @@ -264,7 +273,22 @@ int CmdEM410xWatch(const char *Cmd) // Changed by martin, 4000 x 4 = 16000, // see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235 CmdSamples("16000"); + } while ( + !CmdEM410xRead("") + ); + return 0; +} + +int CmdEM410xWatchnSpoof(const char *Cmd) +{ + int read_h = (*Cmd == 'h'); + do + { + CmdLFRead(read_h ? "h" : ""); + CmdSamples("16000"); } while ( ! CmdEM410xRead("")); + PrintAndLog("# Replaying : %s",global_em410xId); + CmdEM410xSim(global_em410xId); return 0; } @@ -482,48 +506,97 @@ int CmdEM410xWrite(const char *Cmd) int CmdReadWord(const char *Cmd) { - int Word = 16; //default to invalid word - UsbCommand c; + int Word = -1; //default to invalid word + UsbCommand c; - sscanf(Cmd, "%d", &Word); + sscanf(Cmd, "%d", &Word); - if (Word > 15) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } + if ( (Word > 15) | (Word < 0) ) { + PrintAndLog("Word must be between 0 and 15"); + return 1; + } - PrintAndLog("Reading word %d", Word); + PrintAndLog("Reading word %d", Word); - c.cmd = CMD_EM4X_READ_WORD; - c.d.asBytes[0] = 0x0; //Normal mode - c.arg[0] = 0; - c.arg[1] = Word; - c.arg[2] = 0; - SendCommand(&c); + c.cmd = CMD_EM4X_READ_WORD; + c.d.asBytes[0] = 0x0; //Normal mode + c.arg[0] = 0; + c.arg[1] = Word; + c.arg[2] = 0; + SendCommand(&c); + WaitForResponse(CMD_ACK, NULL); + + uint8_t data[LF_TRACE_BUFF_SIZE]; + memset(data, 0x00, LF_TRACE_BUFF_SIZE); + + GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,3560); //3560 -- should be offset.. + WaitForResponseTimeout(CMD_ACK,NULL, 1500); + + for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) { + GraphBuffer[j] = ((int)data[j]) - 128; + } + GraphTraceLen = LF_TRACE_BUFF_SIZE; + + // BiDirectional + //CmdDirectionalThreshold("70 -60"); + + // Askdemod + //Cmdaskdemod("1"); + + uint8_t bits[1000]; + uint8_t * bitstream = bits; + memset(bitstream, 0x00, sizeof(bits)); + + manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream); + return 0; } int CmdReadWordPWD(const char *Cmd) { - int Word = 16; //default to invalid word - int Password = 0xFFFFFFFF; //default to blank password - UsbCommand c; - - sscanf(Cmd, "%d %x", &Word, &Password); - - if (Word > 15) { - PrintAndLog("Word must be between 0 and 15"); - return 1; - } - - PrintAndLog("Reading word %d with password %08X", Word, Password); + int Word = -1; //default to invalid word + int Password = 0xFFFFFFFF; //default to blank password + UsbCommand c; + + sscanf(Cmd, "%d %x", &Word, &Password); + + if ( (Word > 15) | (Word < 0) ) { + PrintAndLog("Word must be between 0 and 15"); + return 1; + } - c.cmd = CMD_EM4X_READ_WORD; - c.d.asBytes[0] = 0x1; //Password mode - c.arg[0] = 0; - c.arg[1] = Word; - c.arg[2] = Password; - SendCommand(&c); + PrintAndLog("Reading word %d with password %08X", Word, Password); + + c.cmd = CMD_EM4X_READ_WORD; + c.d.asBytes[0] = 0x1; //Password mode + c.arg[0] = 0; + c.arg[1] = Word; + c.arg[2] = Password; + SendCommand(&c); + WaitForResponse(CMD_ACK, NULL); + + uint8_t data[LF_TRACE_BUFF_SIZE]; + memset(data, 0x00, LF_TRACE_BUFF_SIZE); + + GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,3560); //3560 -- should be offset.. + WaitForResponseTimeout(CMD_ACK,NULL, 1500); + + for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) { + GraphBuffer[j] = ((int)data[j]) - 128; + } + GraphTraceLen = LF_TRACE_BUFF_SIZE; + + // BiDirectional + //CmdDirectionalThreshold("70 -60"); + + // Askdemod + //Cmdaskdemod("1"); + + uint8_t bits[1000]; + uint8_t * bitstream = bits; + memset(bitstream, 0x00, sizeof(bits)); + + manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream); return 0; } @@ -576,20 +649,19 @@ int CmdWriteWordPWD(const char *Cmd) return 0; } - - static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"}, - {"em410xsim", CmdEM410xSim, 0, " -- Simulate EM410x tag"}, - {"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, - {"em410xwrite", CmdEM410xWrite, 1, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, - {"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, - {"readword", CmdReadWord, 1, " -- Read EM4xxx word data"}, - {"readwordPWD", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode"}, - {"writeword", CmdWriteWord, 1, " -- Write EM4xxx word data"}, - {"writewordPWD", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, + {"410read", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"}, + {"410sim", CmdEM410xSim, 0, " -- Simulate EM410x tag"}, + {"410watch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"}, + {"410spoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" }, + {"410write", CmdEM410xWrite, 1, " <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"}, + {"4xread", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"}, + {"rd", CmdReadWord, 1, " -- Read EM4xxx word data"}, + {"rdpwd", CmdReadWordPWD, 1, " -- Read EM4xxx word data in password mode "}, + {"wr", CmdWriteWord, 1, " -- Write EM4xxx word data"}, + {"wrpwd", CmdWriteWordPWD, 1, " -- Write EM4xxx word data in password mode"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index dd413d2e..9dd11f18 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -10,7 +10,6 @@ #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "ui.h" #include "graph.h" diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index af61bd36..038ec887 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -12,13 +12,12 @@ #include #include #include "data.h" -//#include "proxusb.h" #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" -#include "common.h" +#include "../include/common.h" #include "util.h" -#include "hitag2.h" +#include "../include/hitag2.h" #include "sleep.h" #include "cmdmain.h" diff --git a/client/cmdlfio.c b/client/cmdlfio.c index a3d79b2b..d7d36bc1 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -3,7 +3,6 @@ #include #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "data.h" #include "graph.h" diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index 13917146..0d8fb93d 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -10,7 +10,6 @@ #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "ui.h" #include "graph.h" diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 9783370c..a002bf34 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -10,65 +10,122 @@ #include #include #include -//#include "proxusb.h" #include "proxmark3.h" #include "ui.h" #include "graph.h" +#include "cmdmain.h" #include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" #include "cmdlft55xx.h" +#include "util.h" +#include "data.h" +#define LF_TRACE_BUFF_SIZE 16000 static int CmdHelp(const char *Cmd); int CmdReadBlk(const char *Cmd) { - int Block = 8; //default to invalid block - UsbCommand c; - - sscanf(Cmd, "%d", &Block); - - if (Block > 7) { - PrintAndLog("Block must be between 0 and 7"); - return 1; - } - - PrintAndLog("Reading block %d", Block); - - c.cmd = CMD_T55XX_READ_BLOCK; - c.d.asBytes[0] = 0x0; //Normal mode - c.arg[0] = 0; - c.arg[1] = Block; - c.arg[2] = 0; - SendCommand(&c); + //default to invalid block + int Block = -1; + UsbCommand c; + + sscanf(Cmd, "%d", &Block); + + if ((Block > 7) | (Block < 0)) { + PrintAndLog("Block must be between 0 and 7"); + return 1; + } + + PrintAndLog(" Reading page 0 block : %d", Block); + + // this command fills up BigBuff + // + c.cmd = CMD_T55XX_READ_BLOCK; + c.d.asBytes[0] = 0x00; + c.arg[0] = 0; + c.arg[1] = Block; + c.arg[2] = 0; + SendCommand(&c); + WaitForResponse(CMD_ACK, NULL); + + uint8_t data[LF_TRACE_BUFF_SIZE]; + memset(data, 0x00, LF_TRACE_BUFF_SIZE); + + GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,3560); //3560 -- should be offset.. + WaitForResponseTimeout(CMD_ACK,NULL, 1500); + + for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) { + GraphBuffer[j] = ((int)data[j]) - 128; + } + GraphTraceLen = LF_TRACE_BUFF_SIZE; + + // BiDirectional + //CmdDirectionalThreshold("70 60"); + + // Askdemod + //Cmdaskdemod("1"); + + uint8_t bits[1000]; + uint8_t * bitstream = bits; + memset(bitstream, 0x00, sizeof(bits)); + + manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream); + return 0; } + int CmdReadBlkPWD(const char *Cmd) { - int Block = 8; //default to invalid block - int Password = 0xFFFFFFFF; //default to blank Block 7 - UsbCommand c; - - sscanf(Cmd, "%d %x", &Block, &Password); - - if (Block > 7) { - PrintAndLog("Block must be between 0 and 7"); - return 1; - } - - PrintAndLog("Reading block %d with password %08X", Block, Password); - - c.cmd = CMD_T55XX_READ_BLOCK; - c.d.asBytes[0] = 0x1; //Password mode - c.arg[0] = 0; - c.arg[1] = Block; - c.arg[2] = Password; - SendCommand(&c); + int Block = -1; //default to invalid block + int Password = 0xFFFFFFFF; //default to blank Block 7 + UsbCommand c; + + sscanf(Cmd, "%d %x", &Block, &Password); + + if ((Block > 7) | (Block < 0)) { + PrintAndLog("Block must be between 0 and 7"); + return 1; + } + + PrintAndLog("Reading page 0 block %d pwd %08X", Block, Password); + + c.cmd = CMD_T55XX_READ_BLOCK; + c.d.asBytes[0] = 0x1; //Password mode + c.arg[0] = 0; + c.arg[1] = Block; + c.arg[2] = Password; + SendCommand(&c); + WaitForResponse(CMD_ACK, NULL); + + uint8_t data[LF_TRACE_BUFF_SIZE]; + memset(data, 0x00, LF_TRACE_BUFF_SIZE); + + GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,3560); //3560 -- should be offset.. + WaitForResponseTimeout(CMD_ACK,NULL, 1500); + + for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) { + GraphBuffer[j] = ((int)data[j]) - 128; + } + GraphTraceLen = LF_TRACE_BUFF_SIZE; + + // BiDirectional + //CmdDirectionalThreshold("70 -60"); + + // Askdemod + //Cmdaskdemod("1"); + + uint8_t bits[1000]; + uint8_t * bitstream = bits; + memset(bitstream, 0x00, sizeof(bits)); + + manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream); return 0; } + int CmdWriteBlk(const char *Cmd) { int Block = 8; //default to invalid block @@ -120,22 +177,47 @@ int CmdWriteBlkPWD(const char *Cmd) int CmdReadTrace(const char *Cmd) { - - PrintAndLog("Reading traceability data"); + PrintAndLog(" Reading page 1 - tracedata"); UsbCommand c = {CMD_T55XX_READ_TRACE, {0, 0, 0}}; SendCommand(&c); + WaitForResponse(CMD_ACK, NULL); + + uint8_t data[LF_TRACE_BUFF_SIZE]; + memset(data, 0x00, LF_TRACE_BUFF_SIZE); + + GetFromBigBuf(data,LF_TRACE_BUFF_SIZE,3560); //3560 -- should be offset.. + WaitForResponseTimeout(CMD_ACK,NULL, 1500); + + for (int j = 0; j < LF_TRACE_BUFF_SIZE; j++) { + GraphBuffer[j] = ((int)data[j]) - 128; + } + GraphTraceLen = LF_TRACE_BUFF_SIZE; + + // BiDirectional + //CmdDirectionalThreshold("70 -60"); + + // Askdemod + //Cmdaskdemod("1"); + + + uint8_t bits[1000]; + uint8_t * bitstream = bits; + memset(bitstream, 0x00, sizeof(bits)); + + manchester_decode(GraphBuffer, LF_TRACE_BUFF_SIZE, bitstream); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"readblock", CmdReadBlk, 1, " -- Read T55xx block data (page 0)"}, - {"readblockPWD", CmdReadBlkPWD, 1, " -- Read T55xx block data in password mode(page 0)"}, - {"writeblock", CmdWriteBlk, 1, " -- Write T55xx block data (page 0)"}, - {"writeblockPWD", CmdWriteBlkPWD, 1, " -- Write T55xx block data in password mode(page 0)"}, - {"readtrace", CmdReadTrace, 1, "Read T55xx traceability data (page 1)"}, + {"help", CmdHelp, 1, "This help"}, + {"rd", CmdReadBlk, 0, " -- Read T55xx block data (page 0)"}, + {"rdPWD", CmdReadBlkPWD, 0, " -- Read T55xx block data in password mode(page 0)"}, + {"wr", CmdWriteBlk, 0, " -- Write T55xx block data (page 0)"}, + {"wrPWD", CmdWriteBlkPWD, 0, " -- Write T55xx block data in password mode(page 0)"}, + {"trace", CmdReadTrace, 0, "Read T55xx traceability data (page 1)"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 26128e2f..cb5fcd79 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -11,7 +11,6 @@ #include #include #include "crc16.h" -//#include "proxusb.h" #include "proxmark3.h" #include "data.h" #include "ui.h" diff --git a/client/cmdmain.c b/client/cmdmain.c index fa358fac..c56aaa63 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -16,7 +16,7 @@ #include "cmdparser.h" #include "proxmark3.h" #include "data.h" -#include "usb_cmd.h" +#include "../include/usb_cmd.h" #include "ui.h" #include "cmdhf.h" #include "cmddata.h" diff --git a/client/cmdmain.h b/client/cmdmain.h index 0cf2b35d..5e4ee73a 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -11,7 +11,7 @@ #ifndef CMDMAIN_H__ #define CMDMAIN_H__ -#include "usb_cmd.h" +#include "../include/usb_cmd.h" #include "cmdparser.h" void UsbCommandReceived(UsbCommand *UC); void CommandReceived(char *Cmd); diff --git a/client/data.c b/client/data.c index 51134d48..72acf8a6 100644 --- a/client/data.c +++ b/client/data.c @@ -12,7 +12,6 @@ #include #include "data.h" #include "ui.h" -//#include "proxusb.h" #include "proxmark3.h" #include "cmdmain.h" diff --git a/client/flash.c b/client/flash.c index 3a0a1cda..60c04adc 100644 --- a/client/flash.c +++ b/client/flash.c @@ -13,11 +13,10 @@ #include #include "proxmark3.h" #include "sleep.h" -//#include "proxusb.h" #include "flash.h" #include "elf.h" #include "proxendian.h" -#include "usb_cmd.h" +#include "../include/usb_cmd.h" void SendCommand(UsbCommand* txcmd); void ReceiveCommand(UsbCommand* rxcmd); diff --git a/client/flasher.c b/client/flasher.c index 2a24ba8f..1390d817 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -13,7 +13,7 @@ #include "proxmark3.h" #include "flash.h" #include "uart.h" -#include "usb_cmd.h" +#include "../include/usb_cmd.h" #ifdef _WIN32 # define unlink(x) diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 463ba9be..8b1a523d 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -203,7 +203,7 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out) BitstreamIn input_32_zeroes = {zeroes_32,sizeof(zeroes_32)*8,0}; State initState = suc(k,init(k),&input); output(k,initState,&input_32_zeroes,&out); -} +} void doMAC(uint8_t *cc_nr_p, int length, uint8_t *div_key_p, uint8_t mac[4]) { @@ -212,17 +212,17 @@ void doMAC(uint8_t *cc_nr_p, int length, uint8_t *div_key_p, uint8_t mac[4]) cc_nr=(uint8_t*)malloc(length+1); memcpy(cc_nr,cc_nr_p,length); memcpy(div_key,div_key_p,8); - - reverse_arraybytes(cc_nr,length); - BitstreamIn bitstream = {cc_nr,length * 8,0}; - uint8_t dest []= {0,0,0,0,0,0,0,0}; - BitstreamOut out = { dest, sizeof(dest)*8, 0 }; - MAC(div_key,bitstream, out); - //The output MAC must also be reversed - reverse_arraybytes(dest, sizeof(dest)); - memcpy(mac, dest, 4); + + reverse_arraybytes(cc_nr,length); + BitstreamIn bitstream = {cc_nr,length * 8,0}; + uint8_t dest []= {0,0,0,0,0,0,0,0}; + BitstreamOut out = { dest, sizeof(dest)*8, 0 }; + MAC(div_key,bitstream, out); + //The output MAC must also be reversed + reverse_arraybytes(dest, sizeof(dest)); + memcpy(mac,dest,4); //printf("Calculated_MAC\t%02x%02x%02x%02x\n", dest[0],dest[1],dest[2],dest[3]); - free(cc_nr); + free(cc_nr); return; } @@ -248,8 +248,8 @@ int testMAC() prnlog("[+] FAILED: MAC calculation failed:"); printarr(" Calculated_MAC", calculated_mac, 4); printarr(" Correct_MAC ", correct_MAC, 4); - return 1; - } + return 1; +} return 0; } diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 2f7b6b65..08e1c1a7 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -11,8 +11,8 @@ * @return */ int fileExists(const char *filename) { - struct stat st; - int result = stat(filename, &st); + struct _stat fileStat; + int result = _stat(filename, &fileStat); return result == 0; } diff --git a/client/mifarehost.h b/client/mifarehost.h index 5de082ce..f21b9139 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -15,7 +15,6 @@ #include "cmdmain.h" #include "ui.h" #include "data.h" -//#include "proxusb.h" #include "util.h" #include "nonce2key/nonce2key.h" #include "nonce2key/crapto1.h" diff --git a/client/proxmark3.c b/client/proxmark3.c index 528cae34..a9819b54 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -62,21 +62,6 @@ struct main_loop_arg { char *script_cmds_file; }; -//static void *usb_receiver(void *targ) { -// struct receiver_arg *arg = (struct receiver_arg*)targ; -// UsbCommand cmdbuf; -// -// while (arg->run) { -// if (ReceiveCommandPoll(&cmdbuf)) { -// UsbCommandReceived(&cmdbuf); -// fflush(NULL); -// } -// } -// -// pthread_exit(NULL); -// return NULL; -//} - byte_t rx[0x1000000]; byte_t* prx = rx; @@ -207,14 +192,6 @@ static void *main_loop(void *targ) { return NULL; } -//static void dumpHelp(char *parent, ...) -//{ -// printf("## %s\n\n", parent); -// CommandReceived(parent); -// -// printf("\n"); -//} - static void dumpAllHelp(int markdown) { printf("\n%sProxmark3 command dump%s\n\n",markdown?"# ":"",markdown?"":"\n======================"); @@ -254,17 +231,6 @@ int main(int argc, char* argv[]) { }; pthread_t main_loop_t; -/* - usb_init(); - if (!OpenProxmark(1)) { - fprintf(stderr,"PROXMARK3: NOT FOUND!\n"); - marg.usb_present = 0; - offline = 1; - } else { - marg.usb_present = 1; - offline = 0; - } -*/ sp = uart_open(argv[1]); if (sp == INVALID_SERIAL_PORT) { @@ -305,10 +271,6 @@ int main(int argc, char* argv[]) { pthread_join(main_loop_t, NULL); -// if (marg.usb_present == 1) { -// CloseProxmark(); -// } - // Clean up the port uart_close(sp); diff --git a/client/proxmark3.h b/client/proxmark3.h index 8236bfe7..a634fd68 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -20,7 +20,7 @@ #include "usb_cmd.h" -#define PROXPROMPT "proxmark3> " +#define PROXPROMPT "pm3 --> " void SendCommand(UsbCommand *c); diff --git a/client/ui.c b/client/ui.c index c0d01bc3..4f1b5d85 100644 --- a/client/ui.c +++ b/client/ui.c @@ -90,3 +90,279 @@ void SetLogFilename(char *fn) { logfilename = fn; } + + +int manchester_decode(const int * data, const size_t len, uint8_t * dataout){ + + int bitlength = 0; + int i, clock, high, low, startindex; + low = startindex = 0; + high = 1; + uint8_t bitStream[len]; + + memset(bitStream, 0x00, len); + + /* Detect high and lows */ + for (i = 0; i < len; i++) { + if (data[i] > high) + high = data[i]; + else if (data[i] < low) + low = data[i]; + } + + /* get clock */ + clock = GetT55x7Clock( data, len, high ); + startindex = DetectFirstTransition(data, len, high, low); + + PrintAndLog(" Clock : %d", clock); + PrintAndLog(" startindex : %d", startindex); + + if (high != 1) + bitlength = ManchesterConvertFrom255(data, len, bitStream, high, low, clock, startindex); + else + bitlength= ManchesterConvertFrom1(data, len, bitStream, clock, startindex); + + if ( bitlength > 0 ){ + PrintPaddedManchester(bitStream, bitlength, clock); + } + + memcpy(dataout, bitStream, bitlength); + + free(bitStream); + return bitlength; +} + + int GetT55x7Clock( const int * data, const size_t len, int peak ){ + + int i,lastpeak,clock; + clock = 0xFFFF; + lastpeak = 0; + + /* Detect peak if we don't have one */ + if (!peak) { + for (i = 0; i < len; ++i) { + if (data[i] > peak) { + peak = data[i]; + } + } + } + + for (i = 1; i < len; ++i) { + /* if this is the beginning of a peak */ + if ( data[i-1] != data[i] && data[i] == peak) { + /* find lowest difference between peaks */ + if (lastpeak && i - lastpeak < clock) + clock = i - lastpeak; + lastpeak = i; + } + } + //return clock; + //defaults clock to precise values. + switch(clock){ + case 8: + case 16: + case 32: + case 40: + case 50: + case 64: + case 100: + case 128: + return clock; + break; + default: break; + } + return 32; + } + + int DetectFirstTransition(const int * data, const size_t len, int high, int low){ + + int i, retval; + retval = 0; + /* + Detect first transition Lo-Hi (arbitrary) + skip to the first high + */ + for (i = 0; i < len; ++i) + if (data[i] == high) + break; + + /* now look for the first low */ + for (; i < len; ++i) { + if (data[i] == low) { + retval = i; + break; + } + } + return retval; + } + + int ManchesterConvertFrom255(const int * data, const size_t len, uint8_t * dataout, int high, int low, int clock, int startIndex){ + + int i, j, hithigh, hitlow, first, bit, bitIndex; + i = startIndex; + bitIndex = 0; + + /* + * We assume the 1st bit is zero, it may not be + * the case: this routine (I think) has an init problem. + * Ed. + */ + bit = 0; + + for (; i < (int)(len / clock); i++) + { + hithigh = 0; + hitlow = 0; + first = 1; + + /* Find out if we hit both high and low peaks */ + for (j = 0; j < clock; j++) + { + if (data[(i * clock) + j] == high) + hithigh = 1; + else if (data[(i * clock) + j] == low) + hitlow = 1; + + /* it doesn't count if it's the first part of our read + because it's really just trailing from the last sequence */ + if (first && (hithigh || hitlow)) + hithigh = hitlow = 0; + else + first = 0; + + if (hithigh && hitlow) + break; + } + + /* If we didn't hit both high and low peaks, we had a bit transition */ + if (!hithigh || !hitlow) + bit ^= 1; + + dataout[bitIndex++] = bit; + } + return bitIndex; + } + + int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout, int clock, int startIndex){ + + int i,j, bitindex, lc, tolerance, warnings; + warnings = 0; + int upperlimit = len*2/clock+8; + i = startIndex; + j = 0; + tolerance = clock/4; + uint8_t decodedArr[len]; + + /* Then detect duration between 2 successive transitions */ + for (bitindex = 1; i < len; i++) { + + if (data[i-1] != data[i]) { + lc = i - startIndex; + startIndex = i; + + // Error check: if bitindex becomes too large, we do not + // have a Manchester encoded bitstream or the clock is really wrong! + if (bitindex > upperlimit ) { + PrintAndLog("Error: the clock you gave is probably wrong, aborting."); + return 0; + } + // Then switch depending on lc length: + // Tolerance is 1/4 of clock rate (arbitrary) + if (abs((lc-clock)/2) < tolerance) { + // Short pulse : either "1" or "0" + decodedArr[bitindex++] = data[i-1]; + } else if (abs(lc-clock) < tolerance) { + // Long pulse: either "11" or "00" + decodedArr[bitindex++] = data[i-1]; + decodedArr[bitindex++] = data[i-1]; + } else { + ++warnings; + PrintAndLog("Warning: Manchester decode error for pulse width detection."); + if (warnings > 10) { + PrintAndLog("Error: too many detection errors, aborting."); + return 0; + } + } + } + } + + /* + * We have a decodedArr of "01" ("1") or "10" ("0") + * parse it into final decoded dataout + */ + for (i = 0; i < bitindex; i += 2) { + + if ((decodedArr[i] == 0) && (decodedArr[i+1] == 1)) { + dataout[j++] = 1; + } else if ((decodedArr[i] == 1) && (decodedArr[i+1] == 0)) { + dataout[j++] = 0; + } else { + i++; + warnings++; + PrintAndLog("Unsynchronized, resync..."); + PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)"); + + if (warnings > 10) { + PrintAndLog("Error: too many decode errors, aborting."); + return 0; + } + } + } + + PrintAndLog("%s", sprint_hex(dataout, j)); + return j; + } + + void ManchesterDiffDecodedString(const uint8_t* bitstream, size_t len, uint8_t invert){ + /* + * We have a bitstream of "01" ("1") or "10" ("0") + * parse it into final decoded bitstream + */ + int i, j, warnings; + uint8_t decodedArr[(len/2)+1]; + + j = warnings = 0; + + uint8_t lastbit = 0; + + for (i = 0; i < len; i += 2) { + + uint8_t first = bitstream[i]; + uint8_t second = bitstream[i+1]; + + if ( first == second ) { + ++i; + ++warnings; + if (warnings > 10) { + PrintAndLog("Error: too many decode errors, aborting."); + return; + } + } + else if ( lastbit != first ) { + decodedArr[j++] = 0 ^ invert; + } + else { + decodedArr[j++] = 1 ^ invert; + } + lastbit = second; + } + + PrintAndLog("%s", sprint_hex(decodedArr, j)); +} + + +void PrintPaddedManchester( uint8_t* bitStream, size_t len, size_t blocksize){ + + PrintAndLog(" Manchester decoded bitstream : %d bits", len); + + uint8_t mod = len % blocksize; + uint8_t div = len / blocksize; + int i; + // Now output the bitstream to the scrollback by line of 16 bits + for (i = 0; i < div*blocksize; i+=blocksize) { + PrintAndLog(" %s", sprint_bin(bitStream+i,blocksize) ); + } + if ( mod > 0 ){ + PrintAndLog(" %s", sprint_bin(bitStream+i, mod) ); + } +} diff --git a/client/ui.h b/client/ui.h index a45799d5..f599ef3c 100644 --- a/client/ui.h +++ b/client/ui.h @@ -11,6 +11,8 @@ #ifndef UI_H__ #define UI_H__ +#include "util.h" + void ShowGui(void); void HideGraphWindow(void); void ShowGraphWindow(void); @@ -23,4 +25,11 @@ extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault; extern int offline; extern int flushAfterWrite; //buzzy +int manchester_decode(const int * data, const size_t len, uint8_t * dataout); +int GetT55x7Clock( const int * data, const size_t len, int high ); +int DetectFirstTransition(const int * data, const size_t len, int high, int low); +void PrintPaddedManchester( uint8_t * bitStream, size_t len, size_t blocksize); +void ManchesterDiffDecodedString( const uint8_t *bitStream, size_t len, uint8_t invert ); +int ManchesterConvertFrom255(const int * data, const size_t len, uint8_t * dataout, int high, int low, int clock, int startIndex); +int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout, int clock, int startIndex); #endif diff --git a/client/util.c b/client/util.c index 15e911a1..1ebfebea 100644 --- a/client/util.c +++ b/client/util.c @@ -13,6 +13,7 @@ #ifndef _WIN32 #include #include + int ukbhit(void) { int cnt = 0; @@ -112,6 +113,17 @@ char * sprint_hex(const uint8_t * data, const size_t len) { return buf; } +char * sprint_bin(const uint8_t * data, const size_t len) { + static char buf[1024]; + char * tmp = buf; + size_t i; + + for (i=0; i < len && i < 1024; i++, tmp++) + sprintf(tmp, "%u", data[i]); + + return buf; +} + void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { while (len--) { @@ -131,6 +143,28 @@ uint64_t bytes_to_num(uint8_t* src, size_t len) return num; } +//assumes little endian +char * printBits(size_t const size, void const * const ptr) +{ + unsigned char *b = (unsigned char*) ptr; + unsigned char byte; + static char buf[1024]; + char * tmp = buf; + int i, j; + + for (i=size-1;i>=0;i--) + { + for (j=7;j>=0;j--) + { + byte = b[i] & (1<>= j; + sprintf(tmp, "%u", byte); + tmp++; + } + } + return buf; +} + // ------------------------------------------------------------------------- // string parameters lib // ------------------------------------------------------------------------- diff --git a/client/util.h b/client/util.h index ce8876ed..2677ab84 100644 --- a/client/util.h +++ b/client/util.h @@ -33,9 +33,11 @@ void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext, int byteCount); void print_hex(const uint8_t * data, const size_t len); char * sprint_hex(const uint8_t * data, const size_t len); +char * sprint_bin(const uint8_t * data, const size_t len); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); +char * printBits(size_t const size, void const * const ptr); char param_getchar(const char *line, int paramnum); uint8_t param_get8(const char *line, int paramnum); @@ -45,3 +47,4 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base); int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt); int param_getstr(const char *line, int paramnum, char * str); + diff --git a/common/Makefile.common b/common/Makefile.common index 2befd456..2b2bb2fb 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -54,7 +54,8 @@ DELETE=del /q MOVE=ren COPY=copy PATHSEP=\\# -FLASH_TOOL=winsrc\\prox.exe +#FLASH_TOOL=winsrc\\prox.exe +FLASH_TOOL=winsrc\\flash.exe DETECTED_OS=Windows endif @@ -67,6 +68,7 @@ INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gp CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n + LIBS = -lgcc THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC)) diff --git a/common/cmd.c b/common/cmd.c index 49d9d942..dae3a8da 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -32,7 +32,7 @@ #include "cmd.h" #include "string.h" -#include "proxmark3.h" +#include "../include/proxmark3.h" //static UsbCommand txcmd; diff --git a/common/cmd.h b/common/cmd.h index b330a219..35885de4 100644 --- a/common/cmd.h +++ b/common/cmd.h @@ -33,8 +33,8 @@ #ifndef _PROXMARK_CMD_H_ #define _PROXMARK_CMD_H_ -#include -#include +#include "../include/common.h" +#include "../include/usb_cmd.h" #include "usb_cdc.h" bool cmd_receive(UsbCommand* cmd); diff --git a/common/crc.h b/common/crc.h new file mode 100644 index 00000000..8e68f3b3 --- /dev/null +++ b/common/crc.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Generic CRC calculation code. +//----------------------------------------------------------------------------- + +#ifndef __CRC_H +#define __CRC_H + +#include + +typedef struct crc { + uint32_t state; + int order; + uint32_t polynom; + uint32_t initial_value; + uint32_t final_xor; + uint32_t mask; +} crc_t; + +/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 + * polynom is the CRC polynom. initial_value is the initial value of a clean state. + * final_xor is XORed onto the state before returning it from crc_result(). */ +extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor); + +/* Update the crc state. data is the data of length data_width bits (only the the + * data_width lower-most bits are used). + */ +extern void crc_update(crc_t *crc, uint32_t data, int data_width); + +/* Clean the crc state, e.g. reset it to initial_value */ +extern void crc_clear(crc_t *crc); + +/* Get the result of the crc calculation */ +extern uint32_t crc_finish(crc_t *crc); + +/* Static initialization of a crc structure */ +#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ + .state = ((_initial_value) & ((1L<<(_order))-1)), \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) } + +#endif /* __CRC_H */ diff --git a/common/crc32.c b/common/crc32.c new file mode 100644 index 00000000..69d770f4 --- /dev/null +++ b/common/crc32.c @@ -0,0 +1,35 @@ +#include +#include +#include "crc32.h" + +#define htole32(x) (x) +#define CRC32_PRESET 0xFFFFFFFF + + +static void crc32_byte (uint32_t *crc, const uint8_t value); + +static void crc32_byte (uint32_t *crc, const uint8_t value) { + /* x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 */ + const uint32_t poly = 0xEDB88320; + + *crc ^= value; + for (int current_bit = 7; current_bit >= 0; current_bit--) { + int bit_out = (*crc) & 0x00000001; + *crc >>= 1; + if (bit_out) + *crc ^= poly; + } +} + +void crc32 (const uint8_t *data, const size_t len, uint8_t *crc) { + uint32_t desfire_crc = CRC32_PRESET; + for (size_t i = 0; i < len; i++) { + crc32_byte (&desfire_crc, data[i]); + } + + *((uint32_t *)(crc)) = htole32 (desfire_crc); +} + +void crc32_append (uint8_t *data, const size_t len) { + crc32 (data, len, data + len); +} diff --git a/common/crc32.h b/common/crc32.h new file mode 100644 index 00000000..0dd2a328 --- /dev/null +++ b/common/crc32.h @@ -0,0 +1,15 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// CRC32 +//----------------------------------------------------------------------------- + +#ifndef __CRC32_H +#define __CRC32_H + +void crc32 (const uint8_t *data, const size_t len, uint8_t *crc); +void crc32_append (uint8_t *data, const size_t len); + +#endif diff --git a/common/desfire.h b/common/desfire.h new file mode 100644 index 00000000..912ca9ff --- /dev/null +++ b/common/desfire.h @@ -0,0 +1,177 @@ +#ifndef __DESFIRE_H +#define __DESFIRE_H + +#include "aes.h" +#define DESFIRE(tag) ((struct desfire_tag *) tag) +#define DESFIRE_KEY(key) ((struct desfire_key *) key) + +#define MAX_CRYPTO_BLOCK_SIZE 16 +/* Mifare DESFire EV1 Application crypto operations */ +#define APPLICATION_CRYPTO_DES 0x00 +#define APPLICATION_CRYPTO_3K3DES 0x40 +#define APPLICATION_CRYPTO_AES 0x80 + +#define MAC_LENGTH 4 +#define CMAC_LENGTH 8 + +typedef enum { + MCD_SEND, + MCD_RECEIVE +} MifareCryptoDirection; + +typedef enum { + MCO_ENCYPHER, + MCO_DECYPHER +} MifareCryptoOperation; + +#define MDCM_MASK 0x000F + +#define CMAC_NONE 0 + +// Data send to the PICC is used to update the CMAC +#define CMAC_COMMAND 0x010 +// Data received from the PICC is used to update the CMAC +#define CMAC_VERIFY 0x020 + +// MAC the command (when MDCM_MACED) +#define MAC_COMMAND 0x100 +// The command returns a MAC to verify (when MDCM_MACED) +#define MAC_VERIFY 0x200 + +#define ENC_COMMAND 0x1000 +#define NO_CRC 0x2000 + +#define MAC_MASK 0x0F0 +#define CMAC_MACK 0xF00 + +/* Communication mode */ +#define MDCM_PLAIN 0x00 +#define MDCM_MACED 0x01 +#define MDCM_ENCIPHERED 0x03 + +/* Error code managed by the library */ +#define CRYPTO_ERROR 0x01 + + +enum DESFIRE_AUTH_SCHEME { + AS_LEGACY, + AS_NEW +}; + +enum DESFIRE_CRYPTOALGO { + T_DES = 0x00, + T_3DES = 0x01, + T_3K3DES = 0x02, + T_AES = 0x03 +}; + +struct desfire_key { + + enum DESFIRE_CRYPTOALGO type; + uint8_t data[24]; + // DES_key_schedule ks1; + // DES_key_schedule ks2; + // DES_key_schedule ks3; + AesCtx aes_ks; + uint8_t cmac_sk1[24]; + uint8_t cmac_sk2[24]; + uint8_t aes_version; +}; + +typedef struct desfire_key *desfirekey_t; + +struct desfire_tag { + iso14a_card_select_t info; + int active; + uint8_t last_picc_error; + uint8_t last_internal_error; + uint8_t last_pcd_error; + desfirekey_t session_key; + enum DESFIRE_AUTH_SCHEME authentication_scheme; + uint8_t authenticated_key_no; + + uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE]; + uint8_t cmac[16]; + uint8_t *crypto_buffer; + size_t crypto_buffer_size; + uint32_t selected_application; +}; +typedef struct desfire_tag *desfiretag_t; + + +/* File types */ +enum DESFIRE_FILE_TYPES { + MDFT_STANDARD_DATA_FILE = 0x00, + MDFT_BACKUP_DATA_FILE = 0x01, + MDFT_VALUE_FILE_WITH_BACKUP = 0x02, + MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03, + MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04 +}; + + + +enum DESFIRE_STATUS { + OPERATION_OK = 0x00, + NO_CHANGES = 0x0c, + OUT_OF_EEPROM_ERROR = 0x0e, + ILLEGAL_COMMAND_CODE = 0x1c, + INTEGRITY_ERROR = 0x1e, + NO_SUCH_KEY = 0x40, + LENGTH_ERROR = 0x7e, + PERMISSION_DENIED = 0x9d, + PARAMETER_ERROR = 0x9e, + APPLICATION_NOT_FOUND = 0xa0, + APPL_INTEGRITY_ERROR = 0xa1, + AUTHENTICATION_ERROR = 0xae, + ADDITIONAL_FRAME = 0xaf, + BOUNDARY_ERROR = 0xbe, + PICC_INTEGRITY_ERROR = 0xc1, + COMMAND_ABORTED = 0xca, + PICC_DISABLED_ERROR = 0xcd, + COUNT_ERROR = 0xce, + DUPLICATE_ERROR = 0xde, + EEPROM_ERROR = 0xee, + FILE_NOT_FOUND = 0xf0, + FILE_INTEGRITY_ERROR = 0xf1 +}; + +enum DESFIRE_CMD { + CREATE_APPLICATION = 0xca, + DELETE_APPLICATION = 0xda, + GET_APPLICATION_IDS = 0x6a, + SELECT_APPLICATION = 0x5a, + FORMAT_PICC = 0xfc, + GET_VERSION = 0x60, + READ_DATA = 0xbd, + WRITE_DATA = 0x3d, + GET_VALUE = 0x6c, + CREDIT = 0x0c, + DEBIT = 0xdc, + LIMITED_CREDIT = 0x1c, + WRITE_RECORD = 0x3b, + READ_RECORDS = 0xbb, + CLEAR_RECORD_FILE = 0xeb, + COMMIT_TRANSACTION = 0xc7, + ABORT_TRANSACTION = 0xa7, + GET_FREE_MEMORY = 0x6e, + GET_FILE_IDS = 0x6f, + GET_FILE_SETTINGS = 0xf5, + CHANGE_FILE_SETTINGS = 0x5f, + CREATE_STD_DATA_FILE = 0xcd, + CREATE_BACKUP_DATA_FILE = 0xcb, + CREATE_VALUE_FILE = 0xcc, + CREATE_LINEAR_RECORD_FILE = 0xc1, + CREATE_CYCLIC_RECORD_FILE = 0xc0, + DELETE_FILE = 0xdf, + AUTHENTICATE = 0x0a, // AUTHENTICATE_NATIVE + AUTHENTICATE_ISO = 0x1a, // AUTHENTICATE_STANDARD + AUTHENTICATE_AES = 0xaa, + CHANGE_KEY_SETTINGS = 0x54, + GET_KEY_SETTINGS = 0x45, + CHANGE_KEY = 0xc4, + GET_KEY_VERSION = 0x64, + AUTHENTICATION_FRAME = 0xAF +}; + +#endif + diff --git a/common/iso14443crc.c b/common/iso14443crc.c index a6def1a9..851546ae 100644 --- a/common/iso14443crc.c +++ b/common/iso14443crc.c @@ -6,7 +6,7 @@ // ISO14443 CRC calculation code. //----------------------------------------------------------------------------- -#include "iso14443crc.h" +#include "../common/iso14443crc.h" static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc) { diff --git a/common/iso14443crc.h b/common/iso14443crc.h index 87347714..80941116 100644 --- a/common/iso14443crc.h +++ b/common/iso14443crc.h @@ -8,7 +8,7 @@ #ifndef __ISO14443CRC_H #define __ISO14443CRC_H -#include "common.h" +#include "../include/common.h" //----------------------------------------------------------------------------- // Routines to compute the CRCs (two different flavours, just for confusion) diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 0f7a250b..964059ce 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -7,7 +7,7 @@ //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "../include/proxmark3.h" #include #include //#include "iso15693tools.h" diff --git a/common/legic_prng.c b/common/legic_prng.c index 4f3b1ffe..322429ad 100644 --- a/common/legic_prng.c +++ b/common/legic_prng.c @@ -6,7 +6,7 @@ // LEFIC's obfuscation function //----------------------------------------------------------------------------- -#include "legic_prng.h" +#include "../include/legic_prng.h" struct lfsr { uint8_t a; diff --git a/common/usb_cdc.c b/common/usb_cdc.c index e2787fb6..097d9a4e 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -33,7 +33,7 @@ */ #include "usb_cdc.h" -#include "config_gpio.h" +#include "../include/config_gpio.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) diff --git a/common/usb_cdc.h b/common/usb_cdc.h index d7b9c2e5..b6489937 100644 --- a/common/usb_cdc.h +++ b/common/usb_cdc.h @@ -35,7 +35,7 @@ #ifndef _USB_CDC_H_ #define _USB_CDC_H_ -#include +#include "../include/common.h" void usb_disable(); void usb_enable(); diff --git a/include/crc.h b/include/crc.h deleted file mode 100644 index 8e68f3b3..00000000 --- a/include/crc.h +++ /dev/null @@ -1,48 +0,0 @@ -//----------------------------------------------------------------------------- -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Generic CRC calculation code. -//----------------------------------------------------------------------------- - -#ifndef __CRC_H -#define __CRC_H - -#include - -typedef struct crc { - uint32_t state; - int order; - uint32_t polynom; - uint32_t initial_value; - uint32_t final_xor; - uint32_t mask; -} crc_t; - -/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 - * polynom is the CRC polynom. initial_value is the initial value of a clean state. - * final_xor is XORed onto the state before returning it from crc_result(). */ -extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor); - -/* Update the crc state. data is the data of length data_width bits (only the the - * data_width lower-most bits are used). - */ -extern void crc_update(crc_t *crc, uint32_t data, int data_width); - -/* Clean the crc state, e.g. reset it to initial_value */ -extern void crc_clear(crc_t *crc); - -/* Get the result of the crc calculation */ -extern uint32_t crc_finish(crc_t *crc); - -/* Static initialization of a crc structure */ -#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ - .state = ((_initial_value) & ((1L<<(_order))-1)), \ - .order = (_order), \ - .polynom = (_polynom), \ - .initial_value = (_initial_value), \ - .final_xor = (_final_xor), \ - .mask = ((1L<<(_order))-1) } - -#endif /* __CRC_H */ diff --git a/include/crc.h.old b/include/crc.h.old new file mode 100644 index 00000000..8e68f3b3 --- /dev/null +++ b/include/crc.h.old @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Generic CRC calculation code. +//----------------------------------------------------------------------------- + +#ifndef __CRC_H +#define __CRC_H + +#include + +typedef struct crc { + uint32_t state; + int order; + uint32_t polynom; + uint32_t initial_value; + uint32_t final_xor; + uint32_t mask; +} crc_t; + +/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 + * polynom is the CRC polynom. initial_value is the initial value of a clean state. + * final_xor is XORed onto the state before returning it from crc_result(). */ +extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor); + +/* Update the crc state. data is the data of length data_width bits (only the the + * data_width lower-most bits are used). + */ +extern void crc_update(crc_t *crc, uint32_t data, int data_width); + +/* Clean the crc state, e.g. reset it to initial_value */ +extern void crc_clear(crc_t *crc); + +/* Get the result of the crc calculation */ +extern uint32_t crc_finish(crc_t *crc); + +/* Static initialization of a crc structure */ +#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ + .state = ((_initial_value) & ((1L<<(_order))-1)), \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) } + +#endif /* __CRC_H */ diff --git a/include/mifare.h b/include/mifare.h index e2b7a7c5..403132ac 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -11,7 +11,7 @@ #ifndef _MIFARE_H_ #define _MIFARE_H_ -#include "common.h" +#include "../include/common.h" //----------------------------------------------------------------------------- // ISO 14443A diff --git a/include/proxmark3.h b/include/proxmark3.h index 8c9417da..b3530c64 100644 --- a/include/proxmark3.h +++ b/include/proxmark3.h @@ -14,6 +14,7 @@ // Might as well have the hardware-specific defines everywhere. #include "at91sam7s512.h" #include "config_gpio.h" +#include "usb_cmd.h" #define WDT_HIT() AT91C_BASE_WDTC->WDTC_WDCR = 0xa5000001 @@ -67,8 +68,6 @@ #define TRUE 1 #define FALSE 0 -#include - //#define PACKED __attribute__((__packed__)) #define LED_A_ON() HIGH(GPIO_LED_A) diff --git a/include/usb_cmd.h b/include/usb_cmd.h index b4e29804..36fcf248 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -117,7 +117,7 @@ typedef struct { #define CMD_SNOOP_ICLASS 0x0392 #define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_READER_ICLASS 0x0394 -#define CMD_READER_ICLASS_REPLAY 0x0395 +#define CMD_READER_ICLASS_REPLAY 0x0395 #define CMD_ICLASS_ISO14443A_WRITE 0x0397 // For measurements of the antenna tuning @@ -144,15 +144,31 @@ typedef struct { #define CMD_MIFARE_NESTED 0x0612 #define CMD_MIFARE_READBL 0x0620 -#define CMD_MIFAREU_READBL 0x0720 +#define CMD_MIFAREU_READBL 0x0720 + #define CMD_MIFARE_READSC 0x0621 -#define CMD_MIFAREU_READCARD 0x0721 +#define CMD_MIFAREU_READCARD 0x0721 + #define CMD_MIFARE_WRITEBL 0x0622 -#define CMD_MIFAREU_WRITEBL_COMPAT 0x0722 -#define CMD_MIFAREU_WRITEBL 0x0723 +#define CMD_MIFAREU_WRITEBL_COMPAT 0x0722 + +#define CMD_MIFAREU_WRITEBL 0x0723 #define CMD_MIFARE_CHKKEYS 0x0623 #define CMD_MIFARE_SNIFFER 0x0630 +//ultralightC +#define CMD_MIFAREUC_AUTH1 0x0724 +#define CMD_MIFAREUC_AUTH2 0x0725 +#define CMD_MIFAREUC_READCARD 0x0726 + +// mifare desfire +#define CMD_MIFARE_DESFIRE_READBL 0x0728 +#define CMD_MIFARE_DESFIRE_WRITEBL 0x0729 +#define CMD_MIFARE_DESFIRE_AUTH1 0x072a +#define CMD_MIFARE_DESFIRE_AUTH2 0x072b +#define CMD_MIFARE_DES_READER 0x072c +#define CMD_MIFARE_DESFIRE_INFO 0x072d +#define CMD_MIFARE_DESFIRE 0x072e #define CMD_UNKNOWN 0xFFFF