From f0d73dc3d1907efcc6c9b39b099663aa6c2b71e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 29 Aug 2019 14:17:39 +0200 Subject: [PATCH] chg: 'hf iclass decrypt' - now takes transport key as param. also search for key / dump. Also saves decrypted to bin/eml/json_decref chg: 'hf iclass encrypt' - now takes transport key as param. --- client/cmdhficlass.c | 154 ++++++++++++++++++++----------------------- client/fileutils.c | 53 ++++++++++++++- client/fileutils.h | 16 ++++- 3 files changed, 136 insertions(+), 87 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 30b2a0560..efb70c69c 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -790,75 +790,61 @@ static int CmdHFiClassELoad(const char *Cmd) { return PM3_SUCCESS; } -static int readKeyfile(const char *filename, size_t len, uint8_t **buffer) { - - char *path; - int res = searchFile(&path, PM3_USER_DIRECTORY, filename, ".bin"); - if (res != PM3_SUCCESS) { - PrintAndLogEx(INFO, "res: %d Curr path:: %s", res, path); - return PM3_EFILE; - } - - size_t datalen = 0; - res = loadFile(path, ".bin", (void*)*buffer, len, &datalen); - if ( res != PM3_SUCCESS ) - return res; - - if (datalen != len) { - PrintAndLogEx(ERR, "ERROR, Wrong filesize. Got %d bytes, expected %d", datalen, len); - return PM3_EFILE; - } - return PM3_SUCCESS; -} +#define ICLASS_DECRYPTION_BIN "iclass_decryptionkey.bin" static int CmdHFiClassDecrypt(const char *Cmd) { - - char opt = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || opt == 'h') return usage_hf_iclass_decrypt(); - - uint8_t key[16] = { 0 }; - uint8_t *keyptr = key; - if (readKeyfile("iclass_decryptionkey", sizeof(key), &keyptr) != PM3_SUCCESS) - return usage_hf_iclass_decrypt(); - - PrintAndLogEx(SUCCESS, "decryption key loaded from file"); - - //Open the tagdump-file - FILE *f; + + bool errors = false; + bool have_key = false; + uint8_t cmdp = 0; + + size_t keylen = 0; + uint8_t key[32] = {0}; + uint8_t *keyptr = NULL; + + size_t decryptedlen = 0; + uint8_t *decrypted = NULL; char filename[FILE_PATH_SIZE]; - if (opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) { - f = fopen(filename, "rb"); - if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); - return PM3_EFILE; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_iclass_decrypt(); + case 'f': + if ( param_getstr(Cmd, cmdp + 1, filename, sizeof(filename) ) == 0){ + errors = true; + break; + } + + if ( loadFile_safe(filename, "", (void**)&decrypted, &decryptedlen) != PM3_SUCCESS ) { + errors = true; + break; + } + cmdp += 2; + break; + case 'k': + if (param_gethex(Cmd, cmdp + 1, key, 32)) { + PrintAndLogEx(ERR, "Transport key must include 32 HEX symbols"); + errors = true; + } + have_key = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; } - } else { - return usage_hf_iclass_decrypt(); } - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); + if (errors || cmdp < 1) return usage_hf_iclass_decrypt(); - if (fsize <= 0) { - PrintAndLogEx(ERR, "error, when getting filesize"); - fclose(f); - return 2; - } - - uint8_t *decrypted = calloc(fsize, sizeof(uint8_t)); - if (!decrypted) { - PrintAndLogEx(WARNING, "Failed to allocate memory"); - fclose(f); - return 1; - } - - size_t bytes_read = fread(decrypted, 1, fsize, f); - fclose(f); - if (bytes_read == 0) { - PrintAndLogEx(ERR, "file reading error"); - free(decrypted); - return 3; + if ( have_key == false ) { + int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void**)&keyptr, &keylen); + if (res != PM3_SUCCESS) + return PM3_EINVARG; + + memcpy(key, keyptr, sizeof(key)); } picopass_hdr *hdr = (picopass_hdr *)decrypted; @@ -870,13 +856,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) { uint8_t app_areas = 2; uint8_t max_blk = 31; getMemConfig(mem, chip, &max_blk, &app_areas, &kb); - - //Use the first block (CSN) for filename - char outfilename[FILE_PATH_SIZE] = {0}; - snprintf(outfilename, FILE_PATH_SIZE, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted", - hdr->csn[0], hdr->csn[1], hdr->csn[2], hdr->csn[3], - hdr->csn[4], hdr->csn[5], hdr->csn[6], hdr->csn[7]); - + // tripledes mbedtls_des3_context ctx; mbedtls_des3_set2key_dec(&ctx, key); @@ -894,12 +874,18 @@ static int CmdHFiClassDecrypt(const char *Cmd) { } } - saveFile(outfilename, ".bin", decrypted, fsize); - saveFileEML(outfilename, decrypted, fsize, 8); - saveFileJSON(outfilename, jsfIclass, decrypted, fsize); + //Use the first block (CSN) for filename + char *fptr = calloc(42, sizeof(uint8_t)); + strcat(fptr, "hf-iclass-"); + FillFileNameByUID(fptr, hdr->csn, "-data-decrypted", sizeof(hdr->csn) ); + + saveFile(fptr, ".bin", decrypted, decryptedlen); + saveFileEML(fptr, decrypted, decryptedlen, 8); + saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen); - printIclassDumpContents(decrypted, 1, (fsize / 8), fsize); + printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen); free(decrypted); + free(fptr); return PM3_SUCCESS; } @@ -917,7 +903,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { bool have_key = false; uint8_t blk_data[8] = {0}; uint8_t key[16] = {0}; - uint8_t *keyptr = key; + uint8_t *keyptr = NULL; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -925,17 +911,16 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { case 'h': return usage_hf_iclass_encrypt(); case 'd': - //get the bytes to encrypt - if (param_gethex(Cmd, cmdp + 1, blk_data, 16) != PM3_SUCCESS) { + if (param_gethex(Cmd, cmdp + 1, blk_data, 16)) { PrintAndLogEx(ERR, "Block data must include 16 HEX symbols"); - errors = true;; + errors = true; } cmdp += 2; break; case 'k': - if (param_gethex(Cmd, cmdp + 1, key, 32) != PM3_SUCCESS) { + if (param_gethex(Cmd, cmdp + 1, key, 32)) { PrintAndLogEx(ERR, "Transport key must include 32 HEX symbols"); - errors = true;; + errors = true; } have_key = true; cmdp += 2; @@ -950,10 +935,12 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) { if (errors || cmdp < 1) return usage_hf_iclass_encrypt(); if ( have_key == false ) { - if (readKeyfile("./iclass_decryptionkey", sizeof(key), &keyptr) != PM3_SUCCESS) { - return usage_hf_iclass_encrypt(); - } - PrintAndLogEx(SUCCESS, "Loaded transport key from decryption file"); + size_t keylen = 0; + int res = loadFile_safe(ICLASS_DECRYPTION_BIN, "", (void**)&keyptr, &keylen); + if (res != PM3_SUCCESS) + return PM3_EINVARG; + + memcpy(key, keyptr, sizeof(key)); } iClassEncryptBlkData(blk_data, key); @@ -1283,6 +1270,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) { PrintAndLogEx(SUCCESS, "saving dump file - %d blocks read", gotBytes / 8); saveFile(filename, ".bin", tag_data, gotBytes); saveFileEML(filename, tag_data, gotBytes, 8); + saveFileJSON(filename, jsfIclass, tag_data, gotBytes); return 1; } diff --git a/client/fileutils.c b/client/fileutils.c index 72771f900..1a6b40e53 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -50,7 +50,7 @@ #include "scandir.h" #endif -#define PATH_MAX_LENGTH 100 +#define PATH_MAX_LENGTH 200 /** * @brief checks if a file exists @@ -289,7 +289,7 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s for (size_t i = 0; i < (datalen / 8); i++) { char path[PATH_MAX_LENGTH] = {0}; - sprintf(path, "$blocks.%zu", i); + sprintf(path, "$.blocks.%zu", i); JsonSaveBufAsHexCompact(root, path, data + (i * 8), 8); } break; @@ -341,6 +341,7 @@ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { return PM3_SUCCESS; } + int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) { if (data == NULL) return 1; @@ -401,6 +402,54 @@ out: return retval; } +int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen) { + + char *path; + int res = searchFile(&path, "", preferredName, suffix); + if (res != PM3_SUCCESS) { + PrintAndLogEx(INFO, "res: %d Curr path:: %s", res, path); + return PM3_EFILE; + } + + int retval = PM3_SUCCESS; + + FILE *f = fopen(path, "rb"); + if (!f) { + PrintAndLogEx(WARNING, "file not found or locked. '" _YELLOW_("%s")"'", path); + return PM3_EFILE; + } + + // get filesize in order to malloc memory + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + if (fsize <= 0) { + PrintAndLogEx(FAILED, "error, when getting filesize"); + return PM3_EFILE; + } + + *pdata = calloc(fsize, sizeof(uint8_t)); + if (!pdata) { + PrintAndLogEx(FAILED, "error, cannot allocate memory"); + return PM3_EMALLOC; + } + + size_t bytes_read = fread(*pdata, 1, fsize, f); + + fclose(f); + + if (bytes_read != fsize) { + PrintAndLogEx(FAILED, "error, bytes read mismatch file size"); + return PM3_EFILE; + } + + *datalen = bytes_read; + + PrintAndLogEx(SUCCESS, "loaded %d bytes from binary file " _YELLOW_("%s"), bytes_read, preferredName); + return retval; +} + int loadFileEML(const char *preferredName, void *data, size_t *datalen) { if (data == NULL) return 1; diff --git a/client/fileutils.h b/client/fileutils.h index 7bfc7c138..d7fdb13a3 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -120,7 +120,7 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s */ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr); -/** STUB +/** * @brief Utility function to load data from a binary file. This method takes a preferred name. * E.g. dumpdata-15.bin * @@ -129,10 +129,22 @@ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr); * @param data The data array to store the loaded bytes from file * @param maxdatalen the number of bytes that your data array has * @param datalen the number of bytes loaded from file - * @return 0 for ok, 1 for failz + * @return PM3_SUCCESS for ok, PM3_E* for failz */ int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen); + +/** + * @brief Utility function to load data from a binary file. This method takes a preferred name. + * E.g. dumpdata-15.bin, tries to search for it, and allocated memory. + * + * @param preferredName + * @param suffix the file suffix. Including the ".". + * @param data The data array to store the loaded bytes from file + * @param datalen the number of bytes loaded from file + * @return PM3_SUCCESS for ok, PM3_E* for failz +*/ +int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen); /** * @brief Utility function to load data from a textfile (EML). This method takes a preferred name. * E.g. dumpdata-15.txt