X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/2a99a730556a54222ac653e803316a7839c7cb58..763d1befc1b9251c49cc88a50c73a3096323736a:/client/cmdhficlass.c diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 6c85e1c1..3b9fccdc 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2,6 +2,7 @@ // Copyright (C) 2010 iZsh , Hagen Fritsch // Copyright (C) 2011 Gerhard de Koning Gans // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende +// Copyright (C) 2019 piwi // // 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 @@ -14,16 +15,17 @@ #include #include #include +#include #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type -#include "data.h" -#include "proxmark3.h" +#include "comms.h" #include "ui.h" +#include "cliparser/cliparser.h" #include "cmdparser.h" #include "cmdhficlass.h" #include "common.h" #include "util.h" #include "cmdmain.h" -#include "loclass/des.h" +#include "mbedtls/des.h" #include "loclass/cipherutils.h" #include "loclass/cipher.h" #include "loclass/ikeys.h" @@ -32,10 +34,9 @@ #include "protocols.h" #include "usb_cmd.h" #include "cmdhfmfu.h" +#include "util_posix.h" +#include "cmdhf14a.h" // DropField() -#define llX PRIx64 - -static int CmdHelp(const char *Cmd); #define ICLASS_KEYS_MAX 8 static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { @@ -49,30 +50,161 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }; + typedef struct iclass_block { - uint8_t d[8]; + uint8_t d[8]; } iclass_block_t; -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; + +// iclass / picopass chip config structures and shared routines +typedef struct { + uint8_t app_limit; //[8] + uint8_t otp[2]; //[9-10] + uint8_t block_writelock;//[11] + uint8_t chip_config; //[12] + uint8_t mem_config; //[13] + uint8_t eas; //[14] + uint8_t fuses; //[15] +} picopass_conf_block; + +typedef struct { + uint8_t csn[8]; + picopass_conf_block conf; + uint8_t epurse[8]; + uint8_t key_d[8]; + uint8_t key_c[8]; + uint8_t app_issuer_area[8]; +} picopass_hdr; + + +static void fuse_config(const picopass_hdr *hdr) { + uint8_t fuses = hdr->conf.fuses; + + if (fuses & FUSE_FPERS) + PrintAndLog(" Mode: Personalization [Programmable]"); + else + PrintAndLog(" Mode: Application [Locked]"); + + if (fuses & FUSE_CODING1) + PrintAndLog("Coding: RFU"); + else { + if (fuses & FUSE_CODING0) + PrintAndLog("Coding: ISO 14443-2 B/ISO 15693"); + else + PrintAndLog("Coding: ISO 14443B only"); + } + if ((fuses & FUSE_CRYPT1) && (fuses & FUSE_CRYPT0)) PrintAndLog(" Crypt: Secured page, keys not locked"); + if ((fuses & FUSE_CRYPT1) && !(fuses & FUSE_CRYPT0)) PrintAndLog(" Crypt: Secured page, keys locked"); + if (!(fuses & FUSE_CRYPT1) && (fuses & FUSE_CRYPT0)) PrintAndLog(" Crypt: Non secured page"); + if (!(fuses & FUSE_CRYPT1) && !(fuses & FUSE_CRYPT0)) PrintAndLog(" Crypt: No auth possible. Read only if RA is enabled"); + + if (fuses & FUSE_RA) + PrintAndLog(" RA: Read access enabled"); + else + PrintAndLog(" RA: Read access not enabled"); +} + + +static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) { + // mem-bit 5, mem-bit 7, chip-bit 4: defines chip type + if((chip_cfg & 0x10) && !(mem_cfg & 0x80) && !(mem_cfg & 0x20)) { + *kb = 2; + *app_areas = 2; + *max_blk = 31; + } else if((chip_cfg & 0x10) && (mem_cfg & 0x80) && !(mem_cfg & 0x20)) { + *kb = 16; + *app_areas = 2; + *max_blk = 255; //16kb + } else if(!(chip_cfg & 0x10) && !(mem_cfg & 0x80) && !(mem_cfg & 0x20)) { + *kb = 16; + *app_areas = 16; + *max_blk = 255; //16kb + } else if((chip_cfg & 0x10) && (mem_cfg & 0x80) && (mem_cfg & 0x20)) { + *kb = 32; + *app_areas = 3; + *max_blk = 255; //16kb + } else if(!(chip_cfg & 0x10) && !(mem_cfg & 0x80) && (mem_cfg & 0x20)) { + *kb = 32; + *app_areas = 17; + *max_blk = 255; //16kb + } else { + *kb = 32; + *app_areas = 2; + *max_blk = 255; + } } -int CmdHFiClassList(const char *Cmd) { + +static void mem_app_config(const picopass_hdr *hdr) { + uint8_t mem = hdr->conf.mem_config; + uint8_t chip = hdr->conf.chip_config; + uint8_t applimit = hdr->conf.app_limit; + if (applimit < 6) applimit = 26; + uint8_t kb = 2; + uint8_t app_areas = 2; + uint8_t max_blk = 31; + getMemConfig(mem, chip, &max_blk, &app_areas, &kb); + PrintAndLog(" Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk+1, mem); + PrintAndLog(" AA1: blocks 06-%02X", applimit); + PrintAndLog(" AA2: blocks %02X-%02X", applimit+1, max_blk); +} + + +static void printIclassDumpInfo(uint8_t* iclass_dump) { + fuse_config((picopass_hdr*)iclass_dump); + mem_app_config((picopass_hdr*)iclass_dump); +} + + +static void usage_hf_iclass_chk(void) { + PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag"); + PrintAndLog("Usage: hf iclass chk [h|e|r] "); + PrintAndLog("Options:"); + PrintAndLog("h Show this help"); + PrintAndLog("f Dictionary file with default iclass keys"); + PrintAndLog(" e target Elite / High security key scheme"); + PrintAndLog(" r interpret dictionary file as raw (diversified keys)"); + PrintAndLog("Samples:"); + PrintAndLog(" hf iclass chk f default_iclass_keys.dic"); + PrintAndLog(" hf iclass chk f default_iclass_keys.dic e"); +} + + +static int CmdHFiClassList(const char *Cmd) { PrintAndLog("Deprecated command, use 'hf list iclass' instead"); return 0; } -int CmdHFiClassSnoop(const char *Cmd) { - UsbCommand c = {CMD_SNOOP_ICLASS}; + +static int CmdHFiClassSnoop(const char *Cmd) { + + CLIParserInit("hf iclass snoop", "\nSnoop a communication between an iClass Reader and an iClass Tag.", NULL); + void* argtable[] = { + arg_param_begin, + arg_lit0("j", "jam", "Jam (prevent) e-purse Updates"), + arg_param_end + }; + if (CLIParserParseString(Cmd, argtable, arg_getsize(argtable), true)){ + CLIParserFree(); + return 0; + } + + bool jam_epurse_update = arg_get_lit(1); + + const uint8_t update_epurse_sequence[2] = {0x87, 0x02}; + + UsbCommand c = {CMD_SNOOP_ICLASS, {0}}; + if (jam_epurse_update) { + c.arg[0] = sizeof(update_epurse_sequence); + memcpy(c.d.asBytes, update_epurse_sequence, sizeof(update_epurse_sequence)); + } SendCommand(&c); + return 0; } -int usage_hf_iclass_sim(void) { + +static void usage_hf_iclass_sim(void) { PrintAndLog("Usage: hf iclass sim