diff --git a/Makefile b/Makefile index 93ee2d19c..bf298e652 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ endif print-%: ; @echo $* = $($*) style: - find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; + find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; # Dummy target to test for GNU make availability _test: diff --git a/client/amiitool/amiibo.c b/client/amiitool/amiibo.c index 85b7b226a..24a9f158d 100644 --- a/client/amiitool/amiibo.c +++ b/client/amiitool/amiibo.c @@ -13,168 +13,168 @@ #define HMAC_POS_TAG 0x1B4 void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) { - memcpy(key + 0x00, dump + 0x029, 0x02); - memset(key + 0x02, 0x00, 0x0E); - memcpy(key + 0x10, dump + 0x1D4, 0x08); - memcpy(key + 0x18, dump + 0x1D4, 0x08); - memcpy(key + 0x20, dump + 0x1E8, 0x20); + memcpy(key + 0x00, dump + 0x029, 0x02); + memset(key + 0x02, 0x00, 0x0E); + memcpy(key + 0x10, dump + 0x1D4, 0x08); + memcpy(key + 0x18, dump + 0x1D4, 0x08); + memcpy(key + 0x20, dump + 0x1E8, 0x20); } void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys * masterKeys, const uint8_t * dump, nfc3d_keygen_derivedkeys * derivedKeys) { - uint8_t seed[NFC3D_KEYGEN_SEED_SIZE]; + uint8_t seed[NFC3D_KEYGEN_SEED_SIZE]; - nfc3d_amiibo_calc_seed(dump, seed); - nfc3d_keygen(masterKeys, seed, derivedKeys); + nfc3d_amiibo_calc_seed(dump, seed); + nfc3d_keygen(masterKeys, seed, derivedKeys); } void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys * keys, const uint8_t * in, uint8_t * out) { - mbedtls_aes_context aes; - size_t nc_off = 0; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; + mbedtls_aes_context aes; + size_t nc_off = 0; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; - mbedtls_aes_setkey_enc( &aes, keys->aesKey, 128 ); - memset(nonce_counter, 0, sizeof(nonce_counter)); - memset(stream_block, 0, sizeof(stream_block)); - memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter)); - mbedtls_aes_crypt_ctr( &aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C ); + mbedtls_aes_setkey_enc( &aes, keys->aesKey, 128 ); + memset(nonce_counter, 0, sizeof(nonce_counter)); + memset(stream_block, 0, sizeof(stream_block)); + memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter)); + mbedtls_aes_crypt_ctr( &aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C ); - memcpy(out + 0x000, in + 0x000, 0x008); - // Data signature NOT copied - memcpy(out + 0x028, in + 0x028, 0x004); - // Tag signature NOT copied - memcpy(out + 0x1D4, in + 0x1D4, 0x034); + memcpy(out + 0x000, in + 0x000, 0x008); + // Data signature NOT copied + memcpy(out + 0x028, in + 0x028, 0x004); + // Tag signature NOT copied + memcpy(out + 0x1D4, in + 0x1D4, 0x034); } void nfc3d_amiibo_tag_to_internal(const uint8_t * tag, uint8_t * intl) { - memcpy(intl + 0x000, tag + 0x008, 0x008); - memcpy(intl + 0x008, tag + 0x080, 0x020); - memcpy(intl + 0x028, tag + 0x010, 0x024); - memcpy(intl + 0x04C, tag + 0x0A0, 0x168); - memcpy(intl + 0x1B4, tag + 0x034, 0x020); - memcpy(intl + 0x1D4, tag + 0x000, 0x008); - memcpy(intl + 0x1DC, tag + 0x054, 0x02C); + memcpy(intl + 0x000, tag + 0x008, 0x008); + memcpy(intl + 0x008, tag + 0x080, 0x020); + memcpy(intl + 0x028, tag + 0x010, 0x024); + memcpy(intl + 0x04C, tag + 0x0A0, 0x168); + memcpy(intl + 0x1B4, tag + 0x034, 0x020); + memcpy(intl + 0x1D4, tag + 0x000, 0x008); + memcpy(intl + 0x1DC, tag + 0x054, 0x02C); } void nfc3d_amiibo_internal_to_tag(const uint8_t * intl, uint8_t * tag) { - memcpy(tag + 0x008, intl + 0x000, 0x008); - memcpy(tag + 0x080, intl + 0x008, 0x020); - memcpy(tag + 0x010, intl + 0x028, 0x024); - memcpy(tag + 0x0A0, intl + 0x04C, 0x168); - memcpy(tag + 0x034, intl + 0x1B4, 0x020); - memcpy(tag + 0x000, intl + 0x1D4, 0x008); - memcpy(tag + 0x054, intl + 0x1DC, 0x02C); + memcpy(tag + 0x008, intl + 0x000, 0x008); + memcpy(tag + 0x080, intl + 0x008, 0x020); + memcpy(tag + 0x010, intl + 0x028, 0x024); + memcpy(tag + 0x0A0, intl + 0x04C, 0x168); + memcpy(tag + 0x034, intl + 0x1B4, 0x020); + memcpy(tag + 0x000, intl + 0x1D4, 0x008); + memcpy(tag + 0x054, intl + 0x1DC, 0x02C); } bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain) { - uint8_t internal[NFC3D_AMIIBO_SIZE]; - nfc3d_keygen_derivedkeys dataKeys; - nfc3d_keygen_derivedkeys tagKeys; + uint8_t internal[NFC3D_AMIIBO_SIZE]; + nfc3d_keygen_derivedkeys dataKeys; + nfc3d_keygen_derivedkeys tagKeys; - // Convert format - nfc3d_amiibo_tag_to_internal(tag, internal); + // Convert format + nfc3d_amiibo_tag_to_internal(tag, internal); - // Generate keys - nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys); - nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys); + // Generate keys + nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys); + nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys); - // Decrypt - nfc3d_amiibo_cipher(&dataKeys, internal, plain); + // Decrypt + nfc3d_amiibo_cipher(&dataKeys, internal, plain); - // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), - plain + 0x1D4, 0x34, plain + HMAC_POS_TAG ); + // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + plain + 0x1D4, 0x34, plain + HMAC_POS_TAG ); - // Regenerate data HMAC - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey), - plain + 0x029, 0x1DF, plain + HMAC_POS_DATA ); + // Regenerate data HMAC + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey), + plain + 0x029, 0x1DF, plain + HMAC_POS_DATA ); - return - memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && - memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0; + return + memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && + memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0; } void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag) { - uint8_t cipher[NFC3D_AMIIBO_SIZE]; - nfc3d_keygen_derivedkeys tagKeys; - nfc3d_keygen_derivedkeys dataKeys; + uint8_t cipher[NFC3D_AMIIBO_SIZE]; + nfc3d_keygen_derivedkeys tagKeys; + nfc3d_keygen_derivedkeys dataKeys; - // Generate keys - nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys); - nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys); + // Generate keys + nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys); + nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys); - // Generate tag HMAC - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), - plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); + // Generate tag HMAC + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); - // Init mbedtls HMAC context - mbedtls_md_context_t ctx; - mbedtls_md_init( &ctx ); - mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 ); + // Init mbedtls HMAC context + mbedtls_md_context_t ctx; + mbedtls_md_init( &ctx ); + mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 ); - // Generate data HMAC - mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) ); - mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data - mbedtls_md_hmac_update( &ctx, cipher + HMAC_POS_TAG, 0x20 ); // Tag HMAC - mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons + // Generate data HMAC + mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) ); + mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data + mbedtls_md_hmac_update( &ctx, cipher + HMAC_POS_TAG, 0x20 ); // Tag HMAC + mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons - mbedtls_md_hmac_finish( &ctx, cipher + HMAC_POS_DATA ); + mbedtls_md_hmac_finish( &ctx, cipher + HMAC_POS_DATA ); - // HMAC cleanup - mbedtls_md_free( &ctx ); + // HMAC cleanup + mbedtls_md_free( &ctx ); - // Encrypt - nfc3d_amiibo_cipher(&dataKeys, plain, cipher); + // Encrypt + nfc3d_amiibo_cipher(&dataKeys, plain, cipher); - // Convert back to hardware - nfc3d_amiibo_internal_to_tag(cipher, tag); + // Convert back to hardware + nfc3d_amiibo_internal_to_tag(cipher, tag); } bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) { - FILE * f = fopen(path, "rb"); - if (!f) { - return false; - } + FILE * f = fopen(path, "rb"); + if (!f) { + return false; + } - if (!fread(amiiboKeys, sizeof(*amiiboKeys), 1, f)) { - fclose(f); - return false; - } - fclose(f); + if (!fread(amiiboKeys, sizeof(*amiiboKeys), 1, f)) { + fclose(f); + return false; + } + fclose(f); - if ( - (amiiboKeys->data.magicBytesSize > 16) || - (amiiboKeys->tag.magicBytesSize > 16) - ) { - return false; - } + if ( + (amiiboKeys->data.magicBytesSize > 16) || + (amiiboKeys->tag.magicBytesSize > 16) + ) { + return false; + } - return true; + return true; } void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst) { - //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29); - //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4); + //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29); + //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4); - /* increment write counters */ - //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); - //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); + /* increment write counters */ + //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); + //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); - uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; - uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; + uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; + uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; - num_to_bytes(ami_nb_wr, 2, dst + 0x29); - num_to_bytes(cfg_nb_wr, 2, dst + 0xB4); + num_to_bytes(ami_nb_wr, 2, dst + 0x29); + num_to_bytes(cfg_nb_wr, 2, dst + 0xB4); - /* copy flags */ - dst[0x2C] = src[0x2C]; - /* copy programID */ - memcpy(dst + 0xAC, src + 0xAC, 8); - /* copy AppID */ - memcpy(dst + 0xB6, src + 0xB6, 4); - /* copy AppData */ - memcpy(dst + 0xDC, src + 0xDC, 216); + /* copy flags */ + dst[0x2C] = src[0x2C]; + /* copy programID */ + memcpy(dst + 0xAC, src + 0xAC, 8); + /* copy AppID */ + memcpy(dst + 0xB6, src + 0xB6, 4); + /* copy AppData */ + memcpy(dst + 0xDC, src + 0xDC, 216); } diff --git a/client/amiitool/amiibo.h b/client/amiitool/amiibo.h index 3c7dccc70..5b45e9b98 100644 --- a/client/amiitool/amiibo.h +++ b/client/amiitool/amiibo.h @@ -19,8 +19,8 @@ #pragma pack(1) typedef struct { - nfc3d_keygen_masterkeys data; - nfc3d_keygen_masterkeys tag; + nfc3d_keygen_masterkeys data; + nfc3d_keygen_masterkeys tag; } nfc3d_amiibo_keys; #pragma pack() diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c index 163e6529c..2643ffa36 100644 --- a/client/amiitool/amiitool.c +++ b/client/amiitool/amiitool.c @@ -15,161 +15,161 @@ static char * self; void amiitool_usage() { - fprintf(stderr, - "amiitool build %i (commit %s-%08x)\n" - "by Marcos Del Sol Vives \n" - "\n" - "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" - " -e encrypt and sign amiibo\n" - " -d decrypt and test amiibo\n" - " -c decrypt, copy AppData and encrypt amiibo\n" - " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n" - " -i input file. If not specified, stdin will be used.\n" - " -s input save file, save from this file will replace input file ones.\n" - " -o output file. If not specified, stdout will be used.\n" - " -l decrypt files with invalid signatures.\n", - , self - ); + fprintf(stderr, + "amiitool build %i (commit %s-%08x)\n" + "by Marcos Del Sol Vives \n" + "\n" + "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" + " -e encrypt and sign amiibo\n" + " -d decrypt and test amiibo\n" + " -c decrypt, copy AppData and encrypt amiibo\n" + " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n" + " -i input file. If not specified, stdin will be used.\n" + " -s input save file, save from this file will replace input file ones.\n" + " -o output file. If not specified, stdout will be used.\n" + " -l decrypt files with invalid signatures.\n", + , self + ); } static bool LoadAmiikey(nfc3d_amiibo_keys keys, char* keyfile) { - if (!nfc3d_amiibo_load_keys(&keys, keyfile)) { - PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile); - return false; - } - return true; + if (!nfc3d_amiibo_load_keys(&keys, keyfile)) { + PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile); + return false; + } + return true; } int main(int argc, char ** argv) { - self = argv[0]; + self = argv[0]; - char * infile = NULL; - char * savefile = NULL; - char * outfile = NULL; - char * keyfile = NULL; - char op = '\0'; - bool lenient = false; + char * infile = NULL; + char * savefile = NULL; + char * outfile = NULL; + char * keyfile = NULL; + char op = '\0'; + bool lenient = false; - char c; - while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) { - switch (c) { - case 'e': - case 'd': - case 'c': - op = c; - break; - case 'i': - infile = optarg; - break; - case 's': - savefile = optarg; - break; - case 'o': - outfile = optarg; - break; - case 'l': - lenient = true; - break; - default: - amiitool_usage(); - return 2; - } - } + char c; + while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) { + switch (c) { + case 'e': + case 'd': + case 'c': + op = c; + break; + case 'i': + infile = optarg; + break; + case 's': + savefile = optarg; + break; + case 'o': + outfile = optarg; + break; + case 'l': + lenient = true; + break; + default: + amiitool_usage(); + return 2; + } + } - if (op == '\0' || keyfile == NULL) { - amiitool_usage(); - return 1; - } + if (op == '\0' || keyfile == NULL) { + amiitool_usage(); + return 1; + } - nfc3d_amiibo_keys amiiboKeys; + nfc3d_amiibo_keys amiiboKeys; - uint8_t original[NTAG215_SIZE]; - uint8_t modified[NFC3D_AMIIBO_SIZE]; + uint8_t original[NTAG215_SIZE]; + uint8_t modified[NFC3D_AMIIBO_SIZE]; - FILE * f = stdin; - if (infile) { - f = fopen(infile, "rb"); - if (!f) { - fprintf(stderr, "Could not open input file\n"); - return 3; - } - } - size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); - if (readPages < NFC3D_AMIIBO_SIZE / 4) { - fprintf(stderr, "Could not read from input\n"); - fclose(f); - return 3; - } - fclose(f); + FILE * f = stdin; + if (infile) { + f = fopen(infile, "rb"); + if (!f) { + fprintf(stderr, "Could not open input file\n"); + return 3; + } + } + size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + if (readPages < NFC3D_AMIIBO_SIZE / 4) { + fprintf(stderr, "Could not read from input\n"); + fclose(f); + return 3; + } + fclose(f); - if (op == 'e') { - nfc3d_amiibo_pack(&amiiboKeys, original, modified); - } else if (op == 'd') { - if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) { - fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); - if (!lenient) { - return 6; - } - } - } else { /* copy */ - uint8_t plain_base[NFC3D_AMIIBO_SIZE]; - uint8_t plain_save[NFC3D_AMIIBO_SIZE]; + if (op == 'e') { + nfc3d_amiibo_pack(&amiiboKeys, original, modified); + } else if (op == 'd') { + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + } else { /* copy */ + uint8_t plain_base[NFC3D_AMIIBO_SIZE]; + uint8_t plain_save[NFC3D_AMIIBO_SIZE]; - if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) { - fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); - if (!lenient) { - return 6; - } - } - if (savefile) { - f = fopen(savefile, "rb"); - if (!f) { - fprintf(stderr, "Could not open save file\n"); - return 3; - } - } - size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); - if (readPages < NFC3D_AMIIBO_SIZE / 4) { - fprintf(stderr, "Could not read from save\n"); - fclose(f); - return 3; - } - fclose(f); + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + if (savefile) { + f = fopen(savefile, "rb"); + if (!f) { + fprintf(stderr, "Could not open save file\n"); + return 3; + } + } + size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + if (readPages < NFC3D_AMIIBO_SIZE / 4) { + fprintf(stderr, "Could not read from save\n"); + fclose(f); + return 3; + } + fclose(f); - if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) { - fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); - if (!lenient) { - return 6; - } - } + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } - nfc3d_amiibo_copy_app_data(plain_save, plain_base); - nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified); - } + nfc3d_amiibo_copy_app_data(plain_save, plain_base); + nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified); + } - f = stdout; - if (outfile) { - f = fopen(outfile, "wb"); - if (!f) { - fprintf(stderr, "Could not open output file\n"); - return 4; - } - } - if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) { - fprintf(stderr, "Could not write to output\n"); - fclose(f); - return 4; - } - if (readPages > NFC3D_AMIIBO_SIZE / 4) { - if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) { - fprintf(stderr, "Could not write to output:\n"); - fclose(f); - return 4; - } - } - fclose(f); - return 0; + f = stdout; + if (outfile) { + f = fopen(outfile, "wb"); + if (!f) { + fprintf(stderr, "Could not open output file\n"); + return 4; + } + } + if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) { + fprintf(stderr, "Could not write to output\n"); + fclose(f); + return 4; + } + if (readPages > NFC3D_AMIIBO_SIZE / 4) { + if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) { + fprintf(stderr, "Could not write to output:\n"); + fclose(f); + return 4; + } + } + fclose(f); + return 0; } diff --git a/client/amiitool/drbg.c b/client/amiitool/drbg.c index d56366077..aaf0acef5 100644 --- a/client/amiitool/drbg.c +++ b/client/amiitool/drbg.c @@ -11,68 +11,68 @@ #include void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize) { - assert(ctx != NULL); - assert(hmacKey != NULL); - assert(seed != NULL); - assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE); + assert(ctx != NULL); + assert(hmacKey != NULL); + assert(seed != NULL); + assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE); - // Initialize primitives - ctx->used = false; - ctx->iteration = 0; - ctx->bufferSize = sizeof(ctx->iteration) + seedSize; + // Initialize primitives + ctx->used = false; + ctx->iteration = 0; + ctx->bufferSize = sizeof(ctx->iteration) + seedSize; - // The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start - memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize); + // The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start + memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize); - // Initialize underlying HMAC context - mbedtls_md_init(&ctx->hmacCtx); - mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); - mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize); + // Initialize underlying HMAC context + mbedtls_md_init(&ctx->hmacCtx); + mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); + mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize); } void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output) { - assert(ctx != NULL); - assert(output != NULL); + assert(ctx != NULL); + assert(output != NULL); - if (ctx->used) { - // If used at least once, reinitialize the HMAC - mbedtls_md_hmac_reset(&ctx->hmacCtx); - } else { - ctx->used = true; - } + if (ctx->used) { + // If used at least once, reinitialize the HMAC + mbedtls_md_hmac_reset(&ctx->hmacCtx); + } else { + ctx->used = true; + } - // Store counter in big endian, and increment it - ctx->buffer[0] = ctx->iteration >> 8; - ctx->buffer[1] = ctx->iteration >> 0; - ctx->iteration++; + // Store counter in big endian, and increment it + ctx->buffer[0] = ctx->iteration >> 8; + ctx->buffer[1] = ctx->iteration >> 0; + ctx->iteration++; - // Do HMAC magic - mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize); - mbedtls_md_hmac_finish(&ctx->hmacCtx, output); + // Do HMAC magic + mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize); + mbedtls_md_hmac_finish(&ctx->hmacCtx, output); } void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx) { - assert(ctx != NULL); - mbedtls_md_free(&ctx->hmacCtx); + assert(ctx != NULL); + mbedtls_md_free(&ctx->hmacCtx); } void nfc3d_drbg_generate_bytes(const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize, uint8_t * output, size_t outputSize) { - uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE]; + uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE]; - nfc3d_drbg_ctx rngCtx; - nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize); + nfc3d_drbg_ctx rngCtx; + nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize); - while (outputSize > 0) { - if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) { - nfc3d_drbg_step(&rngCtx, temp); - memcpy(output, temp, outputSize); - break; - } + while (outputSize > 0) { + if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) { + nfc3d_drbg_step(&rngCtx, temp); + memcpy(output, temp, outputSize); + break; + } - nfc3d_drbg_step(&rngCtx, output); - output += NFC3D_DRBG_OUTPUT_SIZE; - outputSize -= NFC3D_DRBG_OUTPUT_SIZE; - } + nfc3d_drbg_step(&rngCtx, output); + output += NFC3D_DRBG_OUTPUT_SIZE; + outputSize -= NFC3D_DRBG_OUTPUT_SIZE; + } - nfc3d_drbg_cleanup(&rngCtx); + nfc3d_drbg_cleanup(&rngCtx); } diff --git a/client/amiitool/drbg.h b/client/amiitool/drbg.h index 0e93abfc0..7b5bddc86 100644 --- a/client/amiitool/drbg.h +++ b/client/amiitool/drbg.h @@ -12,16 +12,16 @@ #include #include "mbedtls/md.h" -#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */ -#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */ +#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */ +#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */ typedef struct { - mbedtls_md_context_t hmacCtx; - bool used; - uint16_t iteration; + mbedtls_md_context_t hmacCtx; + bool used; + uint16_t iteration; - uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE]; - size_t bufferSize; + uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE]; + size_t bufferSize; } nfc3d_drbg_ctx; void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize); diff --git a/client/amiitool/keygen.c b/client/amiitool/keygen.c index c82e3abee..1c0a91344 100644 --- a/client/amiitool/keygen.c +++ b/client/amiitool/keygen.c @@ -11,43 +11,43 @@ #include void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, uint8_t * output, size_t * outputSize) { - assert(baseKeys != NULL); - assert(baseSeed != NULL); - assert(output != NULL); - assert(outputSize != NULL); + assert(baseKeys != NULL); + assert(baseSeed != NULL); + assert(output != NULL); + assert(outputSize != NULL); - uint8_t * start = output; + uint8_t * start = output; - // 1: Copy whole type string - output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); + // 1: Copy whole type string + output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); - // 2: Append (16 - magicBytesSize) from the input seed - size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; - memcpy(output, baseSeed, leadingSeedBytes); - output += leadingSeedBytes; + // 2: Append (16 - magicBytesSize) from the input seed + size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; + memcpy(output, baseSeed, leadingSeedBytes); + output += leadingSeedBytes; - // 3: Append all bytes from magicBytes - memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize); - output += baseKeys->magicBytesSize; + // 3: Append all bytes from magicBytes + memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize); + output += baseKeys->magicBytesSize; - // 4: Append bytes 0x10-0x1F from input seed - memcpy(output, baseSeed + 0x10, 16); - output += 16; + // 4: Append bytes 0x10-0x1F from input seed + memcpy(output, baseSeed + 0x10, 16); + output += 16; - // 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them - unsigned int i; - for (i = 0; i < 32; i++) { - output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i]; - } - output += 32; + // 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them + unsigned int i; + for (i = 0; i < 32; i++) { + output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i]; + } + output += 32; - *outputSize = output - start; + *outputSize = output - start; } void nfc3d_keygen(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, nfc3d_keygen_derivedkeys * derivedKeys) { - uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE]; - size_t preparedSeedSize; + uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE]; + size_t preparedSeedSize; - nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize); - nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys)); + nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize); + nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys)); } diff --git a/client/amiitool/keygen.h b/client/amiitool/keygen.h index 35595e3ef..5e371074e 100644 --- a/client/amiitool/keygen.h +++ b/client/amiitool/keygen.h @@ -14,18 +14,18 @@ #pragma pack(1) typedef struct { - uint8_t hmacKey[16]; - char typeString[14]; - uint8_t rfu; - uint8_t magicBytesSize; - uint8_t magicBytes[16]; - uint8_t xorPad[32]; + uint8_t hmacKey[16]; + char typeString[14]; + uint8_t rfu; + uint8_t magicBytesSize; + uint8_t magicBytes[16]; + uint8_t xorPad[32]; } nfc3d_keygen_masterkeys; typedef struct { - const uint8_t aesKey[16]; - const uint8_t aesIV[16]; - const uint8_t hmacKey[16]; + const uint8_t aesKey[16]; + const uint8_t aesIV[16]; + const uint8_t hmacKey[16]; } nfc3d_keygen_derivedkeys; #pragma pack() diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index 7e3461b37..63e847be1 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -168,9 +168,9 @@ void dbg_printf(const char *fmt, ...) #include "getopt.h" -/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ -/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ -/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ +/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* * Copyright (c) 2002 Todd C. Miller @@ -231,33 +231,33 @@ void dbg_printf(const char *fmt, ...) #include -#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ #ifdef REPLACE_GETOPT -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ #endif -#define PRINT_ERROR ((opterr) && (*options != ':')) +#define PRINT_ERROR ((opterr) && (*options != ':')) -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 -#define EMSG "" +#define EMSG "" static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); + const struct option *, int *, int); static int parse_long_options(char * const *, const char *, - const struct option *, int *, int); + const struct option *, int *, int); static int gcd(int, int); static void permute_args(int, int, int, char * const *); @@ -296,22 +296,22 @@ char opterrmsg[MAX_OPTER_MSG_SIZE]; /* buffer for the last error message */ static void warnx(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); + va_list ap; + va_start(ap, fmt); /* Make sure opterrmsg is always zero-terminated despite the _vsnprintf() implementation specifics and manually suppress the warning. */ memset(opterrmsg, 0, sizeof opterrmsg); - if (fmt != NULL) + if (fmt != NULL) #ifdef __STDC_WANT_SECURE_LIB__ _vsnprintf_s(opterrmsg, MAX_OPTER_MSG_SIZE, sizeof(opterrmsg) - 1, fmt, ap); #else _vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap); #endif - va_end(ap); + va_end(ap); - fprintf(stderr, "%s\n", opterrmsg); + fprintf(stderr, "%s\n", opterrmsg); } #else @@ -325,16 +325,16 @@ static void warnx(const char *fmt, ...) static int gcd(int a, int b) { - int c; + int c; - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } - return (b); + return (b); } /* @@ -344,179 +344,179 @@ gcd(int a, int b) */ static void permute_args(int panonopt_start, int panonopt_end, int opt_end, - char * const *nargv) + char * const *nargv) { - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **) nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } - } + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } } /* * parse_long_options -- - * Parse long options in argc/argv argument vector. + * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */ static int parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int short_too) + const struct option *long_options, int *idx, int short_too) { - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; - current_argv = place; - match = -1; + current_argv = place; + match = -1; - optind++; + optind++; - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - break; - } - /* - * If this is a known short option, don't allow - * a partial match of a single character. - */ - if (short_too && current_argv_len == 1) - continue; + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return (BADARG); - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, current_argv); - optopt = 0; - return (BADCH); - } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); - } else - return (long_options[match].val); + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); } /* * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. + * Parse argc/argv argument vector. Called by user level routines. */ static int getopt_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int flags) + const struct option *long_options, int *idx, int flags) { - char *oli; /* option letter list index */ - int optchar, short_too; - static int posixly_correct = -1; + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; #ifdef __STDC_WANT_SECURE_LIB__ char* buffer = NULL; size_t buffer_size = 0; errno_t err = 0; #endif - if (options == NULL) - return (-1); + if (options == NULL) + return (-1); - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - */ + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ #ifdef __STDC_WANT_SECURE_LIB__ if (posixly_correct == -1) { @@ -530,183 +530,183 @@ getopt_internal(int nargc, char * const *nargv, const char *options, if (posixly_correct == -1) posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); #endif - if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - else if (*options == '-') - flags |= FLAG_ALLARGS; - if (*options == '+' || *options == '-') - options++; + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; - /* - * If we have "-" do nothing, if "--" we are done. - */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - } + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } - /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() - */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; - if (*place == '-') - place++; /* --foo long option */ - else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ - optchar = parse_long_options(nargv, options, long_options, - idx, short_too); - if (optchar != -1) { - place = EMSG; - return (optchar); - } - } + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; - if (PRINT_ERROR) - warnx(illoptchar, optchar); - optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else /* white space */ - place = nargv[optind]; - optchar = parse_long_options(nargv, options, long_options, - idx, 0); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); } #ifdef REPLACE_GETOPT /* * getopt -- - * Parse argc/argv argument vector. + * Parse argc/argv argument vector. * * [eventually this will replace the BSD getopt] */ @@ -714,42 +714,42 @@ int getopt(int nargc, char * const *nargv, const char *options) { - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } #endif /* REPLACE_GETOPT */ /* * getopt_long -- - * Parse argc/argv argument vector. + * Parse argc/argv argument vector. */ int getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); } /* * getopt_long_only -- - * Parse argc/argv argument vector. + * Parse argc/argv argument vector. */ int getopt_long_only(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE|FLAG_LONGONLY)); + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); } /******************************************************************************* * This file is part of the argtable3 library. @@ -2573,29 +2573,29 @@ struct arg_rem *arg_rem(const char *datatype, const char *glossary) #ifndef _TREX_H_ #define _TREX_H_ /*************************************************************** - T-Rex a tiny regular expression library + T-Rex a tiny regular expression library - Copyright (C) 2003-2006 Alberto Demichelis + Copyright (C) 2003-2006 Alberto Demichelis - This software is provided 'as-is', without any express - or implied warranty. In no event will the authors be held - liable for any damages arising from the use of this software. + This software is provided 'as-is', without any express + or implied warranty. In no event will the authors be held + liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for - any purpose, including commercial applications, and to alter - it and redistribute it freely, subject to the following restrictions: + Permission is granted to anyone to use this software for + any purpose, including commercial applications, and to alter + it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but - is not required. + 1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but + is not required. - 2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software. + 2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any - source distribution. + 3. This notice may not be removed or altered from any + source distribution. ****************************************************************/ @@ -2630,8 +2630,8 @@ typedef unsigned int TRexBool; typedef struct TRex TRex; typedef struct { - const TRexChar *begin; - int len; + const TRexChar *begin; + int len; } TRexMatch; TREX_API TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags); @@ -2899,26 +2899,26 @@ struct arg_rex * arg_rexn(const char * shortopts, static const TRexChar *g_nnames[] = { - _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), - _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), - _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), - _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") }; #endif -#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} -#define OP_OR (MAX_CHAR+2) -#define OP_EXPR (MAX_CHAR+3) //parentesis () -#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) -#define OP_DOT (MAX_CHAR+5) -#define OP_CLASS (MAX_CHAR+6) -#define OP_CCLASS (MAX_CHAR+7) -#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ -#define OP_RANGE (MAX_CHAR+9) -#define OP_CHAR (MAX_CHAR+10) -#define OP_EOL (MAX_CHAR+11) -#define OP_BOL (MAX_CHAR+12) -#define OP_WB (MAX_CHAR+13) +#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} +#define OP_OR (MAX_CHAR+2) +#define OP_EXPR (MAX_CHAR+3) //parentesis () +#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) +#define OP_DOT (MAX_CHAR+5) +#define OP_CLASS (MAX_CHAR+6) +#define OP_CCLASS (MAX_CHAR+7) +#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ +#define OP_RANGE (MAX_CHAR+9) +#define OP_CHAR (MAX_CHAR+10) +#define OP_EOL (MAX_CHAR+11) +#define OP_BOL (MAX_CHAR+12) +#define OP_WB (MAX_CHAR+13) #define TREX_SYMBOL_ANY_CHAR ('.') #define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') @@ -2933,610 +2933,610 @@ static const TRexChar *g_nnames[] = typedef int TRexNodeType; typedef struct tagTRexNode{ - TRexNodeType type; - int left; - int right; - int next; + TRexNodeType type; + int left; + int right; + int next; }TRexNode; struct TRex{ - const TRexChar *_eol; - const TRexChar *_bol; - const TRexChar *_p; - int _first; - int _op; - TRexNode *_nodes; - int _nallocated; - int _nsize; - int _nsubexpr; - TRexMatch *_matches; - int _currsubexp; - void *_jmpbuf; - const TRexChar **_error; - int _flags; + const TRexChar *_eol; + const TRexChar *_bol; + const TRexChar *_p; + int _first; + int _op; + TRexNode *_nodes; + int _nallocated; + int _nsize; + int _nsubexpr; + TRexMatch *_matches; + int _currsubexp; + void *_jmpbuf; + const TRexChar **_error; + int _flags; }; static int trex_list(TRex *exp); static int trex_newnode(TRex *exp, TRexNodeType type) { - TRexNode n; - int newid; - n.type = type; - n.next = n.right = n.left = -1; - if(type == OP_EXPR) - n.right = exp->_nsubexpr++; - if(exp->_nallocated < (exp->_nsize + 1)) { - exp->_nallocated *= 2; - exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); - } - exp->_nodes[exp->_nsize++] = n; - newid = exp->_nsize - 1; - return (int)newid; + TRexNode n; + int newid; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + exp->_nallocated *= 2; + exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + newid = exp->_nsize - 1; + return (int)newid; } static void trex_error(TRex *exp,const TRexChar *error) { - if(exp->_error) *exp->_error = error; - longjmp(*((jmp_buf*)exp->_jmpbuf),-1); + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); } static void trex_expect(TRex *exp, int n){ - if((*exp->_p) != n) - trex_error(exp, _SC("expected paren")); - exp->_p++; + if((*exp->_p) != n) + trex_error(exp, _SC("expected paren")); + exp->_p++; } static TRexChar trex_escapechar(TRex *exp) { - if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ - exp->_p++; - switch(*exp->_p) { - case 'v': exp->_p++; return '\v'; - case 'n': exp->_p++; return '\n'; - case 't': exp->_p++; return '\t'; - case 'r': exp->_p++; return '\r'; - case 'f': exp->_p++; return '\f'; - default: return (*exp->_p++); - } - } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); - return (*exp->_p++); + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); + return (*exp->_p++); } static int trex_charclass(TRex *exp,int classid) { - int n = trex_newnode(exp,OP_CCLASS); - exp->_nodes[n].left = classid; - return n; + int n = trex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; } static int trex_charnode(TRex *exp,TRexBool isclass) { - TRexChar t; - if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { - exp->_p++; - switch(*exp->_p) { - case 'n': exp->_p++; return trex_newnode(exp,'\n'); - case 't': exp->_p++; return trex_newnode(exp,'\t'); - case 'r': exp->_p++; return trex_newnode(exp,'\r'); - case 'f': exp->_p++; return trex_newnode(exp,'\f'); - case 'v': exp->_p++; return trex_newnode(exp,'\v'); - case 'a': case 'A': case 'w': case 'W': case 's': case 'S': - case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': - case 'p': case 'P': case 'l': case 'u': - { - t = *exp->_p; exp->_p++; - return trex_charclass(exp,t); - } - case 'b': - case 'B': - if(!isclass) { - int node = trex_newnode(exp,OP_WB); - exp->_nodes[node].left = *exp->_p; - exp->_p++; - return node; - } //else default - default: - t = *exp->_p; exp->_p++; - return trex_newnode(exp,t); - } - } - else if(!scisprint(*exp->_p)) { + TRexChar t; + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return trex_newnode(exp,'\n'); + case 't': exp->_p++; return trex_newnode(exp,'\t'); + case 'r': exp->_p++; return trex_newnode(exp,'\r'); + case 'f': exp->_p++; return trex_newnode(exp,'\f'); + case 'v': exp->_p++; return trex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + t = *exp->_p; exp->_p++; + return trex_charclass(exp,t); + } + case 'b': + case 'B': + if(!isclass) { + int node = trex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + default: + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); + } + } + else if(!scisprint(*exp->_p)) { - trex_error(exp,_SC("letter expected")); - } - t = *exp->_p; exp->_p++; - return trex_newnode(exp,t); + trex_error(exp,_SC("letter expected")); + } + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); } static int trex_class(TRex *exp) { - int ret = -1; - int first = -1,chain; - if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ - ret = trex_newnode(exp,OP_NCLASS); - exp->_p++; - }else ret = trex_newnode(exp,OP_CLASS); + int ret = -1; + int first = -1,chain; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ + ret = trex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = trex_newnode(exp,OP_CLASS); - if(*exp->_p == ']') trex_error(exp,_SC("empty class")); - chain = ret; - while(*exp->_p != ']' && exp->_p != exp->_eol) { - if(*exp->_p == '-' && first != -1){ - int r,t; - if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); - r = trex_newnode(exp,OP_RANGE); - if(first>*exp->_p) trex_error(exp,_SC("invalid range")); - if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); - exp->_nodes[r].left = exp->_nodes[first].type; - t = trex_escapechar(exp); - exp->_nodes[r].right = t; + if(*exp->_p == ']') trex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + int r,t; + if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); + r = trex_newnode(exp,OP_RANGE); + if(first>*exp->_p) trex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + t = trex_escapechar(exp); + exp->_nodes[r].right = t; exp->_nodes[chain].next = r; - chain = r; - first = -1; - } - else{ - if(first!=-1){ - int c = first; - exp->_nodes[chain].next = c; - chain = c; - first = trex_charnode(exp,TRex_True); - } - else{ - first = trex_charnode(exp,TRex_True); - } - } - } - if(first!=-1){ - int c = first; - exp->_nodes[chain].next = c; - chain = c; - first = -1; - } - /* hack? */ - exp->_nodes[ret].left = exp->_nodes[ret].next; - exp->_nodes[ret].next = -1; - return ret; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = trex_charnode(exp,TRex_True); + } + else{ + first = trex_charnode(exp,TRex_True); + } + } + } + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; } static int trex_parsenumber(TRex *exp) { - int ret = *exp->_p-'0'; - int positions = 10; - exp->_p++; - while(isdigit(*exp->_p)) { - ret = ret*10+(*exp->_p++-'0'); - if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); - positions *= 10; - }; - return ret; + int ret = *exp->_p-'0'; + int positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; } static int trex_element(TRex *exp) { - int ret = -1; - switch(*exp->_p) - { - case '(': { - int expr,newn; - exp->_p++; + int ret = -1; + switch(*exp->_p) + { + case '(': { + int expr,newn; + exp->_p++; - if(*exp->_p =='?') { - exp->_p++; - trex_expect(exp,':'); - expr = trex_newnode(exp,OP_NOCAPEXPR); - } - else - expr = trex_newnode(exp,OP_EXPR); - newn = trex_list(exp); - exp->_nodes[expr].left = newn; - ret = expr; - trex_expect(exp,')'); - } - break; - case '[': - exp->_p++; - ret = trex_class(exp); - trex_expect(exp,']'); - break; - case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; - case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; - default: - ret = trex_charnode(exp,TRex_False); - break; - } + if(*exp->_p =='?') { + exp->_p++; + trex_expect(exp,':'); + expr = trex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = trex_newnode(exp,OP_EXPR); + newn = trex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + trex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = trex_class(exp); + trex_expect(exp,']'); + break; + case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; + case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; + default: + ret = trex_charnode(exp,TRex_False); + break; + } - { - TRexBool isgreedy = TRex_False; - unsigned short p0 = 0, p1 = 0; - switch(*exp->_p){ - case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; - case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; - case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; - case '{': - exp->_p++; - if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); - p0 = (unsigned short)trex_parsenumber(exp); - /*******************************/ - switch(*exp->_p) { - case '}': - p1 = p0; exp->_p++; - break; - case ',': - exp->_p++; - p1 = 0xFFFF; - if(isdigit(*exp->_p)){ - p1 = (unsigned short)trex_parsenumber(exp); - } - trex_expect(exp,'}'); - break; - default: - trex_error(exp,_SC(", or } expected")); - } - /*******************************/ - isgreedy = TRex_True; - break; + { + TRexBool isgreedy = TRex_False; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; + case '{': + exp->_p++; + if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); + p0 = (unsigned short)trex_parsenumber(exp); + /*******************************/ + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit(*exp->_p)){ + p1 = (unsigned short)trex_parsenumber(exp); + } + trex_expect(exp,'}'); + break; + default: + trex_error(exp,_SC(", or } expected")); + } + /*******************************/ + isgreedy = TRex_True; + break; - } - if(isgreedy) { - int nnode = trex_newnode(exp,OP_GREEDY); - exp->_nodes[nnode].left = ret; - exp->_nodes[nnode].right = ((p0)<<16)|p1; - ret = nnode; - } - } - if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { - int nnode = trex_element(exp); - exp->_nodes[ret].next = nnode; - } + } + if(isgreedy) { + int nnode = trex_newnode(exp,OP_GREEDY); + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } + } + if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + int nnode = trex_element(exp); + exp->_nodes[ret].next = nnode; + } - return ret; + return ret; } static int trex_list(TRex *exp) { - int ret=-1,e; - if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { - exp->_p++; - ret = trex_newnode(exp,OP_BOL); - } - e = trex_element(exp); - if(ret != -1) { - exp->_nodes[ret].next = e; - } - else ret = e; + int ret=-1,e; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = trex_newnode(exp,OP_BOL); + } + e = trex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; - if(*exp->_p == TREX_SYMBOL_BRANCH) { - int temp,tright; - exp->_p++; - temp = trex_newnode(exp,OP_OR); - exp->_nodes[temp].left = ret; - tright = trex_list(exp); - exp->_nodes[temp].right = tright; - ret = temp; - } - return ret; + if(*exp->_p == TREX_SYMBOL_BRANCH) { + int temp,tright; + exp->_p++; + temp = trex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + tright = trex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; } static TRexBool trex_matchcclass(int cclass,TRexChar c) { - switch(cclass) { - case 'a': return isalpha(c)?TRex_True:TRex_False; - case 'A': return !isalpha(c)?TRex_True:TRex_False; - case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; - case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; - case 's': return ISSPACE(c)?TRex_True:TRex_False; - case 'S': return !ISSPACE(c)?TRex_True:TRex_False; - case 'd': return isdigit(c)?TRex_True:TRex_False; - case 'D': return !isdigit(c)?TRex_True:TRex_False; - case 'x': return isxdigit(c)?TRex_True:TRex_False; - case 'X': return !isxdigit(c)?TRex_True:TRex_False; - case 'c': return iscntrl(c)?TRex_True:TRex_False; - case 'C': return !iscntrl(c)?TRex_True:TRex_False; - case 'p': return ispunct(c)?TRex_True:TRex_False; - case 'P': return !ispunct(c)?TRex_True:TRex_False; - case 'l': return islower(c)?TRex_True:TRex_False; - case 'u': return isupper(c)?TRex_True:TRex_False; - } - return TRex_False; /*cannot happen*/ + switch(cclass) { + case 'a': return isalpha(c)?TRex_True:TRex_False; + case 'A': return !isalpha(c)?TRex_True:TRex_False; + case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; + case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; + case 's': return ISSPACE(c)?TRex_True:TRex_False; + case 'S': return !ISSPACE(c)?TRex_True:TRex_False; + case 'd': return isdigit(c)?TRex_True:TRex_False; + case 'D': return !isdigit(c)?TRex_True:TRex_False; + case 'x': return isxdigit(c)?TRex_True:TRex_False; + case 'X': return !isxdigit(c)?TRex_True:TRex_False; + case 'c': return iscntrl(c)?TRex_True:TRex_False; + case 'C': return !iscntrl(c)?TRex_True:TRex_False; + case 'p': return ispunct(c)?TRex_True:TRex_False; + case 'P': return !ispunct(c)?TRex_True:TRex_False; + case 'l': return islower(c)?TRex_True:TRex_False; + case 'u': return isupper(c)?TRex_True:TRex_False; + } + return TRex_False; /*cannot happen*/ } static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c) { - do { - switch(node->type) { - case OP_RANGE: - if (exp->_flags & TREX_ICASE) - { - if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; - if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; - } - else - { - if(c >= node->left && c <= node->right) return TRex_True; - } - break; - case OP_CCLASS: - if(trex_matchcclass(node->left,c)) return TRex_True; - break; - default: - if (exp->_flags & TREX_ICASE) - { - if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; - } - else - { - if(c == node->type)return TRex_True; - } + do { + switch(node->type) { + case OP_RANGE: + if (exp->_flags & TREX_ICASE) + { + if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; + if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; + } + else + { + if(c >= node->left && c <= node->right) return TRex_True; + } + break; + case OP_CCLASS: + if(trex_matchcclass(node->left,c)) return TRex_True; + break; + default: + if (exp->_flags & TREX_ICASE) + { + if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; + } + else + { + if(c == node->type)return TRex_True; + } - } - } while((node->next != -1) && (node = &exp->_nodes[node->next])); - return TRex_False; + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return TRex_False; } static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next) { - TRexNodeType type = node->type; - switch(type) { - case OP_GREEDY: { - //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; - TRexNode *greedystop = NULL; - int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; - const TRexChar *s=str, *good = str; + TRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + TRexNode *greedystop = NULL; + int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const TRexChar *s=str, *good = str; - if(node->next != -1) { - greedystop = &exp->_nodes[node->next]; - } - else { - greedystop = next; - } + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } - while((nmaches == 0xFFFF || nmaches < p1)) { + while((nmaches == 0xFFFF || nmaches < p1)) { - const TRexChar *stop; - if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) - break; - nmaches++; - good=s; - if(greedystop) { - //checks that 0 matches satisfy the expression(if so skips) - //if not would always stop(for instance if is a '?') - if(greedystop->type != OP_GREEDY || - (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) - { - TRexNode *gnext = NULL; - if(greedystop->next != -1) { - gnext = &exp->_nodes[greedystop->next]; - }else if(next && next->next != -1){ - gnext = &exp->_nodes[next->next]; - } - stop = trex_matchnode(exp,greedystop,s,gnext); - if(stop) { - //if satisfied stop it - if(p0 == p1 && p0 == nmaches) break; - else if(nmaches >= p0 && p1 == 0xFFFF) break; - else if(nmaches >= p0 && nmaches <= p1) break; - } - } - } + const TRexChar *stop; + if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + TRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = trex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } - if(s >= exp->_eol) - break; - } - if(p0 == p1 && p0 == nmaches) return good; - else if(nmaches >= p0 && p1 == 0xFFFF) return good; - else if(nmaches >= p0 && nmaches <= p1) return good; - return NULL; - } - case OP_OR: { - const TRexChar *asd = str; - TRexNode *temp=&exp->_nodes[node->left]; - while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - asd = str; - temp = &exp->_nodes[node->right]; - while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - return NULL; - break; - } - case OP_EXPR: - case OP_NOCAPEXPR:{ - TRexNode *n = &exp->_nodes[node->left]; - const TRexChar *cur = str; - int capture = -1; - if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { - capture = exp->_currsubexp; - exp->_matches[capture].begin = cur; - exp->_currsubexp++; - } + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const TRexChar *asd = str; + TRexNode *temp=&exp->_nodes[node->left]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + TRexNode *n = &exp->_nodes[node->left]; + const TRexChar *cur = str; + int capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } - do { - TRexNode *subnext = NULL; - if(n->next != -1) { - subnext = &exp->_nodes[n->next]; - }else { - subnext = next; - } - if(!(cur = trex_matchnode(exp,n,cur,subnext))) { - if(capture != -1){ - exp->_matches[capture].begin = 0; - exp->_matches[capture].len = 0; - } - return NULL; - } - } while((n->next != -1) && (n = &exp->_nodes[n->next])); + do { + TRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = trex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); - if(capture != -1) - exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); - return cur; - } - case OP_WB: - if((str == exp->_bol && !ISSPACE(*str)) - || ((str == exp->_eol && !ISSPACE(*(str-1)))) - || ((!ISSPACE(*str) && ISSPACE(*(str+1)))) - || ((ISSPACE(*str) && !ISSPACE(*(str+1)))) ) { - return (node->left == 'b')?str:NULL; - } - return (node->left == 'b')?NULL:str; - case OP_BOL: - if(str == exp->_bol) return str; - return NULL; - case OP_EOL: - if(str == exp->_eol) return str; - return NULL; - case OP_DOT: - str++; - return str; - case OP_NCLASS: - case OP_CLASS: - if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { + if(capture != -1) + exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); + return cur; + } + case OP_WB: + if((str == exp->_bol && !ISSPACE(*str)) + || ((str == exp->_eol && !ISSPACE(*(str-1)))) + || ((!ISSPACE(*str) && ISSPACE(*(str+1)))) + || ((ISSPACE(*str) && !ISSPACE(*(str+1)))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT: + str++; + return str; + case OP_NCLASS: + case OP_CLASS: + if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { str++; - return str; - } - return NULL; - case OP_CCLASS: - if(trex_matchcclass(node->left,*str)) { + return str; + } + return NULL; + case OP_CCLASS: + if(trex_matchcclass(node->left,*str)) { str++; - return str; - } - return NULL; - default: /* char */ - if (exp->_flags & TREX_ICASE) - { - if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL; - } - else - { - if (*str != node->type) return NULL; - } - str++; - return str; - } - return NULL; + return str; + } + return NULL; + default: /* char */ + if (exp->_flags & TREX_ICASE) + { + if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL; + } + else + { + if (*str != node->type) return NULL; + } + str++; + return str; + } + return NULL; } /* public api */ TRex *trex_compile(const TRexChar *pattern,const TRexChar **error,int flags) { - TRex *exp = (TRex *)malloc(sizeof(TRex)); - exp->_eol = exp->_bol = NULL; - exp->_p = pattern; - exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); - exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); - exp->_nsize = 0; - exp->_matches = 0; - exp->_nsubexpr = 0; - exp->_first = trex_newnode(exp,OP_EXPR); - exp->_error = error; - exp->_jmpbuf = malloc(sizeof(jmp_buf)); - exp->_flags = flags; - if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { - int res = trex_list(exp); - exp->_nodes[exp->_first].left = res; - if(*exp->_p!='\0') - trex_error(exp,_SC("unexpected character")); + TRex *exp = (TRex *)malloc(sizeof(TRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); + exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = trex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = malloc(sizeof(jmp_buf)); + exp->_flags = flags; + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + int res = trex_list(exp); + exp->_nodes[exp->_first].left = res; + if(*exp->_p!='\0') + trex_error(exp,_SC("unexpected character")); #ifdef _DEBUG - { - int nsize,i; - TRexNode *t; - nsize = exp->_nsize; - t = &exp->_nodes[0]; - scprintf(_SC("\n")); - for(i = 0;i < nsize; i++) { - if(exp->_nodes[i].type>MAX_CHAR) - scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); - else - scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); - scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); - } - scprintf(_SC("\n")); - } + { + int nsize,i; + TRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } #endif - exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); - memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); - } - else{ - trex_free(exp); - return NULL; - } - return exp; + exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); + } + else{ + trex_free(exp); + return NULL; + } + return exp; } void trex_free(TRex *exp) { - if(exp) { - if(exp->_nodes) free(exp->_nodes); - if(exp->_jmpbuf) free(exp->_jmpbuf); - if(exp->_matches) free(exp->_matches); - free(exp); - } + if(exp) { + if(exp->_nodes) free(exp->_nodes); + if(exp->_jmpbuf) free(exp->_jmpbuf); + if(exp->_matches) free(exp->_matches); + free(exp); + } } TRexBool trex_match(TRex* exp,const TRexChar* text) { - const TRexChar* res = NULL; - exp->_bol = text; - exp->_eol = text + scstrlen(text); - exp->_currsubexp = 0; - res = trex_matchnode(exp,exp->_nodes,text,NULL); - if(res == NULL || res != exp->_eol) - return TRex_False; - return TRex_True; + const TRexChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = trex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return TRex_False; + return TRex_True; } TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) { - const TRexChar *cur = NULL; - int node = exp->_first; - if(text_begin >= text_end) return TRex_False; - exp->_bol = text_begin; - exp->_eol = text_end; - do { - cur = text_begin; - while(node != -1) { - exp->_currsubexp = 0; - cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); - if(!cur) - break; - node = exp->_nodes[node].next; - } - text_begin++; - } while(cur == NULL && text_begin != text_end); + const TRexChar *cur = NULL; + int node = exp->_first; + if(text_begin >= text_end) return TRex_False; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + text_begin++; + } while(cur == NULL && text_begin != text_end); - if(cur == NULL) - return TRex_False; + if(cur == NULL) + return TRex_False; - --text_begin; + --text_begin; - if(out_begin) *out_begin = text_begin; - if(out_end) *out_end = cur; - return TRex_True; + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return TRex_True; } TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) { - return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); + return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); } int trex_getsubexpcount(TRex* exp) { - return exp->_nsubexpr; + return exp->_nsubexpr; } TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp) { - if( n<0 || n >= exp->_nsubexpr) return TRex_False; - *subexp = exp->_matches[n]; - return TRex_True; + if( n<0 || n >= exp->_nsubexpr) return TRex_False; + *subexp = exp->_matches[n]; + return TRex_True; } /******************************************************************************* * This file is part of the argtable3 library. diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c index f1f2e3b1e..e0c853d23 100644 --- a/client/cliparser/cliparser.c +++ b/client/cliparser/cliparser.c @@ -20,186 +20,186 @@ char *programHelp = NULL; char buf[500] = {0}; int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) { - argtable = NULL; - argtableLen = 0; - programName = vprogramName; - programHint = vprogramHint; - programHelp = vprogramHelp; - memset(buf, 0x00, 500); + argtable = NULL; + argtableLen = 0; + programName = vprogramName; + programHint = vprogramHint; + programHelp = vprogramHelp; + memset(buf, 0x00, 500); - return 0; + return 0; } int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { - int nerrors; + int nerrors; - argtable = vargtable; - argtableLen = vargtableLen; + argtable = vargtable; + argtableLen = vargtableLen; - /* verify the argtable[] entries were allocated sucessfully */ - if (arg_nullcheck(argtable) != 0) { - /* NULL entries were detected, some allocations must have failed */ - printf("ERROR: Insufficient memory\n"); - return 2; - } - /* Parse the command line as defined by argtable[] */ - nerrors = arg_parse(argc, argv, argtable); + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) { + /* NULL entries were detected, some allocations must have failed */ + printf("ERROR: Insufficient memory\n"); + return 2; + } + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc, argv, argtable); - /* special case: '--help' takes precedence over error reporting */ - if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record - printf("Usage: %s", programName); - arg_print_syntaxv(stdout, argtable, "\n"); - if (programHint) - printf("%s\n\n", programHint); - arg_print_glossary(stdout, argtable, " %-20s %s\n"); - printf("\n"); - if (programHelp) - printf("%s \n", programHelp); + /* special case: '--help' takes precedence over error reporting */ + if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record + printf("Usage: %s", programName); + arg_print_syntaxv(stdout, argtable, "\n"); + if (programHint) + printf("%s\n\n", programHint); + arg_print_glossary(stdout, argtable, " %-20s %s\n"); + printf("\n"); + if (programHelp) + printf("%s \n", programHelp); - return 1; - } + return 1; + } - /* If the parser returned any errors then display them and exit */ - if (nerrors > 0) { - /* Display the error details contained in the arg_end struct.*/ - arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); - printf("Try '%s --help' for more information.\n", programName); + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); + printf("Try '%s --help' for more information.\n", programName); - return 3; - } + return 3; + } - return 0; + return 0; } enum ParserState { - PS_FIRST, - PS_ARGUMENT, - PS_OPTION, + PS_FIRST, + PS_ARGUMENT, + PS_OPTION, }; #define isSpace(c)(c == ' ' || c == '\t') int CLIParserParseString(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { - return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false); + return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false); } int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) { - int argc = 0; - char *argv[200] = {NULL}; + int argc = 0; + char *argv[200] = {NULL}; - int len = strlen(str); - char *bufptr = buf; - char *spaceptr = NULL; - enum ParserState state = PS_FIRST; + int len = strlen(str); + char *bufptr = buf; + char *spaceptr = NULL; + enum ParserState state = PS_FIRST; - argv[argc++] = bufptr; - // param0 = program name - memcpy(buf, programName, strlen(programName) + 1); // with 0x00 - bufptr += strlen(programName) + 1; - if (len) - argv[argc++] = bufptr; + argv[argc++] = bufptr; + // param0 = program name + memcpy(buf, programName, strlen(programName) + 1); // with 0x00 + bufptr += strlen(programName) + 1; + if (len) + argv[argc++] = bufptr; - // parse params - for (int i = 0; i < len; i++) { - switch(state){ - case PS_FIRST: // first char - if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields - state = PS_OPTION; + // parse params + for (int i = 0; i < len; i++) { + switch(state){ + case PS_FIRST: // first char + if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields + state = PS_OPTION; - if (spaceptr) { - bufptr = spaceptr; - *bufptr = 0x00; - bufptr++; - argv[argc++] = bufptr; - } - } - spaceptr = NULL; - case PS_ARGUMENT: - if (state == PS_FIRST) - state = PS_ARGUMENT; - if (isSpace(str[i])) { - spaceptr = bufptr; - state = PS_FIRST; - } - *bufptr = str[i]; - bufptr++; - break; - case PS_OPTION: - if (isSpace(str[i])){ - state = PS_FIRST; + if (spaceptr) { + bufptr = spaceptr; + *bufptr = 0x00; + bufptr++; + argv[argc++] = bufptr; + } + } + spaceptr = NULL; + case PS_ARGUMENT: + if (state == PS_FIRST) + state = PS_ARGUMENT; + if (isSpace(str[i])) { + spaceptr = bufptr; + state = PS_FIRST; + } + *bufptr = str[i]; + bufptr++; + break; + case PS_OPTION: + if (isSpace(str[i])){ + state = PS_FIRST; - *bufptr = 0x00; - bufptr++; - argv[argc++] = bufptr; - break; - } + *bufptr = 0x00; + bufptr++; + argv[argc++] = bufptr; + break; + } - *bufptr = str[i]; - bufptr++; - break; - } - } + *bufptr = str[i]; + bufptr++; + break; + } + } - return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); + return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); } void CLIParserFree() { - arg_freetable(argtable, argtableLen); - argtable = NULL; + arg_freetable(argtable, argtableLen); + argtable = NULL; - return; + return; } // convertors int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { - *datalen = 0; + *datalen = 0; - int ibuf = 0; - uint8_t buf[256] = {0}; - int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX - if (res || !ibuf) - return res; + int ibuf = 0; + uint8_t buf[256] = {0}; + int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX + if (res || !ibuf) + return res; - switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { - case 1: - printf("Parameter error: Invalid HEX value.\n"); - return 1; - case 2: - printf("Parameter error: parameter too large.\n"); - return 2; - case 3: - printf("Parameter error: Hex string must have even number of digits.\n"); - return 3; - } + switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { + case 1: + printf("Parameter error: Invalid HEX value.\n"); + return 1; + case 2: + printf("Parameter error: parameter too large.\n"); + return 2; + case 3: + printf("Parameter error: Hex string must have even number of digits.\n"); + return 3; + } - return 0; + return 0; } int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { - *datalen = 0; - if (!argstr->count) - return 0; + *datalen = 0; + if (!argstr->count) + return 0; - uint8_t buf[256] = {0}; - int ibuf = 0; + uint8_t buf[256] = {0}; + int ibuf = 0; - for (int i = 0; i < argstr->count; i++) { - int len = strlen(argstr->sval[i]); - memcpy(&buf[ibuf], argstr->sval[i], len); - ibuf += len; - } - buf[ibuf] = 0; + for (int i = 0; i < argstr->count; i++) { + int len = strlen(argstr->sval[i]); + memcpy(&buf[ibuf], argstr->sval[i], len); + ibuf += len; + } + buf[ibuf] = 0; - if (!ibuf) - return 0; + if (!ibuf) + return 0; - if (ibuf > maxdatalen) - return 2; + if (ibuf > maxdatalen) + return 2; - memcpy(data, buf, ibuf); - *datalen = ibuf; + memcpy(data, buf, ibuf); + *datalen = ibuf; - return 0; + return 0; } diff --git a/client/cliparser/getopt.h b/client/cliparser/getopt.h index 09ff126b4..c036ff686 100644 --- a/client/cliparser/getopt.h +++ b/client/cliparser/getopt.h @@ -1,5 +1,5 @@ -/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ -/* $FreeBSD$ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-2-Clause-NetBSD @@ -46,34 +46,34 @@ #define optional_argument 2 struct option { - /* name of long option */ - const char *name; - /* - * one of no_argument, required_argument, and optional_argument: - * whether option takes an argument - */ - int has_arg; - /* if not NULL, set *flag to val when option found */ - int *flag; - /* if flag not NULL, value to set *flag to; else return value */ - int val; + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; }; __BEGIN_DECLS -int getopt_long(int, char * const *, const char *, - const struct option *, int *); -int getopt_long_only(int, char * const *, const char *, - const struct option *, int *); +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); #ifndef _GETOPT_DECLARED -#define _GETOPT_DECLARED -int getopt(int, char * const [], const char *); +#define _GETOPT_DECLARED +int getopt(int, char * const [], const char *); -extern char *optarg; /* getopt(3) external variables */ +extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt; #endif #ifndef _OPTRESET_DECLARED -#define _OPTRESET_DECLARED -extern int optreset; /* getopt(3) external variable */ +#define _OPTRESET_DECLARED +extern int optreset; /* getopt(3) external variable */ #endif __END_DECLS diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 94411f8b5..c0e455fe2 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -12,70 +12,70 @@ static int CmdHelp(const char *Cmd); int usage_analyse_lcr(void) { - PrintAndLogEx(NORMAL, "Specifying the bytes of a UID with a known LRC will find the last byte value"); - PrintAndLogEx(NORMAL, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse lcr [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " bytes to calc missing XOR in a LCR"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse lcr 04008064BA"); - PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A"); - return 0; + PrintAndLogEx(NORMAL, "Specifying the bytes of a UID with a known LRC will find the last byte value"); + PrintAndLogEx(NORMAL, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse lcr [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " bytes to calc missing XOR in a LCR"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse lcr 04008064BA"); + PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A"); + return 0; } int usage_analyse_checksum(void) { - PrintAndLogEx(NORMAL, "The bytes will be added with eachother and than limited with the applied mask"); - PrintAndLogEx(NORMAL, "Finally compute ones' complement of the least significant bytes"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse chksum [h] [v] b m "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " v supress header"); - PrintAndLogEx(NORMAL, " b bytes to calc missing XOR in a LCR"); - PrintAndLogEx(NORMAL, " m bit mask to limit the outpuyt"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse chksum b 137AF00A0A0D m FF"); - PrintAndLogEx(NORMAL, "expected output: 0x61"); - return 0; + PrintAndLogEx(NORMAL, "The bytes will be added with eachother and than limited with the applied mask"); + PrintAndLogEx(NORMAL, "Finally compute ones' complement of the least significant bytes"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse chksum [h] [v] b m "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " v supress header"); + PrintAndLogEx(NORMAL, " b bytes to calc missing XOR in a LCR"); + PrintAndLogEx(NORMAL, " m bit mask to limit the outpuyt"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse chksum b 137AF00A0A0D m FF"); + PrintAndLogEx(NORMAL, "expected output: 0x61"); + return 0; } int usage_analyse_crc(void){ - PrintAndLogEx(NORMAL, "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse crc [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " bytes to calc crc"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D"); - return 0; + PrintAndLogEx(NORMAL, "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse crc [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " bytes to calc crc"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D"); + return 0; } int usage_analyse_nuid(void){ - PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse hid [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " input bytes (14 hexsymbols)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse nuid 11223344556677"); - return 0; + PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse hid [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " input bytes (14 hexsymbols)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse nuid 11223344556677"); + return 0; } int usage_analyse_a(void) { - PrintAndLogEx(NORMAL, "Iceman's personal garbage test command"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse a [h] d "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " d bytes to send to device"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse a d 137AF00A0A0D"); - return 0; + PrintAndLogEx(NORMAL, "Iceman's personal garbage test command"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse a [h] d "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " d bytes to send to device"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse a d 137AF00A0A0D"); + return 0; } static uint8_t calculateLRC( uint8_t* bytes, uint8_t len) { @@ -94,129 +94,129 @@ static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){ ----------------- C32F 9d74 - return 0; + return 0; } */ /* static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){ - return 0; + return 0; } */ static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += CRUMB(bytes[i], 0); - sum += CRUMB(bytes[i], 2); - sum += CRUMB(bytes[i], 4); - sum += CRUMB(bytes[i], 6); - } - sum &= mask; + sum += CRUMB(bytes[i], 2); + sum += CRUMB(bytes[i], 4); + sum += CRUMB(bytes[i], 6); + } + sum &= mask; return sum; } static uint16_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return (~calcSumCrumbAdd(bytes, len, mask) & mask); + return (~calcSumCrumbAdd(bytes, len, mask) & mask); } static uint16_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += NIBBLE_LOW(bytes[i]); - sum += NIBBLE_HIGH(bytes[i]); - } - sum &= mask; + sum += NIBBLE_HIGH(bytes[i]); + } + sum &= mask; return sum; } static uint16_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ - return (~calcSumNibbleAdd(bytes, len, mask) & mask); + return (~calcSumNibbleAdd(bytes, len, mask) & mask); } static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= CRUMB(bytes[i], 0); - sum ^= CRUMB(bytes[i], 2); - sum ^= CRUMB(bytes[i], 4); - sum ^= CRUMB(bytes[i], 6); - } - sum &= mask; + sum ^= CRUMB(bytes[i], 2); + sum ^= CRUMB(bytes[i], 4); + sum ^= CRUMB(bytes[i], 6); + } + sum &= mask; return sum; } static uint16_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= NIBBLE_LOW(bytes[i]); - sum ^= NIBBLE_HIGH(bytes[i]); - } - sum &= mask; + sum ^= NIBBLE_HIGH(bytes[i]); + } + sum &= mask; return sum; } static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { - sum ^= bytes[i]; - } - sum &= mask; + sum ^= bytes[i]; + } + sum &= mask; return sum; } static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { - sum += bytes[i]; - } - sum &= mask; + sum += bytes[i]; + } + sum &= mask; return sum; } // Ones complement static uint16_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return (~calcSumByteAdd(bytes, len, mask) & mask); + return (~calcSumByteAdd(bytes, len, mask) & mask); } static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { - sum -= bytes[i]; - } - sum &= mask; + sum -= bytes[i]; + } + sum &= mask; return sum; } static uint16_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ - return (~calcSumByteSub(bytes, len, mask) & mask); + return (~calcSumByteSub(bytes, len, mask) & mask); } static uint16_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum -= NIBBLE_LOW(bytes[i]); - sum -= NIBBLE_HIGH(bytes[i]); - } - sum &= mask; + sum -= NIBBLE_HIGH(bytes[i]); + } + sum &= mask; return sum; } static uint16_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return (~calcSumNibbleSub(bytes, len, mask) & mask); + return (~calcSumNibbleSub(bytes, len, mask) & mask); } // BSD shift checksum 8bit version static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){ - uint16_t sum = 0; - for(uint8_t i = 0; i < len; i++){ - sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator - sum += bytes[i]; // add next byte - sum &= 0xFF; // - } - sum &= mask; - return sum; + uint16_t sum = 0; + for(uint8_t i = 0; i < len; i++){ + sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator + sum += bytes[i]; // add next byte + sum &= 0xFF; // + } + sum &= mask; + return sum; } // BSD shift checksum 4bit version static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){ - uint16_t sum = 0; - for(uint8_t i = 0; i < len; i++){ - sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator - sum += NIBBLE_HIGH(bytes[i]); // add high nibble - sum &= 0xF; // - sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator - sum += NIBBLE_LOW(bytes[i]); // add low nibble - sum &= 0xF; // - } - sum &= mask; - return sum; + uint16_t sum = 0; + for(uint8_t i = 0; i < len; i++){ + sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator + sum += NIBBLE_HIGH(bytes[i]); // add high nibble + sum &= 0xF; // + sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator + sum += NIBBLE_LOW(bytes[i]); // add low nibble + sum &= 0xF; // + } + sum &= mask; + return sum; } // measuring LFSR maximum length @@ -226,334 +226,334 @@ int CmdAnalyseLfsr(const char *Cmd){ uint16_t lfsr = start_state; //uint32_t period = 0; - uint8_t iv = param_get8ex(Cmd, 0, 0, 16); - uint8_t find = param_get8ex(Cmd, 1, 0, 16); + uint8_t iv = param_get8ex(Cmd, 0, 0, 16); + uint8_t find = param_get8ex(Cmd, 1, 0, 16); - PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv); - PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find); + PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv); + PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find); - for (uint8_t i = 0x01; i < 0x30; i += 1) { - //period = 0; - legic_prng_init(iv); - legic_prng_forward(i); - lfsr = legic_prng_get_bits(12); + for (uint8_t i = 0x01; i < 0x30; i += 1) { + //period = 0; + legic_prng_init(iv); + legic_prng_forward(i); + lfsr = legic_prng_get_bits(12); - PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n",i, lfsr, 0x40 ^ lfsr, find ^ lfsr); - } - return 0; + PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n",i, lfsr, 0x40 ^ lfsr, find ^ lfsr); + } + return 0; } int CmdAnalyseLCR(const char *Cmd) { - uint8_t data[50]; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr(); + uint8_t data[50]; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr(); - int len = 0; - switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { - case 1: - PrintAndLogEx(WARNING, "Invalid HEX value."); - return 1; - case 2: - PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data)); - return 1; - case 3: - PrintAndLogEx(WARNING, "Hex must have even number of digits."); - return 1; - } - uint8_t finalXor = calculateLRC(data, len); - PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor); - return 0; + int len = 0; + switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { + case 1: + PrintAndLogEx(WARNING, "Invalid HEX value."); + return 1; + case 2: + PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data)); + return 1; + case 3: + PrintAndLogEx(WARNING, "Hex must have even number of digits."); + return 1; + } + uint8_t finalXor = calculateLRC(data, len); + PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor); + return 0; } int CmdAnalyseCRC(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); - int len = strlen(Cmd); - if ( len & 1 ) return usage_analyse_crc(); + int len = strlen(Cmd); + if ( len & 1 ) return usage_analyse_crc(); - // add 1 for null terminator. - uint8_t *data = calloc(len+1, sizeof(uint8_t)); - if ( !data ) return 1; + // add 1 for null terminator. + uint8_t *data = calloc(len+1, sizeof(uint8_t)); + if ( !data ) return 1; - if ( param_gethex(Cmd, 0, data, len)) { - free(data); - return usage_analyse_crc(); - } - len >>= 1; + if ( param_gethex(Cmd, 0, data, len)) { + free(data); + return usage_analyse_crc(); + } + len >>= 1; - PrintAndLogEx(NORMAL, "\nTests with (%d) | %s",len, sprint_hex(data, len)); + PrintAndLogEx(NORMAL, "\nTests with (%d) | %s",len, sprint_hex(data, len)); - // 51 f5 7a d6 - uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 - init_table(CRC_LEGIC); - uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); - PrintAndLogEx(NORMAL, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, len, legic8), legic8); - init_table(CRC_FELICA); - PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len)); + // 51 f5 7a d6 + uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 + init_table(CRC_LEGIC); + uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); + PrintAndLogEx(NORMAL, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, len, legic8), legic8); + init_table(CRC_FELICA); + PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len)); - PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); - PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) ); - PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80)); - PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); + PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); + PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) ); + PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80)); + PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); - uint8_t b1, b2; - // ISO14443 crc B - compute_crc(CRC_14443_B, data, len, &b1, &b2); - uint16_t crcBB_1 = b1 << 8 | b2; - uint16_t bbb = crc(CRC_14443_B, data, len); - PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb ); + uint8_t b1, b2; + // ISO14443 crc B + compute_crc(CRC_14443_B, data, len, &b1, &b2); + uint16_t crcBB_1 = b1 << 8 | b2; + uint16_t bbb = crc(CRC_14443_B, data, len); + PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb ); - // Test of CRC16, '123456789' string. - // + // Test of CRC16, '123456789' string. + // - PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); - uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; - legic8 = CRC8Legic(dataStr, sizeof(dataStr)); + PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); + uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; + legic8 = CRC8Legic(dataStr, sizeof(dataStr)); - //these below has been tested OK. - PrintAndLogEx(NORMAL, "Confirmed CRC Implementations"); - PrintAndLogEx(NORMAL, "-------------------------------------\n"); - PrintAndLogEx(NORMAL, "CRC 8 based\n\n"); - PrintAndLogEx(NORMAL, "LEGIC: CRC8 : %X (C6 expected)", legic8); - PrintAndLogEx(NORMAL, "MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr))); - PrintAndLogEx(NORMAL, "-------------------------------------\n"); - PrintAndLogEx(NORMAL, "CRC16 based\n\n"); + //these below has been tested OK. + PrintAndLogEx(NORMAL, "Confirmed CRC Implementations"); + PrintAndLogEx(NORMAL, "-------------------------------------\n"); + PrintAndLogEx(NORMAL, "CRC 8 based\n\n"); + PrintAndLogEx(NORMAL, "LEGIC: CRC8 : %X (C6 expected)", legic8); + PrintAndLogEx(NORMAL, "MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "-------------------------------------\n"); + PrintAndLogEx(NORMAL, "CRC16 based\n\n"); - // input from commandline - PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); + // input from commandline + PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); - uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; - PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-4)); - PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2)); + uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-4)); + PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2)); - uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; - PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr)-2)); - PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n"); + uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; + PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr)-2)); + PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n"); - // ISO14443 crc A - compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcAA = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)) ); + // ISO14443 crc A + compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcAA = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)) ); - // ISO14443 crc B - compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcBB = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr)) ); + // ISO14443 crc B + compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcBB = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr)) ); - // ISO15693 crc (x.25) - compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcCC = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)) ); + // ISO15693 crc (x.25) + compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcCC = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)) ); - // ICLASS - compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcDD = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)) ); + // ICLASS + compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcDD = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)) ); - // FeliCa - compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcEE = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, crc(CRC_FELICA, dataStr, sizeof(dataStr))); + // FeliCa + compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcEE = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, crc(CRC_FELICA, dataStr, sizeof(dataStr))); - free(data); - return 0; + free(data); + return 0; } int CmdAnalyseCHKSUM(const char *Cmd){ - uint8_t data[50]; - uint8_t cmdp = 0; - uint32_t mask = 0xFFFF; - bool errors = false; - bool useHeader = false; - int len = 0; - memset(data, 0x0, sizeof(data)); + uint8_t data[50]; + uint8_t cmdp = 0; + uint32_t mask = 0xFFFF; + bool errors = false; + bool useHeader = false; + int len = 0; + memset(data, 0x0, sizeof(data)); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'b': - case 'B': - param_gethex_ex(Cmd, cmdp+1, data, &len); - if ( len%2 ) errors = true; - len >>= 1; - cmdp += 2; - break; - case 'm': - case 'M': - mask = param_get32ex(Cmd, cmdp+1, 0, 16); - cmdp += 2; - break; - case 'v': - case 'V': - useHeader = true; - cmdp++; - break; - case 'h': - case 'H': - return usage_analyse_checksum(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0 ) return usage_analyse_checksum(); + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'b': + case 'B': + param_gethex_ex(Cmd, cmdp+1, data, &len); + if ( len%2 ) errors = true; + len >>= 1; + cmdp += 2; + break; + case 'm': + case 'M': + mask = param_get32ex(Cmd, cmdp+1, 0, 16); + cmdp += 2; + break; + case 'v': + case 'V': + useHeader = true; + cmdp++; + break; + case 'h': + case 'H': + return usage_analyse_checksum(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0 ) return usage_analyse_checksum(); - if (useHeader) { - PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor"); - PrintAndLogEx(NORMAL, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |"); - PrintAndLogEx(NORMAL, "------------------+-------------+------------------+-----------------+--------------------"); - } - PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", - calcSumByteAdd(data, len, mask) - , calcSumNibbleAdd(data, len, mask) - , calcSumCrumbAdd(data, len, mask) - , calcSumByteSub(data, len, mask) - , calcSumNibbleSub(data, len, mask) - , calcSumByteAddOnes(data, len, mask) - , calcSumNibbleAddOnes(data, len, mask) - , calcSumCrumbAddOnes(data, len, mask) - , calcSumByteSubOnes(data, len, mask) - , calcSumNibbleSubOnes(data, len, mask) - , calcSumByteXor(data, len, mask) - , calcSumNibbleXor(data, len, mask) - , calcSumCrumbXor(data, len, mask) - , calcBSDchecksum8(data, len, mask) - , calcBSDchecksum4(data, len, mask) - ); - return 0; + if (useHeader) { + PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor"); + PrintAndLogEx(NORMAL, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |"); + PrintAndLogEx(NORMAL, "------------------+-------------+------------------+-----------------+--------------------"); + } + PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", + calcSumByteAdd(data, len, mask) + , calcSumNibbleAdd(data, len, mask) + , calcSumCrumbAdd(data, len, mask) + , calcSumByteSub(data, len, mask) + , calcSumNibbleSub(data, len, mask) + , calcSumByteAddOnes(data, len, mask) + , calcSumNibbleAddOnes(data, len, mask) + , calcSumCrumbAddOnes(data, len, mask) + , calcSumByteSubOnes(data, len, mask) + , calcSumNibbleSubOnes(data, len, mask) + , calcSumByteXor(data, len, mask) + , calcSumNibbleXor(data, len, mask) + , calcSumCrumbXor(data, len, mask) + , calcBSDchecksum8(data, len, mask) + , calcBSDchecksum4(data, len, mask) + ); + return 0; } int CmdAnalyseDates(const char *Cmd){ - // look for datestamps in a given array of bytes - PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!"); - return 0; + // look for datestamps in a given array of bytes + PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!"); + return 0; } int CmdAnalyseTEASelfTest(const char *Cmd){ - uint8_t v[8], v_le[8]; - memset(v, 0x00, sizeof(v)); - memset(v_le, 0x00, sizeof(v_le)); - uint8_t* v_ptr = v_le; + uint8_t v[8], v_le[8]; + memset(v, 0x00, sizeof(v)); + memset(v_le, 0x00, sizeof(v_le)); + uint8_t* v_ptr = v_le; - uint8_t cmdlen = strlen(Cmd); - cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen; + uint8_t cmdlen = strlen(Cmd); + cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen; - if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){ - PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen); - return 1; - } + if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){ + PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen); + return 1; + } - SwapEndian64ex(v , 8, 4, v_ptr); + SwapEndian64ex(v , 8, 4, v_ptr); - // ENCRYPTION KEY: - uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB }; - uint8_t keyle[16]; - uint8_t* key_ptr = keyle; - SwapEndian64ex(key , sizeof(key), 4, key_ptr); + // ENCRYPTION KEY: + uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB }; + uint8_t keyle[16]; + uint8_t* key_ptr = keyle; + SwapEndian64ex(key , sizeof(key), 4, key_ptr); - PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8)); + PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8)); - tea_decrypt(v_ptr, key_ptr); - PrintAndLogEx(NORMAL, "TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8)); + tea_decrypt(v_ptr, key_ptr); + PrintAndLogEx(NORMAL, "TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8)); - tea_encrypt(v_ptr, key_ptr); - tea_encrypt(v_ptr, key_ptr); - PrintAndLogEx(NORMAL, "TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8)); + tea_encrypt(v_ptr, key_ptr); + tea_encrypt(v_ptr, key_ptr); + PrintAndLogEx(NORMAL, "TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8)); - return 0; + return 0; } char* pb(uint32_t b) { - static char buf1[33] = {0}; - static char buf2[33] = {0}; - static char *s; + static char buf1[33] = {0}; + static char buf2[33] = {0}; + static char *s; - if (s != buf1) - s = buf1; - else - s = buf2; + if (s != buf1) + s = buf1; + else + s = buf2; - memset(s, 0, sizeof(buf1)); + memset(s, 0, sizeof(buf1)); - uint32_t mask = 0x80000000; - for (uint8_t i=0; i<32;i++) { - s[i] = (mask & b)?'1':'0'; - mask >>= 1; - } - return s; + uint32_t mask = 0x80000000; + for (uint8_t i=0; i<32;i++) { + s[i] = (mask & b)?'1':'0'; + mask >>= 1; + } + return s; } int CmdAnalyseA(const char *Cmd){ - int hexlen = 0; - uint8_t cmdp = 0; - bool errors = false; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + int hexlen = 0; + uint8_t cmdp = 0; + bool errors = false; + uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'd': - param_gethex_ex(Cmd, cmdp+1, data, &hexlen); - hexlen >>= 1; - if ( hexlen != sizeof(data) ) { - PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) ); - } - cmdp += 2; - break; - case 'h': - return usage_analyse_a(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0 ) return usage_analyse_a(); + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'd': + param_gethex_ex(Cmd, cmdp+1, data, &hexlen); + hexlen >>= 1; + if ( hexlen != sizeof(data) ) { + PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) ); + } + cmdp += 2; + break; + case 'h': + return usage_analyse_a(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0 ) return usage_analyse_a(); - UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}}; - memcpy(c.d.asBytes, data, USB_CMD_DATA_SIZE); - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}}; + memcpy(c.d.asBytes, data, USB_CMD_DATA_SIZE); + clearCommandBuffer(); + SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - return 1; - } - PrintAndLogEx(NORMAL, "got ack. Status %d", resp.arg[0]); - return 0; + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + return 1; + } + PrintAndLogEx(NORMAL, "got ack. Status %d", resp.arg[0]); + return 0; - PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n"); - PrintAndLogEx(NORMAL, "-- " _RED_(its my message) "\n"); - PrintAndLogEx(NORMAL, "-- " _YELLOW_(its my message) "\n"); - PrintAndLogEx(NORMAL, "-- " _GREEN_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _RED_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _YELLOW_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _GREEN_(its my message) "\n"); - //uint8_t syncBit = 99; - // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from - // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) - // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern - // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) - # define SYNC_16BIT 0xB24D - uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16); - uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16); - uint8_t byte_offset = 99; - // reverse byte - uint8_t rev = reflect8(bt); - PrintAndLogEx(NORMAL, "input %02x | %02x \n", bt, rev); - // add byte to shift register - shiftReg = shiftReg << 8 | rev; + //uint8_t syncBit = 99; + // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from + // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) + // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern + // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) + # define SYNC_16BIT 0xB24D + uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16); + uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16); + uint8_t byte_offset = 99; + // reverse byte + uint8_t rev = reflect8(bt); + PrintAndLogEx(NORMAL, "input %02x | %02x \n", bt, rev); + // add byte to shift register + shiftReg = shiftReg << 8 | rev; - PrintAndLogEx(NORMAL, "shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT); + PrintAndLogEx(NORMAL, "shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT); - uint8_t n0 = 0, n1 = 0; + uint8_t n0 = 0, n1 = 0; - n0 = (rev & (uint8_t)(~(0xFF >> (8-4)))) >> 4; - n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4))); + n0 = (rev & (uint8_t)(~(0xFF >> (8-4)))) >> 4; + n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4))); - PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); + PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); /* hex(0xb24d shr 0) 0xB24D 0b1011001001001101 @@ -562,111 +562,111 @@ hex(0xb24d shr 2) 0x2C93 */ for ( int i =0; i< 16; i++) { - PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF )); + PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF )); - // kolla om SYNC_PATTERN finns. - if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7; - else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6; - else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5; - else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; - else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3; - else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2; - else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1; - else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0; + // kolla om SYNC_PATTERN finns. + if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7; + else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6; + else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5; + else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; + else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3; + else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2; + else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1; + else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0; - PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset); - if ( byte_offset != 99 ) - break; + PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset); + if ( byte_offset != 99 ) + break; - shiftReg >>=1; + shiftReg >>=1; } - uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset))); - PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) ); + uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset))); + PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) ); - /* + /* pm3 --> da hex2bin 4db2 0100110110110010 */ - return 0; + return 0; /* - // split byte into two parts. - uint8_t offset = 3, n0 = 0, n1 = 0; - rev = 0xB2; - for (uint8_t m=0; m<8; m++) { - offset = m; - n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset; - n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset))); + // split byte into two parts. + uint8_t offset = 3, n0 = 0, n1 = 0; + rev = 0xB2; + for (uint8_t m=0; m<8; m++) { + offset = m; + n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset; + n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset))); - PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); - n0 = 0, n1 = 0; - // PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) ); - //PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) ); - //PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) )); - } + PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); + n0 = 0, n1 = 0; + // PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) ); + //PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) ); + //PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) )); + } return 0; - // from A -- x bits into B and the rest into C. + // from A -- x bits into B and the rest into C. - for ( uint8_t i=0; i<8; i++){ - PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) ); - b = a & (a & (0xFF >> (8-i))); - a >>=1; - } + for ( uint8_t i=0; i<8; i++){ + PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) ); + b = a & (a & (0xFF >> (8-i))); + a >>=1; + } - */ - return 0; + */ + return 0; - // 14443-A - uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc - uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc - PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" ); - PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES": "NO" ); + // 14443-A + uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc + uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc + PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" ); + PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES": "NO" ); - // 14443-B - uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73}; - PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO"); + // 14443-B + uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73}; + PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO"); - // 15693 test - uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct - uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong - PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO"); + // 15693 test + uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct + uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong + PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO"); - // iCLASS test - wrong crc , swapped bytes. - uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43}; - uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; - PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO"); + // iCLASS test - wrong crc , swapped bytes. + uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43}; + uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; + PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO"); - // FeliCa test - uint8_t felica_w[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7e}; - uint8_t felica_c[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; - PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO"); + // FeliCa test + uint8_t felica_w[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7e}; + uint8_t felica_c[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO"); - PrintAndLogEx(NORMAL, "\n\n"); + PrintAndLogEx(NORMAL, "\n\n"); - return 0; - /* - bool term = !isatty(STDIN_FILENO); - if (!term) { - char star[4]; - star[0] = '-'; - star[1] = '\\'; - star[2] = '|'; - star[3] = '/'; + return 0; + /* + bool term = !isatty(STDIN_FILENO); + if (!term) { + char star[4]; + star[0] = '-'; + star[1] = '\\'; + star[2] = '|'; + star[3] = '/'; - for (uint8_t k=0; k<4; k = (k+1) % 4 ) { - PrintAndLogEx(NORMAL, "\e[s%c\e[u", star[k]); - fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - break; - } - } - } - */ + for (uint8_t k=0; k<4; k = (k+1) % 4 ) { + PrintAndLogEx(NORMAL, "\e[s%c\e[u", star[k]); + fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + break; + } + } + } + */ //piwi // uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000) @@ -691,225 +691,225 @@ return 0; uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001) uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002) */ - uint64_t *keylistA = NULL, *keylistB = NULL; - uint32_t keycountA = 0, keycountB = 0; -// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800}; -// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f}; + uint64_t *keylistA = NULL, *keylistB = NULL; + uint32_t keycountA = 0, keycountB = 0; +// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800}; +// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f}; uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02}; uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; - keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA); - keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB); + keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA); + keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB); - switch (keycountA) { - case 0: PrintAndLogEx(FAILED, "Key test A failed\n"); break; - case 1: PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]); break; - } - switch (keycountB) { - case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break; - case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break; - } + switch (keycountA) { + case 0: PrintAndLogEx(FAILED, "Key test A failed\n"); break; + case 1: PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]); break; + } + switch (keycountB) { + case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break; + case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break; + } - free(keylistA); - free(keylistB); + free(keylistA); + free(keylistB); -// qsort(keylist, keycount, sizeof(*keylist), compare_uint64); -// keycount = intersection(last_keylist, keylist); +// qsort(keylist, keycount, sizeof(*keylist), compare_uint64); +// keycount = intersection(last_keylist, keylist); - /* - uint64_t keys[] = { - 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, - 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, - 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, - 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9, - 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, - 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, - 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, - 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe - }; + /* + uint64_t keys[] = { + 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, + 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, + 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, + 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9, + 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, + 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, + 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, + 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe + }; - uint64_t keya[] = { - 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, - 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, - 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, - 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9 - }; - uint64_t keyb[] = { - 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, - 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, - 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, - 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe - }; + uint64_t keya[] = { + 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, + 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, + 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, + 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9 + }; + uint64_t keyb[] = { + 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, + 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, + 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, + 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe + }; - */ + */ - /* - uint64_t xor[] = { - 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, - 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, - 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, - 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776, - 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, - 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, - 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, - 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 - }; + /* + uint64_t xor[] = { + 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, + 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, + 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, + 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776, + 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, + 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, + 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, + 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 + }; - uint64_t xorA[] = { - 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, - 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, - 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, - 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC - }; - uint64_t xorB[] = { - 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, - 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, - 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, - 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 - }; - */ - /* - // xor key A | xor key B - 1 | 0DEFED88E531 | 2F87A1BDC230 - 2 | 7577AFA2E1BC | E43F502B984C - 3 | 14D7D7BDBEC3 | 8A776AB752D9 - 4 | F5ABD3C6278B | 9A58D96A472F - 5 | AABDFA08276F | EF3702E01916 - 6 | B77C275C10D6 | 48A03B01D007 - 7 | B6DD0B434080 | 14754B0D659E - 8 | AAF2444499C6 | 009AD1868FDD - 9 | 852D7F8EBF90 | 6082DB527C11 - 10 | 3108821DB92C | 4D666ADA4C0E - 11 | B3756A1FB685 | 2D461D05F163 - 12 | DFE627C86A52 | 3596CFF0FEC8 - 13 | 5D3C093EF375 | 8CBD9258FE22 - 14 | 28C81D6FBF0E | 00D29A7B304B - 15 | 1204DF4D3ECC | BC33DC6C9244 - */ + uint64_t xorA[] = { + 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, + 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, + 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, + 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC + }; + uint64_t xorB[] = { + 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, + 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, + 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, + 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 + }; + */ + /* + // xor key A | xor key B + 1 | 0DEFED88E531 | 2F87A1BDC230 + 2 | 7577AFA2E1BC | E43F502B984C + 3 | 14D7D7BDBEC3 | 8A776AB752D9 + 4 | F5ABD3C6278B | 9A58D96A472F + 5 | AABDFA08276F | EF3702E01916 + 6 | B77C275C10D6 | 48A03B01D007 + 7 | B6DD0B434080 | 14754B0D659E + 8 | AAF2444499C6 | 009AD1868FDD + 9 | 852D7F8EBF90 | 6082DB527C11 + 10 | 3108821DB92C | 4D666ADA4C0E + 11 | B3756A1FB685 | 2D461D05F163 + 12 | DFE627C86A52 | 3596CFF0FEC8 + 13 | 5D3C093EF375 | 8CBD9258FE22 + 14 | 28C81D6FBF0E | 00D29A7B304B + 15 | 1204DF4D3ECC | BC33DC6C9244 + */ - // generate xor table :) - /* - for (uint8_t i=0; i<31; i++){ - uint64_t a = keys[i] ^ keys[i+1]; - PrintAndLogEx(NORMAL, "%u | %012" PRIX64 " | \n", i, a); - } - */ + // generate xor table :) + /* + for (uint8_t i=0; i<31; i++){ + uint64_t a = keys[i] ^ keys[i+1]; + PrintAndLogEx(NORMAL, "%u | %012" PRIX64 " | \n", i, a); + } + */ - /* - uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16); - uint8_t uid[6] = {0}; - num_to_bytes(id,4,uid); + /* + uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16); + uint8_t uid[6] = {0}; + num_to_bytes(id,4,uid); - uint8_t key_s0a[] = { - uid[1] ^ uid[2] ^ uid[3] ^ 0x11, - uid[1] ^ 0x72, - uid[2] ^ 0x80, - (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19, - 0xA3, - 0x2F - }; + uint8_t key_s0a[] = { + uid[1] ^ uid[2] ^ uid[3] ^ 0x11, + uid[1] ^ 0x72, + uid[2] ^ 0x80, + (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19, + 0xA3, + 0x2F + }; - PrintAndLogEx(NORMAL, "UID | %s\n", sprint_hex(uid,4 )); - PrintAndLogEx(NORMAL, "KEY A | %s\n", sprint_hex(key_s0a, 6)); + PrintAndLogEx(NORMAL, "UID | %s\n", sprint_hex(uid,4 )); + PrintAndLogEx(NORMAL, "KEY A | %s\n", sprint_hex(key_s0a, 6)); - // arrays w all keys - uint64_t foo[32] = {0}; + // arrays w all keys + uint64_t foo[32] = {0}; - //A - foo[0] = bytes_to_num(key_s0a, 6); - //B - //foo[16] = 0xcafe71411fbf; - foo[16] = 0xeafe51411fbf; + //A + foo[0] = bytes_to_num(key_s0a, 6); + //B + //foo[16] = 0xcafe71411fbf; + foo[16] = 0xeafe51411fbf; - for (uint8_t i=0; i<15; i++){ - foo[i+1] = foo[i] ^ xorA[i]; - foo[i+16+1] = foo[i+16] ^ xorB[i]; + for (uint8_t i=0; i<15; i++){ + foo[i+1] = foo[i] ^ xorA[i]; + foo[i+16+1] = foo[i+16] ^ xorB[i]; - } - for (uint8_t i=0; i<15; i++){ - uint64_t a = foo[i]; - uint64_t b = foo[i+16]; + } + for (uint8_t i=0; i<15; i++){ + uint64_t a = foo[i]; + uint64_t b = foo[i+16]; - PrintAndLogEx(NORMAL, "%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n", - i, - a, - ( a == keya[i])?"ok":"err", - b, - ( b == keyb[i])?"ok":"err" - ); - } - */ - return 0; + PrintAndLogEx(NORMAL, "%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n", + i, + a, + ( a == keya[i])?"ok":"err", + b, + ( b == keyb[i])?"ok":"err" + ); + } + */ + return 0; } void generate4bNUID(uint8_t *uid, uint8_t *nuid){ - uint16_t crc; - uint8_t b1, b2; + uint16_t crc; + uint8_t b1, b2; - compute_crc(CRC_14443_A, uid, 3, &b1, &b2); - nuid[0] = (b2 & 0xE0) | 0xF; - nuid[1] = b1; - crc = b1; - crc |= b2 << 8; - crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true); - nuid[2] = (crc >> 8) & 0xFF ; - nuid[3] = crc & 0xFF; + compute_crc(CRC_14443_A, uid, 3, &b1, &b2); + nuid[0] = (b2 & 0xE0) | 0xF; + nuid[1] = b1; + crc = b1; + crc |= b2 << 8; + crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true); + nuid[2] = (crc >> 8) & 0xFF ; + nuid[3] = crc & 0xFF; } int CmdAnalyseNuid(const char *Cmd){ - uint8_t nuid[4] = {0}; - uint8_t uid[7] = {0}; - int len = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); + uint8_t nuid[4] = {0}; + uint8_t uid[7] = {0}; + int len = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); - /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */ - /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ - /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ - if (cmdp == 't') { - memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); - generate4bNUID(uid, nuid); + /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */ + /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ + /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ + if (cmdp == 't') { + memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); + generate4bNUID(uid, nuid); - bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); - PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail)); + bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); + PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail)); - memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); - generate4bNUID(uid, nuid); - bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); - PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_(OK) : _RED_(Fail)); - return 0; - } + memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); + generate4bNUID(uid, nuid); + bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); + PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_(OK) : _RED_(Fail)); + return 0; + } - param_gethex_ex(Cmd, 0, uid, &len); - if ( len%2 || len != 14) return usage_analyse_nuid(); + param_gethex_ex(Cmd, 0, uid, &len); + if ( len%2 || len != 14) return usage_analyse_nuid(); - generate4bNUID(uid, nuid); + generate4bNUID(uid, nuid); - PrintAndLogEx(NORMAL, "UID | %s \n", sprint_hex(uid, 7)); - PrintAndLogEx(NORMAL, "NUID | %s \n", sprint_hex(nuid, 4)); - return 0; + PrintAndLogEx(NORMAL, "UID | %s \n", sprint_hex(uid, 7)); + PrintAndLogEx(NORMAL, "NUID | %s \n", sprint_hex(nuid, 4)); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"lcr", CmdAnalyseLCR, 1, "Generate final byte for XOR LRC"}, - {"crc", CmdAnalyseCRC, 1, "Stub method for CRC evaluations"}, - {"chksum", CmdAnalyseCHKSUM, 1, "Checksum with adding, masking and one's complement"}, - {"dates", CmdAnalyseDates, 1, "Look for datestamps in a given array of bytes"}, - {"tea", CmdAnalyseTEASelfTest, 1, "Crypto TEA test"}, - {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"}, - {"a", CmdAnalyseA, 1, "num bits test"}, - {"nuid", CmdAnalyseNuid, 1, "create NUID from 7byte UID"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"lcr", CmdAnalyseLCR, 1, "Generate final byte for XOR LRC"}, + {"crc", CmdAnalyseCRC, 1, "Stub method for CRC evaluations"}, + {"chksum", CmdAnalyseCHKSUM, 1, "Checksum with adding, masking and one's complement"}, + {"dates", CmdAnalyseDates, 1, "Look for datestamps in a given array of bytes"}, + {"tea", CmdAnalyseTEASelfTest, 1, "Crypto TEA test"}, + {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"}, + {"a", CmdAnalyseA, 1, "num bits test"}, + {"nuid", CmdAnalyseNuid, 1, "create NUID from 7byte UID"}, + {NULL, NULL, 0, NULL} }; int CmdAnalyse(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdanalyse.h b/client/cmdanalyse.h index c362744c0..131fe0d11 100644 --- a/client/cmdanalyse.h +++ b/client/cmdanalyse.h @@ -11,20 +11,20 @@ #ifndef CMDANALYSE_H__ #define CMDANALYSE_H__ -#include //size_t +#include // size_t #include #include #include "cmdmain.h" #include "proxmark3.h" -#include "ui.h" // PrintAndLog +#include "ui.h" // PrintAndLog #include "util.h" #include "crc.h" -#include "crc16.h" // crc16 ccitt +#include "crc16.h" // crc16 ccitt #include "tea.h" #include "legic_prng.h" #include "loclass/elite_crack.h" -#include "mifare/mfkey.h" //nonce2key -#include "util_posix.h" // msclock +#include "mifare/mfkey.h" // nonce2key +#include "util_posix.h" // msclock int usage_analyse_lcr(void); diff --git a/client/cmdcrc.c b/client/cmdcrc.c index a54653d3e..38d5a2005 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -23,7 +23,7 @@ int split(char *str, char *arr[MAX_ARGS]){ } if(str[beginIndex] == '\0') { break; - } + } endIndex = beginIndex; while (str[endIndex] && !isspace(str[endIndex])) { ++endIndex; @@ -40,202 +40,202 @@ int split(char *str, char *arr[MAX_ARGS]){ } int CmdCrc(const char *Cmd) { - char name[] = {"reveng "}; - char Cmd2[100 + 7]; - memcpy(Cmd2, name, 7); - memcpy(Cmd2 + 7, Cmd, 100); - char *argv[MAX_ARGS]; - int argc = split(Cmd2, argv); + char name[] = {"reveng "}; + char Cmd2[100 + 7]; + memcpy(Cmd2, name, 7); + memcpy(Cmd2 + 7, Cmd, 100); + char *argv[MAX_ARGS]; + int argc = split(Cmd2, argv); - if (argc == 3 && memcmp(argv[1], "-g", 2) == 0) { - CmdrevengSearch(argv[2]); - } else { - reveng_main(argc, argv); - } - for(int i = 0; i < argc; ++i) { - free(argv[i]); - } - return 0; + if (argc == 3 && memcmp(argv[1], "-g", 2) == 0) { + CmdrevengSearch(argv[2]); + } else { + reveng_main(argc, argv); + } + for(int i = 0; i < argc; ++i) { + free(argv[i]); + } + return 0; } //returns array of model names and the count of models returning // as well as a width array for the width of each model int GetModels(char *Models[], int *count, uint8_t *width){ - /* default values */ - static model_t model = MZERO; + /* default values */ + static model_t model = MZERO; - int ibperhx = 8;//, obperhx = 8; - int rflags = 0, uflags = 0; /* search and UI flags */ - poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL; - model_t pset = model, *candmods, *mptr; + int ibperhx = 8;//, obperhx = 8; + int rflags = 0, uflags = 0; /* search and UI flags */ + poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL; + model_t pset = model, *candmods, *mptr; - /* stdin must be binary */ - #ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); - #endif /* _WIN32 */ + /* stdin must be binary */ + #ifdef _WIN32 + _setmode(STDIN_FILENO, _O_BINARY); + #endif /* _WIN32 */ - SETBMP(); + SETBMP(); - int args = 0, psets, pass; - int Cnt = 0; - if (width[0] == 0) { //reveng -D - *count = mcount(); - if (!*count){ - PrintAndLogEx(WARNING, "no preset models available"); - return 0; - } - for (int mode = 0; mode < *count; ++mode) { - mbynum(&model, mode); - mcanon(&model); - size_t size = (model.name && *model.name) ? strlen(model.name) : 7; - char *tmp = calloc(size+1, sizeof(char)); - if (tmp==NULL){ - PrintAndLogEx(WARNING, "out of memory?"); - return 0; - } - memcpy(tmp, model.name, size); - Models[mode] = tmp; - width[mode] = plen(model.spoly); - } - mfree(&model); - } else { //reveng -s + int args = 0, psets, pass; + int Cnt = 0; + if (width[0] == 0) { //reveng -D + *count = mcount(); + if (!*count){ + PrintAndLogEx(WARNING, "no preset models available"); + return 0; + } + for (int mode = 0; mode < *count; ++mode) { + mbynum(&model, mode); + mcanon(&model); + size_t size = (model.name && *model.name) ? strlen(model.name) : 7; + char *tmp = calloc(size+1, sizeof(char)); + if (tmp==NULL){ + PrintAndLogEx(WARNING, "out of memory?"); + return 0; + } + memcpy(tmp, model.name, size); + Models[mode] = tmp; + width[mode] = plen(model.spoly); + } + mfree(&model); + } else { //reveng -s - if (~model.flags & P_MULXN){ - PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models"); - return 0; - } - praloc(&model.spoly, (unsigned long)width[0]); - praloc(&model.init, (unsigned long)width[0]); - praloc(&model.xorout, (unsigned long)width[0]); + if (~model.flags & P_MULXN){ + PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models"); + return 0; + } + praloc(&model.spoly, (unsigned long)width[0]); + praloc(&model.init, (unsigned long)width[0]); + praloc(&model.xorout, (unsigned long)width[0]); - if (!plen(model.spoly)) - palloc(&model.spoly, (unsigned long)width[0]); - else - width[0] = (uint8_t)plen(model.spoly); + if (!plen(model.spoly)) + palloc(&model.spoly, (unsigned long)width[0]); + else + width[0] = (uint8_t)plen(model.spoly); - /* special case if qpoly is zero, search to end of range */ - if (!ptst(qpoly)) - rflags &= ~R_HAVEQ; + /* special case if qpoly is zero, search to end of range */ + if (!ptst(qpoly)) + rflags &= ~R_HAVEQ; - /* if endianness not specified, try - * little-endian then big-endian. - * NB: crossed-endian algorithms will not be - * searched. - */ - /* scan against preset models */ - if (~uflags & C_NOPCK) { - pass = 0; - Cnt = 0; - do { - psets = mcount(); + /* if endianness not specified, try + * little-endian then big-endian. + * NB: crossed-endian algorithms will not be + * searched. + */ + /* scan against preset models */ + if (~uflags & C_NOPCK) { + pass = 0; + Cnt = 0; + do { + psets = mcount(); - while (psets) { - mbynum(&pset, --psets); + while (psets) { + mbynum(&pset, --psets); - /* skip if different width, or refin or refout don't match */ - if( plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) - continue; - /* skip if the preset doesn't match specified parameters */ - if (rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) - continue; - if (rflags & R_HAVEI && psncmp(&model.init, &pset.init)) - continue; - if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) - continue; + /* skip if different width, or refin or refout don't match */ + if( plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) + continue; + /* skip if the preset doesn't match specified parameters */ + if (rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) + continue; + if (rflags & R_HAVEI && psncmp(&model.init, &pset.init)) + continue; + if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) + continue; - //for additional args (not used yet, maybe future?) - apoly = pclone(pset.xorout); + //for additional args (not used yet, maybe future?) + apoly = pclone(pset.xorout); - if (pset.flags & P_REFOUT) - prev(&apoly); + if (pset.flags & P_REFOUT) + prev(&apoly); - for (qptr = apolys; qptr < pptr; ++qptr) { - crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); - if (ptst(crc)) { - pfree(&crc); - break; - } - pfree(&crc); - } - pfree(&apoly); + for (qptr = apolys; qptr < pptr; ++qptr) { + crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); + if (ptst(crc)) { + pfree(&crc); + break; + } + pfree(&crc); + } + pfree(&apoly); - if (qptr == pptr) { + if (qptr == pptr) { - /* the selected model solved all arguments */ - mcanon(&pset); + /* the selected model solved all arguments */ + mcanon(&pset); - size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7; - //PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt); - char *tmp = calloc(size+1, sizeof(char)); - if (tmp == NULL){ - PrintAndLogEx(WARNING, "out of memory?"); - return 0; - } - width[Cnt] = width[0]; - memcpy(tmp, pset.name, size); - Models[Cnt++] = tmp; - *count = Cnt; - uflags |= C_RESULT; - } - } - mfree(&pset); + size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7; + //PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt); + char *tmp = calloc(size+1, sizeof(char)); + if (tmp == NULL){ + PrintAndLogEx(WARNING, "out of memory?"); + return 0; + } + width[Cnt] = width[0]; + memcpy(tmp, pset.name, size); + Models[Cnt++] = tmp; + *count = Cnt; + uflags |= C_RESULT; + } + } + mfree(&pset); - /* toggle refIn/refOut and reflect arguments */ - if (~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for (qptr = apolys; qptr < pptr; ++qptr) { - prevch(qptr, ibperhx); - } - } - } while (~rflags & R_HAVERI && ++pass < 2); - } - //got everything now free the memory... + /* toggle refIn/refOut and reflect arguments */ + if (~rflags & R_HAVERI) { + model.flags ^= P_REFIN | P_REFOUT; + for (qptr = apolys; qptr < pptr; ++qptr) { + prevch(qptr, ibperhx); + } + } + } while (~rflags & R_HAVERI && ++pass < 2); + } + //got everything now free the memory... - if (uflags & C_RESULT) { - for (qptr = apolys; qptr < pptr; ++qptr) { - pfree(qptr); - } - } - if(uflags & C_NOBFS && ~rflags & R_HAVEP) { - PrintAndLogEx(WARNING, "no models found"); - return 0; - } + if (uflags & C_RESULT) { + for (qptr = apolys; qptr < pptr; ++qptr) { + pfree(qptr); + } + } + if(uflags & C_NOBFS && ~rflags & R_HAVEP) { + PrintAndLogEx(WARNING, "no models found"); + return 0; + } - if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ - PrintAndLogEx(WARNING, "cannot search for crossed-endian models"); - return 0; - } - pass = 0; - do { - mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); - if (mptr && plen(mptr->spoly)) { - uflags |= C_RESULT; - } - while (mptr && plen(mptr->spoly)) { - mfree(mptr++); - } - free(candmods); - if (~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for (qptr = apolys; qptr < pptr; ++qptr) { - prevch(qptr, ibperhx); - } - } - } while (~rflags & R_HAVERI && ++pass < 2); + if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ + PrintAndLogEx(WARNING, "cannot search for crossed-endian models"); + return 0; + } + pass = 0; + do { + mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); + if (mptr && plen(mptr->spoly)) { + uflags |= C_RESULT; + } + while (mptr && plen(mptr->spoly)) { + mfree(mptr++); + } + free(candmods); + if (~rflags & R_HAVERI) { + model.flags ^= P_REFIN | P_REFOUT; + for (qptr = apolys; qptr < pptr; ++qptr) { + prevch(qptr, ibperhx); + } + } + } while (~rflags & R_HAVERI && ++pass < 2); - for (qptr = apolys; qptr < pptr; ++qptr) { - pfree(qptr); - } - free(apolys); - mfree(&model); + for (qptr = apolys; qptr < pptr; ++qptr) { + pfree(qptr); + } + free(apolys); + mfree(&model); - if (~uflags & C_RESULT){ - PrintAndLogEx(WARNING, "no models found"); - return 0; - } - } - return 1; + if (~uflags & C_RESULT){ + PrintAndLogEx(WARNING, "no models found"); + return 0; + } + } + return 1; } //-c || -v @@ -246,156 +246,156 @@ int GetModels(char *Models[], int *count, uint8_t *width){ // l = little endian input and output, L = little endian output only, t = left justified} //result = calculated crc hex string int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result){ - /* default values */ - static model_t model = MZERO; + /* default values */ + static model_t model = MZERO; - int ibperhx = 8, obperhx = 8; - int rflags = 0; // search flags - int c; - poly_t apoly, crc; + int ibperhx = 8, obperhx = 8; + int rflags = 0; // search flags + int c; + poly_t apoly, crc; - char *string; + char *string; - // stdin must be binary - #ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); - #endif /* _WIN32 */ + // stdin must be binary + #ifdef _WIN32 + _setmode(STDIN_FILENO, _O_BINARY); + #endif /* _WIN32 */ - SETBMP(); - //set model - c = mbynam(&model, inModel); - if (!c) { - PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c); - return 0; - } - if (c < 0){ - PrintAndLogEx(WARNING, "no preset models available"); - return 0; - } - rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; + SETBMP(); + //set model + c = mbynam(&model, inModel); + if (!c) { + PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c); + return 0; + } + if (c < 0){ + PrintAndLogEx(WARNING, "no preset models available"); + return 0; + } + rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; - //set flags - switch (endian) { - case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ - model.flags &= ~P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'B': /* B big-endian output (RefOut = false) */ - model.flags &= ~P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 'r': /* r right-justified */ - model.flags |= P_RTJUST; - break; - case 'l': /* l little-endian input and output */ - model.flags |= P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'L': /* L little-endian output */ - model.flags |= P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 't': /* t left-justified */ - model.flags &= ~P_RTJUST; - break; - } - /* canonicalise the model, so the one we dump is the one we - * calculate with (not with -s, spoly may be blank which will - * normalise to zero and clear init and xorout.) - */ - mcanon(&model); + //set flags + switch (endian) { + case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ + model.flags &= ~P_REFIN; + rflags |= R_HAVERI; + /* fall through: */ + case 'B': /* B big-endian output (RefOut = false) */ + model.flags &= ~P_REFOUT; + rflags |= R_HAVERO; + mnovel(&model); + /* fall through: */ + case 'r': /* r right-justified */ + model.flags |= P_RTJUST; + break; + case 'l': /* l little-endian input and output */ + model.flags |= P_REFIN; + rflags |= R_HAVERI; + /* fall through: */ + case 'L': /* L little-endian output */ + model.flags |= P_REFOUT; + rflags |= R_HAVERO; + mnovel(&model); + /* fall through: */ + case 't': /* t left-justified */ + model.flags &= ~P_RTJUST; + break; + } + /* canonicalise the model, so the one we dump is the one we + * calculate with (not with -s, spoly may be blank which will + * normalise to zero and clear init and xorout.) + */ + mcanon(&model); - if (reverse) { - // v calculate reversed CRC - /* Distinct from the -V switch as this causes - * the arguments and output to be reversed as well. - */ - // reciprocate Poly - prcp(&model.spoly); + if (reverse) { + // v calculate reversed CRC + /* Distinct from the -V switch as this causes + * the arguments and output to be reversed as well. + */ + // reciprocate Poly + prcp(&model.spoly); - /* mrev() does: - * if(refout) prev(init); else prev(xorout); - * but here the entire argument polynomial is - * reflected, not just the characters, so RefIn - * and RefOut are not inverted as with -V. - * Consequently Init is the mirror image of the - * one resulting from -V, and so we have: - */ - if (~model.flags & P_REFOUT) { - prev(&model.init); - prev(&model.xorout); - } + /* mrev() does: + * if(refout) prev(init); else prev(xorout); + * but here the entire argument polynomial is + * reflected, not just the characters, so RefIn + * and RefOut are not inverted as with -V. + * Consequently Init is the mirror image of the + * one resulting from -V, and so we have: + */ + if (~model.flags & P_REFOUT) { + prev(&model.init); + prev(&model.xorout); + } - // swap init and xorout - apoly = model.init; - model.init = model.xorout; - model.xorout = apoly; - } - // c calculate CRC + // swap init and xorout + apoly = model.init; + model.init = model.xorout; + model.xorout = apoly; + } + // c calculate CRC - /* in the Williams model, xorout is applied after the refout stage. - * as refout is part of ptostr(), we reverse xorout here. - */ - if (model.flags & P_REFOUT) - prev(&model.xorout); + /* in the Williams model, xorout is applied after the refout stage. + * as refout is part of ptostr(), we reverse xorout here. + */ + if (model.flags & P_REFOUT) + prev(&model.xorout); - apoly = strtop(inHexStr, model.flags, ibperhx); + apoly = strtop(inHexStr, model.flags, ibperhx); - if (reverse) - prev(&apoly); + if (reverse) + prev(&apoly); - crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags); + crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags); - if (reverse) - prev(&crc); + if (reverse) + prev(&crc); - string = ptostr(crc, model.flags, obperhx); - for (int i = 0; i < 50; i++){ - result[i] = string[i]; - if (result[i]==0) break; - } - free(string); - pfree(&crc); - pfree(&apoly); - return 1; + string = ptostr(crc, model.flags, obperhx); + for (int i = 0; i < 50; i++){ + result[i] = string[i]; + if (result[i]==0) break; + } + free(string); + pfree(&crc); + pfree(&apoly); + return 1; } //test call to RunModel int CmdrevengTestC(const char *Cmd){ - int cmdp = 0; - char inModel[30] = {0x00}; - char inHexStr[30] = {0x00}; - char result[30]; - int dataLen; - char endian = 0; - dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel)); - if (dataLen < 4) return 0; - dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); - if (dataLen < 4) return 0; - bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; - endian = param_getchar(Cmd, cmdp++); + int cmdp = 0; + char inModel[30] = {0x00}; + char inHexStr[30] = {0x00}; + char result[30]; + int dataLen; + char endian = 0; + dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel)); + if (dataLen < 4) return 0; + dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); + if (dataLen < 4) return 0; + bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; + endian = param_getchar(Cmd, cmdp++); - //PrintAndLogEx(NORMAL, "mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); - int ans = RunModel(inModel, inHexStr, reverse, endian, result); - if (!ans) return 0; + //PrintAndLogEx(NORMAL, "mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); + int ans = RunModel(inModel, inHexStr, reverse, endian, result); + if (!ans) return 0; - PrintAndLogEx(SUCCESS, "result: %s",result); - return 1; + PrintAndLogEx(SUCCESS, "result: %s",result); + return 1; } //returns a calloced string (needs to be freed) char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize){ - char *tmp = calloc(len+1, sizeof(char)); - for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ - for (size_t i = 0; i < blockSize; i+=2){ - tmp[i+(blockSize*block)] = inStr[(blockSize-1-i-1)+(blockSize*block)]; - tmp[i+(blockSize*block)+1] = inStr[(blockSize-1-i)+(blockSize*block)]; - } - } - return tmp; + char *tmp = calloc(len+1, sizeof(char)); + for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ + for (size_t i = 0; i < blockSize; i+=2){ + tmp[i+(blockSize*block)] = inStr[(blockSize-1-i-1)+(blockSize*block)]; + tmp[i+(blockSize*block)+1] = inStr[(blockSize-1-i)+(blockSize*block)]; + } + } + return tmp; } // takes hex string in and searches for a matching result (hex string must include checksum) @@ -403,84 +403,84 @@ int CmdrevengSearch(const char *Cmd){ #define NMODELS 105 - char inHexStr[100] = {0x00}; - int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); - if (dataLen < 4) return 0; + char inHexStr[100] = {0x00}; + int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); + if (dataLen < 4) return 0; - // these two arrays, must match preset size. - char *Models[NMODELS]; - uint8_t width[NMODELS] = {0}; - int count = 0; + // these two arrays, must match preset size. + char *Models[NMODELS]; + uint8_t width[NMODELS] = {0}; + int count = 0; - uint8_t crcChars = 0; - char result[30]; - char revResult[30]; - int ans = GetModels(Models, &count, width); - bool found = false; - if (!ans) return 0; + uint8_t crcChars = 0; + char result[30]; + char revResult[30]; + int ans = GetModels(Models, &count, width); + bool found = false; + if (!ans) return 0; - // try each model and get result - for (int i = 0; i < count; i++){ - /*if (found) { - free(Models[i]); - continue; - }*/ - // round up to # of characters in this model's crc - crcChars = ((width[i]+7)/8)*2; - // can't test a model that has more crc digits than our data - if (crcChars >= dataLen) - continue; - memset(result, 0, 30); - char *inCRC = calloc(crcChars+1, sizeof(char)); - memcpy(inCRC, inHexStr+(dataLen-crcChars), crcChars); + // try each model and get result + for (int i = 0; i < count; i++){ + /*if (found) { + free(Models[i]); + continue; + }*/ + // round up to # of characters in this model's crc + crcChars = ((width[i]+7)/8)*2; + // can't test a model that has more crc digits than our data + if (crcChars >= dataLen) + continue; + memset(result, 0, 30); + char *inCRC = calloc(crcChars+1, sizeof(char)); + memcpy(inCRC, inHexStr+(dataLen-crcChars), crcChars); - char *outHex = calloc(dataLen-crcChars+1, sizeof(char)); - memcpy(outHex, inHexStr, dataLen-crcChars); + char *outHex = calloc(dataLen-crcChars+1, sizeof(char)); + memcpy(outHex, inHexStr, dataLen-crcChars); - PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); - ans = RunModel(Models[i], outHex, false, 0, result); - if (ans) { - // test for match - if (memcmp(result, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value: %s\n", Models[i], result); - //optional - stop searching if found... - found = true; - } else { - if (crcChars > 2){ - char *swapEndian = SwapEndianStr(result, crcChars, crcChars); - if (memcmp(swapEndian, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value endian swapped: %s\n", Models[i], swapEndian); - // optional - stop searching if found... - found = true; - } - free(swapEndian); - } - } - } - ans = RunModel(Models[i], outHex, true, 0, revResult); - if (ans) { - // test for match - if (memcmp(revResult, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value: %s\n", Models[i], revResult); - // optional - stop searching if found... - found = true; - } else { - if (crcChars > 2){ - char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars); - if (memcmp(swapEndian, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value endian swapped: %s\n", Models[i], swapEndian); - // optional - stop searching if found... - found = true; - } - free(swapEndian); - } - } - } - free(inCRC); - free(outHex); - free(Models[i]); - } + PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); + ans = RunModel(Models[i], outHex, false, 0, result); + if (ans) { + // test for match + if (memcmp(result, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value: %s\n", Models[i], result); + //optional - stop searching if found... + found = true; + } else { + if (crcChars > 2){ + char *swapEndian = SwapEndianStr(result, crcChars, crcChars); + if (memcmp(swapEndian, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value endian swapped: %s\n", Models[i], swapEndian); + // optional - stop searching if found... + found = true; + } + free(swapEndian); + } + } + } + ans = RunModel(Models[i], outHex, true, 0, revResult); + if (ans) { + // test for match + if (memcmp(revResult, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value: %s\n", Models[i], revResult); + // optional - stop searching if found... + found = true; + } else { + if (crcChars > 2){ + char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars); + if (memcmp(swapEndian, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value endian swapped: %s\n", Models[i], swapEndian); + // optional - stop searching if found... + found = true; + } + free(swapEndian); + } + } + } + free(inCRC); + free(outHex); + free(Models[i]); + } - if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); - return 1; + if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); + return 1; } \ No newline at end of file diff --git a/client/cmddata.c b/client/cmddata.c index 45bce9c9c..9753701e5 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -18,267 +18,267 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); int usage_data_printdemodbuf(void){ - PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); - PrintAndLogEx(NORMAL, " o enter offset in # of bits"); - PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); + PrintAndLogEx(NORMAL, " o enter offset in # of bits"); + PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); + return 0; } int usage_data_manrawdecode(void){ - PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); - PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); - PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " [invert] invert output"); - PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); + PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); + PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); + PrintAndLogEx(NORMAL, " [invert] invert output"); + PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); + return 0; } int usage_data_biphaserawdecode(void){ - PrintAndLogEx(NORMAL, "Usage: data biphaserawdecode [offset] [invert] [maxErr]"); - PrintAndLogEx(NORMAL, " Converts 10 or 01 to 1 and 11 or 00 to 0"); - PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position"); - PrintAndLogEx(NORMAL, " [invert <0|1>], set to 1 to invert output"); - PrintAndLogEx(NORMAL, " [maxErr int], set max errors tolerated - default=20"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data biphaserawdecode = decode biphase bitstream from the demodbuffer"); - PrintAndLogEx(NORMAL, " Example: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data biphaserawdecode [offset] [invert] [maxErr]"); + PrintAndLogEx(NORMAL, " Converts 10 or 01 to 1 and 11 or 00 to 0"); + PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); + PrintAndLogEx(NORMAL, " --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position"); + PrintAndLogEx(NORMAL, " [invert <0|1>], set to 1 to invert output"); + PrintAndLogEx(NORMAL, " [maxErr int], set max errors tolerated - default=20"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data biphaserawdecode = decode biphase bitstream from the demodbuffer"); + PrintAndLogEx(NORMAL, " Example: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output"); + return 0; } int usage_data_rawdemod(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); - PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); - PrintAndLogEx(NORMAL, " 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); - PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); - PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod fs h = print help specific to fsk demod"); - PrintAndLogEx(NORMAL, " : data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); + PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); + PrintAndLogEx(NORMAL, " 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); + PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); + PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod fs h = print help specific to fsk demod"); + PrintAndLogEx(NORMAL, " : data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); + return 0; } int usage_data_rawdemod_am(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]"); - PrintAndLogEx(NORMAL, " ['s'] optional, check for Sequence Terminator"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]"); + PrintAndLogEx(NORMAL, " ['s'] optional, check for Sequence Terminator"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); + PrintAndLogEx(NORMAL, " , 1 to invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); + PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); + PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + return 0; } int usage_data_rawdemod_ab(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] "); - PrintAndLogEx(NORMAL, " [offset], offset to begin biphase, default=0"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, " NOTE: can be entered as second or third argument"); - PrintAndLogEx(NORMAL, " NOTE: can be entered as first, second or last argument"); - PrintAndLogEx(NORMAL, " NOTE: any other arg must have previous args set to work"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] "); + PrintAndLogEx(NORMAL, " [offset], offset to begin biphase, default=0"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); + PrintAndLogEx(NORMAL, " , 1 to invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); + PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); + PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); + PrintAndLogEx(NORMAL, " NOTE: can be entered as second or third argument"); + PrintAndLogEx(NORMAL, " NOTE: can be entered as first, second or last argument"); + PrintAndLogEx(NORMAL, " NOTE: any other arg must have previous args set to work"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + return 0; } int usage_data_rawdemod_ar(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod ar = demod an ask tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); + PrintAndLogEx(NORMAL, " , 1 to invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); + PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); + PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod ar = demod an ask tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + return 0; } int usage_data_rawdemod_fs(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod fs [clock] [fchigh] [fclow]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, omit for autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output, can be used even if the clock is omitted"); - PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect"); - PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod fs [clock] [fchigh] [fclow]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, omit for autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output, can be used even if the clock is omitted"); + PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect"); + PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); + return 0; } int usage_data_rawdemod_nr(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod nr [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod nr [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + return 0; } int usage_data_rawdemod_p1(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod p1 [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod p1 = demod a psk1 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod p1 [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod p1 = demod a psk1 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + return 0; } int usage_data_rawdemod_p2(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod p2 [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod p2 [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); + return 0; } int usage_data_autocorr(void) { - PrintAndLogEx(NORMAL, "Autocorrelate is used to detect repeating sequences. We use it as detection of length in bits a message inside the signal is"); - PrintAndLogEx(NORMAL, "Usage: data autocorr w [g]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " w window length for correlation - default = 4000"); - PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)"); - return 0; + PrintAndLogEx(NORMAL, "Autocorrelate is used to detect repeating sequences. We use it as detection of length in bits a message inside the signal is"); + PrintAndLogEx(NORMAL, "Usage: data autocorr w [g]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " w window length for correlation - default = 4000"); + PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)"); + return 0; } int usage_data_undecimate(void){ - PrintAndLogEx(NORMAL, "Usage: data undec [factor]"); - PrintAndLogEx(NORMAL, "This function performs un-decimation, by repeating each sample N times"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " factor The number of times to repeat each sample.[default:2]"); - PrintAndLogEx(NORMAL, "Example: 'data undec 3'"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data undec [factor]"); + PrintAndLogEx(NORMAL, "This function performs un-decimation, by repeating each sample N times"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " factor The number of times to repeat each sample.[default:2]"); + PrintAndLogEx(NORMAL, "Example: 'data undec 3'"); + return 0; } int usage_data_detectclock(void){ - PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] "); - PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of"); - PrintAndLogEx(NORMAL, " , specify the clock (optional - to get best start position only)"); - PrintAndLogEx(NORMAL, " 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock f = detect the clock of an fsk modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock p = detect the clock of an psk modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] "); + PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of"); + PrintAndLogEx(NORMAL, " , specify the clock (optional - to get best start position only)"); + PrintAndLogEx(NORMAL, " 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer"); + PrintAndLogEx(NORMAL, " data detectclock f = detect the clock of an fsk modulated wave in the GraphBuffer"); + PrintAndLogEx(NORMAL, " data detectclock p = detect the clock of an psk modulated wave in the GraphBuffer"); + PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer"); + return 0; } int usage_data_hex2bin(void){ - PrintAndLogEx(NORMAL, "Usage: data hex2bin "); - PrintAndLogEx(NORMAL, " This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data hex2bin "); + PrintAndLogEx(NORMAL, " This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); + return 0; } int usage_data_bin2hex(void){ - PrintAndLogEx(NORMAL, "Usage: data bin2hex "); - PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data bin2hex "); + PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); + return 0; } int usage_data_buffclear(void){ - PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside"); - PrintAndLogEx(NORMAL, "Usage: data buffclear [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - return 0; + PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside"); + PrintAndLogEx(NORMAL, "Usage: data buffclear [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + return 0; } int usage_data_fsktonrz() { - PrintAndLogEx(NORMAL, "Usage: data fsktonrz c l f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)"); - PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)"); - PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data fsktonrz c l f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)"); + PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)"); + PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)"); + return 0; } //set the demod buffer with given array of binary (one bit per byte) //by marshmellow void setDemodBuf(uint8_t *buf, size_t size, size_t start_idx) { - if (buf == NULL) return; + if (buf == NULL) return; - if ( size > MAX_DEMOD_BUF_LEN - start_idx) - size = MAX_DEMOD_BUF_LEN - start_idx; + if ( size > MAX_DEMOD_BUF_LEN - start_idx) + size = MAX_DEMOD_BUF_LEN - start_idx; - for (size_t i = 0; i < size; i++) - DemodBuffer[i] = buf[start_idx++]; + for (size_t i = 0; i < size; i++) + DemodBuffer[i] = buf[start_idx++]; - DemodBufferLen = size; + DemodBufferLen = size; } bool getDemodBuf(uint8_t *buf, size_t *size) { - if (buf == NULL) return false; - if (size == NULL) return false; - if (*size == 0) return false; + if (buf == NULL) return false; + if (size == NULL) return false; + if (*size == 0) return false; - *size = (*size > DemodBufferLen) ? DemodBufferLen : *size; + *size = (*size > DemodBufferLen) ? DemodBufferLen : *size; - memcpy(buf, DemodBuffer, *size); - return true; + memcpy(buf, DemodBuffer, *size); + return true; } // include // Root mean square double rms(double *v, size_t n) { - double sum = 0.0; - for(size_t i = 0; i < n; i++) - sum += v[i] * v[i]; - return sqrt(sum / n); + double sum = 0.0; + for(size_t i = 0; i < n; i++) + sum += v[i] * v[i]; + return sqrt(sum / n); } int cmp_int( const void *a, const void *b) { if (*(const int *)a < *(const int *)b) - return -1; + return -1; else - return *(const int *)a > *(const int *)b; + return *(const int *)a > *(const int *)b; } int cmp_uint8( const void *a, const void *b) { if (*(const uint8_t *)a < *(const uint8_t *)b) - return -1; + return -1; else - return *(const uint8_t *)a > *(const uint8_t *)b; + return *(const uint8_t *)a > *(const uint8_t *)b; } // Median of a array of values double median_int( int *src, size_t size ) { @@ -291,23 +291,23 @@ double median_uint8( uint8_t *src, size_t size ) { } // function to compute mean for a series static double compute_mean(const int *data, size_t n) { - double mean = 0.0; - for (size_t i=0; i < n; i++) - mean += data[i]; - mean /= n; - return mean; + double mean = 0.0; + for (size_t i=0; i < n; i++) + mean += data[i]; + mean /= n; + return mean; } // function to compute variance for a series static double compute_variance(const int *data, size_t n) { - double variance = 0.0; - double mean = compute_mean(data, n); + double variance = 0.0; + double mean = compute_mean(data, n); - for (size_t i=0; i < n; i++) - variance += pow(( data[i] - mean), 2.0); + for (size_t i=0; i < n; i++) + variance += pow(( data[i] - mean), 2.0); - variance /= n; - return variance; + variance /= n; + return variance; } // Function to compute autocorrelation for a series @@ -315,133 +315,133 @@ static double compute_variance(const int *data, size_t n) { // - Corrected divide by n to divide (n - lag) from Tobias Mueller /* static double compute_autoc(const int *data, size_t n, int lag) { - double autocv = 0.0; // Autocovariance value - double ac_value; // Computed autocorrelation value to be returned - double variance; // Computed variance - double mean; + double autocv = 0.0; // Autocovariance value + double ac_value; // Computed autocorrelation value to be returned + double variance; // Computed variance + double mean; - mean = compute_mean(data, n); - variance = compute_variance(data, n); + mean = compute_mean(data, n); + variance = compute_variance(data, n); - for (size_t i=0; i < (n - lag); i++) - autocv += (data[i] - mean) * (data[i+lag] - mean); + for (size_t i=0; i < (n - lag); i++) + autocv += (data[i] - mean) * (data[i+lag] - mean); - autocv = (1.0 / (n - lag)) * autocv; + autocv = (1.0 / (n - lag)) * autocv; - // Autocorrelation is autocovariance divided by variance - ac_value = autocv / variance; - return ac_value; + // Autocorrelation is autocovariance divided by variance + ac_value = autocv / variance; + return ac_value; } */ // option '1' to save DemodBuffer any other to restore void save_restoreDB(uint8_t saveOpt) { - static uint8_t SavedDB[MAX_DEMOD_BUF_LEN]; - static size_t SavedDBlen; - static bool DB_Saved = false; - static size_t savedDemodStartIdx = 0; - static int savedDemodClock = 0; + static uint8_t SavedDB[MAX_DEMOD_BUF_LEN]; + static size_t SavedDBlen; + static bool DB_Saved = false; + static size_t savedDemodStartIdx = 0; + static int savedDemodClock = 0; - if (saveOpt == GRAPH_SAVE) { //save + if (saveOpt == GRAPH_SAVE) { //save - memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer)); - SavedDBlen = DemodBufferLen; - DB_Saved = true; - savedDemodStartIdx = g_DemodStartIdx; - savedDemodClock = g_DemodClock; - } else if (DB_Saved) { //restore + memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer)); + SavedDBlen = DemodBufferLen; + DB_Saved = true; + savedDemodStartIdx = g_DemodStartIdx; + savedDemodClock = g_DemodClock; + } else if (DB_Saved) { //restore - memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); - DemodBufferLen = SavedDBlen; - g_DemodClock = savedDemodClock; - g_DemodStartIdx = savedDemodStartIdx; - } + memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); + DemodBufferLen = SavedDBlen; + g_DemodClock = savedDemodClock; + g_DemodStartIdx = savedDemodStartIdx; + } } int CmdSetDebugMode(const char *Cmd) { - int demod = 0; - sscanf(Cmd, "%i", &demod); - g_debugMode = (uint8_t)demod; - return 1; + int demod = 0; + sscanf(Cmd, "%i", &demod); + g_debugMode = (uint8_t)demod; + return 1; } //by marshmellow // max output to 512 bits if we have more - should be plenty void printDemodBuff(void) { - int len = DemodBufferLen; - if (len < 1) { - PrintAndLogEx(NORMAL, "(printDemodBuff) no bits found in demod buffer"); - return; - } - if (len > 512) len = 512; + int len = DemodBufferLen; + if (len < 1) { + PrintAndLogEx(NORMAL, "(printDemodBuff) no bits found in demod buffer"); + return; + } + if (len > 512) len = 512; - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 16) ); + PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 16) ); } int CmdPrintDemodBuff(const char *Cmd) { - char hex[512] = {0x00}; - bool hexMode = false; - bool errors = false; - uint32_t offset = 0; - uint32_t length = 512; - char cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_printdemodbuf(); - case 'x': - hexMode = true; - cmdp++; - break; - case 'o': - offset = param_get32ex(Cmd, cmdp+1, 0, 10); - if (!offset) errors = true; - cmdp += 2; - break; - case 'l': - length = param_get32ex(Cmd, cmdp+1, 512, 10); - if (!length) errors = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_data_printdemodbuf(); + char hex[512] = {0x00}; + bool hexMode = false; + bool errors = false; + uint32_t offset = 0; + uint32_t length = 512; + char cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_data_printdemodbuf(); + case 'x': + hexMode = true; + cmdp++; + break; + case 'o': + offset = param_get32ex(Cmd, cmdp+1, 0, 10); + if (!offset) errors = true; + cmdp += 2; + break; + case 'l': + length = param_get32ex(Cmd, cmdp+1, 512, 10); + if (!length) errors = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors) return usage_data_printdemodbuf(); - if (DemodBufferLen == 0) { - PrintAndLogEx(NORMAL, "Demodbuffer is empty"); - return 0; - } - length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length; - int numBits = (length) & 0x00FFC; //make sure we don't exceed our string + if (DemodBufferLen == 0) { + PrintAndLogEx(NORMAL, "Demodbuffer is empty"); + return 0; + } + length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length; + int numBits = (length) & 0x00FFC; //make sure we don't exceed our string - if (hexMode){ - char *buf = (char *) (DemodBuffer + offset); - numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; - numBits = binarraytohex(hex, buf, numBits); - if (numBits == 0) { - return 0; - } - PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); - } else { - PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset, numBits, 16)); - } - return 1; + if (hexMode){ + char *buf = (char *) (DemodBuffer + offset); + numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; + numBits = binarraytohex(hex, buf, numBits); + if (numBits == 0) { + return 0; + } + PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); + } else { + PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset, numBits, 16)); + } + return 1; } //by marshmellow //this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer int CmdGetBitStream(const char *Cmd) { - CmdHpf(Cmd); - for (uint32_t i = 0; i < GraphTraceLen; i++) - GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; + CmdHpf(Cmd); + for (uint32_t i = 0; i < GraphTraceLen; i++) + GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } //by marshmellow @@ -451,94 +451,94 @@ int CmdGetBitStream(const char *Cmd) { //emSearch will auto search for EM410x format in bitstream //askType switches decode: ask/raw = 0, ask/manchester = 1 int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { - int invert = 0; - int clk = 0; - int maxErr = 100; - int maxLen = 0; - uint8_t askamp = 0; - char amp = tolower(param_getchar(Cmd, 0)); - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + int invert = 0; + int clk = 0; + int maxErr = 100; + int maxLen = 0; + uint8_t askamp = 0; + char amp = tolower(param_getchar(Cmd, 0)); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &); + sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &); - if (!maxLen) maxLen = BIGBUF_SIZE; + if (!maxLen) maxLen = BIGBUF_SIZE; - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); - return 0; - } + if (invert != 0 && invert != 1) { + PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); + return 0; + } - if (clk == 1) { - invert = 1; - clk = 0; - } + if (clk == 1) { + invert = 1; + clk = 0; + } - size_t BitLen = getFromGraphBuf(bits); + size_t BitLen = getFromGraphBuf(bits); - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); - if (BitLen < 255) return 0; + if (BitLen < 255) return 0; - if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; + if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; - int foundclk = 0; - //amp before ST check - if (amp == 'a') - askAmp(bits, BitLen); + int foundclk = 0; + //amp before ST check + if (amp == 'a') + askAmp(bits, BitLen); - bool st = false; - size_t ststart = 0, stend = 0; - if (*stCheck) - st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); + bool st = false; + size_t ststart = 0, stend = 0; + if (*stCheck) + st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); - if (st) { - *stCheck = st; - clk = (clk == 0) ? foundclk : clk; - CursorCPos = ststart; - CursorDPos = stend; - if (verbose || g_debugMode) - PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); - } + if (st) { + *stCheck = st; + clk = (clk == 0) ? foundclk : clk; + CursorCPos = ststart; + CursorDPos = stend; + if (verbose || g_debugMode) + PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); + } - int startIdx = 0; - int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); + int startIdx = 0; + int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); - if (errCnt < 0 || BitLen < 16){ //if fatal error (or -1) - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%d, clock:%d", errCnt, (invert)?'Y':'N', BitLen, clk); - return 0; - } + if (errCnt < 0 || BitLen < 16){ //if fatal error (or -1) + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%d, clock:%d", errCnt, (invert)?'Y':'N', BitLen, clk); + return 0; + } - if (errCnt > maxErr){ - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%d, clock:%d", errCnt, BitLen, clk); - return 0; - } + if (errCnt > maxErr){ + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%d, clock:%d", errCnt, BitLen, clk); + return 0; + } - if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); - //output - setDemodBuf(bits, BitLen, 0); - setClockGrid(clk, startIdx); + //output + setDemodBuf(bits, BitLen, 0); + setClockGrid(clk, startIdx); - if (verbose || g_debugMode){ - if (errCnt > 0) - PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); - if (askType) - PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:",clk); - else - PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:",clk); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - } - uint64_t lo = 0; - uint32_t hi = 0; - if (emSearch) - AskEm410xDecode(true, &hi, &lo); + if (verbose || g_debugMode){ + if (errCnt > 0) + PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); + if (askType) + PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:",clk); + else + PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:",clk); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + } + uint64_t lo = 0; + uint32_t hi = 0; + if (emSearch) + AskEm410xDecode(true, &hi, &lo); - return 1; + return 1; } int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) { - bool st = false; - return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st); + bool st = false; + return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st); } //by marshmellow @@ -547,68 +547,68 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) { //prints binary found and saves in graphbuffer for further commands int Cmdaskmandemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am(); - bool st = true; - if (Cmd[0] == 's') - return ASKDemod_ext(Cmd++, true, true, 1, &st); - else if (Cmd[1] == 's') - return ASKDemod_ext(Cmd += 2, true, true, 1, &st); + bool st = true; + if (Cmd[0] == 's') + return ASKDemod_ext(Cmd++, true, true, 1, &st); + else if (Cmd[1] == 's') + return ASKDemod_ext(Cmd += 2, true, true, 1, &st); - return ASKDemod(Cmd, true, true, 1); + return ASKDemod(Cmd, true, true, 1); } //by marshmellow //manchester decode //stricktly take 10 and 01 and convert to 0 and 1 int Cmdmandecoderaw(const char *Cmd) { - size_t size = 0; - int high = 0, low = 0; - int i = 0, errCnt = 0, invert = 0, maxErr = 20; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode(); + size_t size = 0; + int high = 0, low = 0; + int i = 0, errCnt = 0, invert = 0, maxErr = 20; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode(); - if (DemodBufferLen == 0) return 0; + if (DemodBufferLen == 0) return 0; - uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; + uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - for (; i < DemodBufferLen; ++i){ - if (DemodBuffer[i] > high) - high = DemodBuffer[i]; - else if(DemodBuffer[i] < low) - low = DemodBuffer[i]; - bits[i] = DemodBuffer[i]; - } + for (; i < DemodBufferLen; ++i){ + if (DemodBuffer[i] > high) + high = DemodBuffer[i]; + else if(DemodBuffer[i] < low) + low = DemodBuffer[i]; + bits[i] = DemodBuffer[i]; + } - if (high > 7 || low < 0 ){ - PrintAndLogEx(WARNING, "Error: please raw demod the wave first then manchester raw decode"); - return 0; - } + if (high > 7 || low < 0 ){ + PrintAndLogEx(WARNING, "Error: please raw demod the wave first then manchester raw decode"); + return 0; + } - sscanf(Cmd, "%i %i", &invert, &maxErr); - size = i; - uint8_t alignPos = 0; - errCnt = manrawdecode(bits, &size, invert, &alignPos); - if (errCnt >= maxErr){ - PrintAndLogEx(WARNING, "Too many errors: %d",errCnt); - return 0; - } + sscanf(Cmd, "%i %i", &invert, &maxErr); + size = i; + uint8_t alignPos = 0; + errCnt = manrawdecode(bits, &size, invert, &alignPos); + if (errCnt >= maxErr){ + PrintAndLogEx(WARNING, "Too many errors: %d",errCnt); + return 0; + } - PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:",errCnt); - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); + PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:",errCnt); + PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); - if (errCnt == 0){ - uint64_t id = 0; - uint32_t hi = 0; - size_t idx = 0; - if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1){ - //need to adjust to set bitstream back to manchester encoded data - //setDemodBuf(bits, size, idx); - printEM410x(hi, id); - } - } - return 1; + if (errCnt == 0){ + uint64_t id = 0; + uint32_t hi = 0; + size_t idx = 0; + if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1){ + //need to adjust to set bitstream back to manchester encoded data + //setDemodBuf(bits, size, idx); + printEM410x(hi, id); + } + } + return 1; } //by marshmellow @@ -618,269 +618,269 @@ int Cmdmandecoderaw(const char *Cmd) { // and "invert" default = 0 if 1 it will invert output // the argument offset allows us to manually shift if the output is incorrect - [EDIT: now auto detects] int CmdBiphaseDecodeRaw(const char *Cmd) { - size_t size = 0; - int offset = 0, invert = 0, maxErr = 20, errCnt = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 3 || cmdp == 'h') return usage_data_biphaserawdecode(); + size_t size = 0; + int offset = 0, invert = 0, maxErr = 20, errCnt = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 3 || cmdp == 'h') return usage_data_biphaserawdecode(); - sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); - if (DemodBufferLen == 0){ - PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); - return 0; - } + sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); + if (DemodBufferLen == 0){ + PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); + return 0; + } - uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - size = sizeof(bits); - if ( !getDemodBuf(bits, &size) ) return 0; + uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; + size = sizeof(bits); + if ( !getDemodBuf(bits, &size) ) return 0; - errCnt = BiphaseRawDecode(bits, &size, &offset, invert); - if (errCnt < 0){ - PrintAndLogEx(WARNING, "Error during decode:%d", errCnt); - return 0; - } - if (errCnt > maxErr){ - PrintAndLogEx(WARNING, "Too many errors attempting to decode: %d",errCnt); - return 0; - } + errCnt = BiphaseRawDecode(bits, &size, &offset, invert); + if (errCnt < 0){ + PrintAndLogEx(WARNING, "Error during decode:%d", errCnt); + return 0; + } + if (errCnt > maxErr){ + PrintAndLogEx(WARNING, "Too many errors attempting to decode: %d",errCnt); + return 0; + } - if (errCnt > 0) - PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d",errCnt); + if (errCnt > 0) + PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d",errCnt); - PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert); - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); + PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert); + PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); - //remove first bit from raw demod - if (offset) - setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); + //remove first bit from raw demod + if (offset) + setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); - setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2); - return 1; + setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2); + return 1; } //by marshmellow // - ASK Demod then Biphase decode GraphBuffer samples int ASKbiphaseDemod(const char *Cmd, bool verbose) { - //ask raw demod GraphBuffer first - int offset=0, clk=0, invert=0, maxErr=0; - sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); + //ask raw demod GraphBuffer first + int offset=0, clk=0, invert=0, maxErr=0; + sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); - uint8_t BitStream[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(BitStream); - if (size == 0 ) { - PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); - return 0; - } - int startIdx = 0; - //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer - int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); - if ( errCnt < 0 || errCnt > maxErr ) { - PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); - return 0; - } + uint8_t BitStream[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(BitStream); + if (size == 0 ) { + PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); + return 0; + } + int startIdx = 0; + //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer + int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); + if ( errCnt < 0 || errCnt > maxErr ) { + PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); + return 0; + } - //attempt to Biphase decode BitStream - errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert); - if (errCnt < 0){ - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt); - return 0; - } - if (errCnt > maxErr) { - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt); - return 0; - } - //success set DemodBuffer and return - setDemodBuf(BitStream, size, 0); - setClockGrid(clk, startIdx + clk*offset/2); - if (g_debugMode || verbose){ - PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt); - printDemodBuff(); - } - return 1; + //attempt to Biphase decode BitStream + errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert); + if (errCnt < 0){ + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt); + return 0; + } + if (errCnt > maxErr) { + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt); + return 0; + } + //success set DemodBuffer and return + setDemodBuf(BitStream, size, 0); + setClockGrid(clk, startIdx + clk*offset/2); + if (g_debugMode || verbose){ + PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt); + printDemodBuff(); + } + return 1; } //by marshmellow - see ASKbiphaseDemod int Cmdaskbiphdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); - return ASKbiphaseDemod(Cmd, true); + return ASKbiphaseDemod(Cmd, true); } //by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); - return ASKDemod(Cmd, true, false, 0); + return ASKDemod(Cmd, true, false, 0); } int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose) { - // sanity check - if ( window > len ) window = len; + // sanity check + if ( window > len ) window = len; - if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); + if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); - //test - double autocv = 0.0; // Autocovariance value - double ac_value; // Computed autocorrelation value to be returned - double variance; // Computed variance - double mean; - size_t correlation = 0; - int lastmax = 0; + //test + double autocv = 0.0; // Autocovariance value + double ac_value; // Computed autocorrelation value to be returned + double variance; // Computed variance + double mean; + size_t correlation = 0; + int lastmax = 0; - // in, len, 4000 - mean = compute_mean(in, len); - variance = compute_variance(in, len); + // in, len, 4000 + mean = compute_mean(in, len); + variance = compute_variance(in, len); - static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; + static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; - for (int i = 0; i < len - window; ++i) { + for (int i = 0; i < len - window; ++i) { - for (size_t j=0; j < (len - i); j++) { - autocv += (in[j] - mean) * (in[j+i] - mean); - } - autocv = (1.0 / (len - i)) * autocv; + for (size_t j=0; j < (len - i); j++) { + autocv += (in[j] - mean) * (in[j+i] - mean); + } + autocv = (1.0 / (len - i)) * autocv; - CorrelBuffer[i] = autocv; + CorrelBuffer[i] = autocv; - // Autocorrelation is autocovariance divided by variance - ac_value = autocv / variance; + // Autocorrelation is autocovariance divided by variance + ac_value = autocv / variance; - // keep track of which distance is repeating. - if ( ac_value > 1) { - correlation = i-lastmax; - lastmax = i; - } - } + // keep track of which distance is repeating. + if ( ac_value > 1) { + correlation = i-lastmax; + lastmax = i; + } + } - // - int hi = 0, idx = 0; - int distance = 0, hi_1 = 0, idx_1 = 0; - for (int i = 0; i <= len; ++i){ - if ( CorrelBuffer[i] > hi) { - hi = CorrelBuffer[i]; - idx = i; - } - } + // + int hi = 0, idx = 0; + int distance = 0, hi_1 = 0, idx_1 = 0; + for (int i = 0; i <= len; ++i){ + if ( CorrelBuffer[i] > hi) { + hi = CorrelBuffer[i]; + idx = i; + } + } - for (int i = idx+1; i <= window; ++i){ - if ( CorrelBuffer[i] > hi_1 ) { - hi_1 = CorrelBuffer[i]; - idx_1 = i; - } - } + for (int i = idx+1; i <= window; ++i){ + if ( CorrelBuffer[i] > hi_1 ) { + hi_1 = CorrelBuffer[i]; + idx_1 = i; + } + } - int foo = ABS(hi-hi_1); - int bar = (int)((int)((hi+hi_1) / 2) * 0.03); - if ( verbose && foo < bar ) { - distance = idx_1 - idx; - PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); - } else if (verbose && ( correlation > 1 ) ) { - PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); - } else { - PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); - } + int foo = ABS(hi-hi_1); + int bar = (int)((int)((hi+hi_1) / 2) * 0.03); + if ( verbose && foo < bar ) { + distance = idx_1 - idx; + PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); + } else if (verbose && ( correlation > 1 ) ) { + PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); + } else { + PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); + } - int retval = correlation; - if (SaveGrph) { - //GraphTraceLen = GraphTraceLen - window; - memcpy(out, CorrelBuffer, len * sizeof(int)); - if ( distance > 0) { - setClockGrid(distance, idx); - retval = distance; - } - else - setClockGrid(correlation, idx); + int retval = correlation; + if (SaveGrph) { + //GraphTraceLen = GraphTraceLen - window; + memcpy(out, CorrelBuffer, len * sizeof(int)); + if ( distance > 0) { + setClockGrid(distance, idx); + retval = distance; + } + else + setClockGrid(correlation, idx); - CursorCPos = idx_1; - CursorDPos = idx_1+retval; - DemodBufferLen = 0; - RepaintGraphWindow(); - } + CursorCPos = idx_1; + CursorDPos = idx_1+retval; + DemodBufferLen = 0; + RepaintGraphWindow(); + } - return retval; + return retval; } int CmdAutoCorr(const char *Cmd) { - uint32_t window = 4000; - uint8_t cmdp = 0; - bool updateGrph = false; - bool errors = false; + uint32_t window = 4000; + uint8_t cmdp = 0; + bool updateGrph = false; + bool errors = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_autocorr(); - case 'g': - updateGrph = true; - cmdp++; - break; - case 'w': - window = param_get32ex(Cmd, cmdp+1, 4000, 10); - if (window >= GraphTraceLen) { - PrintAndLogEx(WARNING, "window must be smaller than trace (%d samples)", GraphTraceLen); - errors = true; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0 ) return usage_data_autocorr(); + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_data_autocorr(); + case 'g': + updateGrph = true; + cmdp++; + break; + case 'w': + window = param_get32ex(Cmd, cmdp+1, 4000, 10); + if (window >= GraphTraceLen) { + PrintAndLogEx(WARNING, "window must be smaller than trace (%d samples)", GraphTraceLen); + errors = true; + } + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0 ) return usage_data_autocorr(); - return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true); + return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true); } int CmdBitsamples(const char *Cmd) { - int cnt = 0; - uint8_t got[12288]; + int cnt = 0; + uint8_t got[12288]; - if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500 , false)) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } + if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500 , false)) { + PrintAndLogEx(WARNING, "command execution time out"); + return false; + } - for (int j = 0; j < sizeof(got); j++) { - for (int k = 0; k < 8; k++) { - if(got[j] & (1 << (7 - k))) - GraphBuffer[cnt++] = 1; - else - GraphBuffer[cnt++] = 0; - } - } - GraphTraceLen = cnt; - RepaintGraphWindow(); - return 0; + for (int j = 0; j < sizeof(got); j++) { + for (int k = 0; k < 8; k++) { + if(got[j] & (1 << (7 - k))) + GraphBuffer[cnt++] = 1; + else + GraphBuffer[cnt++] = 0; + } + } + GraphTraceLen = cnt; + RepaintGraphWindow(); + return 0; } int CmdBuffClear(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_data_buffclear(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_data_buffclear(); - UsbCommand c = {CMD_BUFF_CLEAR, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - ClearGraph(true); - return 0; + UsbCommand c = {CMD_BUFF_CLEAR, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + ClearGraph(true); + return 0; } int CmdDec(const char *Cmd) { - for (int i = 0; i < (GraphTraceLen / 2); ++i) - GraphBuffer[i] = GraphBuffer[i * 2]; - GraphTraceLen /= 2; - PrintAndLogEx(NORMAL, "decimated by 2"); - RepaintGraphWindow(); - return 0; + for (int i = 0; i < (GraphTraceLen / 2); ++i) + GraphBuffer[i] = GraphBuffer[i * 2]; + GraphTraceLen /= 2; + PrintAndLogEx(NORMAL, "decimated by 2"); + RepaintGraphWindow(); + return 0; } /** * Undecimate - I'd call it 'interpolate', but we'll save that @@ -891,62 +891,62 @@ int CmdDec(const char *Cmd) */ int CmdUndec(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_data_undecimate(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_data_undecimate(); - uint8_t factor = param_get8ex(Cmd, 0, 2, 10); + uint8_t factor = param_get8ex(Cmd, 0, 2, 10); - //We have memory, don't we? - int swap[MAX_GRAPH_TRACE_LEN] = {0}; - uint32_t g_index = 0, s_index = 0; - while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) - { - int count = 0; - for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++) - swap[s_index+count] = GraphBuffer[g_index]; - s_index += count; - g_index++; - } + //We have memory, don't we? + int swap[MAX_GRAPH_TRACE_LEN] = {0}; + uint32_t g_index = 0, s_index = 0; + while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) + { + int count = 0; + for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++) + swap[s_index+count] = GraphBuffer[g_index]; + s_index += count; + g_index++; + } - memcpy(GraphBuffer, swap, s_index * sizeof(int)); - GraphTraceLen = s_index; - RepaintGraphWindow(); - return 0; + memcpy(GraphBuffer, swap, s_index * sizeof(int)); + GraphTraceLen = s_index; + RepaintGraphWindow(); + return 0; } //by marshmellow //shift graph zero up or down based on input + or - int CmdGraphShiftZero(const char *Cmd) { - int shift = 0, shiftedVal = 0; - //set options from parameters entered with the command - sscanf(Cmd, "%i", &shift); + int shift = 0, shiftedVal = 0; + //set options from parameters entered with the command + sscanf(Cmd, "%i", &shift); - for(int i = 0; i < GraphTraceLen; i++){ - if ( i+shift >= GraphTraceLen) - shiftedVal = GraphBuffer[i]; - else - shiftedVal = GraphBuffer[i] + shift; + for(int i = 0; i < GraphTraceLen; i++){ + if ( i+shift >= GraphTraceLen) + shiftedVal = GraphBuffer[i]; + else + shiftedVal = GraphBuffer[i] + shift; - if (shiftedVal > 127) - shiftedVal = 127; - else if (shiftedVal < -127) - shiftedVal = -127; - GraphBuffer[i] = shiftedVal; - } - CmdNorm(""); - return 0; + if (shiftedVal > 127) + shiftedVal = 127; + else if (shiftedVal < -127) + shiftedVal = -127; + GraphBuffer[i] = shiftedVal; + } + CmdNorm(""); + return 0; } int AskEdgeDetect(const int *in, int *out, int len, int threshold) { - int last = 0; - for(int i = 1; i= threshold) //large jump up - last = 127; - else if (in[i] - in[i-1] <= -1 * threshold) //large jump down - last = -127; - out[i-1] = last; - } - return 0; + int last = 0; + for(int i = 1; i= threshold) //large jump up + last = 127; + else if (in[i] - in[i-1] <= -1 * threshold) //large jump down + last = -127; + out[i-1] = last; + } + return 0; } //by marshmellow @@ -954,69 +954,69 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold) { //similar to dirtheshold, threshold commands //takes a threshold length which is the measured length between two samples then determines an edge int CmdAskEdgeDetect(const char *Cmd) { - int thresLen = 25; - int ans = 0; - sscanf(Cmd, "%i", &thresLen); + int thresLen = 25; + int ans = 0; + sscanf(Cmd, "%i", &thresLen); - ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen); - RepaintGraphWindow(); - return ans; + ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen); + RepaintGraphWindow(); + return ans; } /* Print our clock rate */ // uses data from graphbuffer // adjusted to take char parameter for type of modulation to find the clock - by marshmellow. int CmdDetectClockRate(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h') - return usage_data_detectclock(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h') + return usage_data_detectclock(); - int clock = 0; - switch ( cmdp ) { - case 'a' : - clock = GetAskClock(Cmd+1, true); - break; - case 'f' : - clock = GetFskClock("", true); - break; - case 'n' : - clock = GetNrzClock("", true); - break; - case 'p' : - clock = GetPskClock("", true); - break; - default : - PrintAndLogEx(NORMAL, "Please specify a valid modulation to detect the clock of - see option h for help"); - break; - } - RepaintGraphWindow(); - return clock; + int clock = 0; + switch ( cmdp ) { + case 'a' : + clock = GetAskClock(Cmd+1, true); + break; + case 'f' : + clock = GetFskClock("", true); + break; + case 'n' : + clock = GetNrzClock("", true); + break; + case 'p' : + clock = GetPskClock("", true); + break; + default : + PrintAndLogEx(NORMAL, "Please specify a valid modulation to detect the clock of - see option h for help"); + break; + } + RepaintGraphWindow(); + return clock; } char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) { - static char fType[8]; - memset(fType, 0x00, 8); - char *fskType = fType; + static char fType[8]; + memset(fType, 0x00, 8); + char *fskType = fType; - if (fchigh == 10 && fclow == 8){ + if (fchigh == 10 && fclow == 8){ - if (invert) - memcpy(fskType, "FSK2a", 5); - else - memcpy(fskType, "FSK2", 4); + if (invert) + memcpy(fskType, "FSK2a", 5); + else + memcpy(fskType, "FSK2", 4); - } else if (fchigh == 8 && fclow == 5) { + } else if (fchigh == 8 && fclow == 5) { - if (invert) - memcpy(fskType, "FSK1", 4); - else - memcpy(fskType, "FSK1a", 5); + if (invert) + memcpy(fskType, "FSK1", 4); + else + memcpy(fskType, "FSK1a", 5); - } else { - memcpy(fskType, "FSK??", 5); - } - return fskType; + } else { + memcpy(fskType, "FSK??", 5); + } + return fskType; } //by marshmellow @@ -1024,65 +1024,65 @@ char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) //takes 4 arguments - Clock, invert, fchigh, fclow //defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) int FSKrawDemod(const char *Cmd, bool verbose) { - //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint8_t rfLen, invert, fchigh, fclow; + //raw fsk demod no manchester decoding no start bit finding just get binary from wave + uint8_t rfLen, invert, fchigh, fclow; - //set defaults - //set options from parameters entered with the command - rfLen = param_get8(Cmd, 0); - invert = param_get8(Cmd, 1); - fchigh = param_get8(Cmd, 2); - fclow = param_get8(Cmd, 3); + //set defaults + //set options from parameters entered with the command + rfLen = param_get8(Cmd, 0); + invert = param_get8(Cmd, 1); + fchigh = param_get8(Cmd, 2); + fclow = param_get8(Cmd, 3); - if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { - if (rfLen == 1) { - invert = 1; //if invert option only is used - rfLen = 0; - } - } + if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { + if (rfLen == 1) { + invert = 1; //if invert option only is used + rfLen = 0; + } + } if (getSignalProperties()->isnoise) return 0; - - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(bits); - if (BitLen == 0) return 0; - //get field clock lengths - uint16_t fcs = 0; - if (!fchigh || !fclow) { - fcs = countFC(bits, BitLen, true); - if (!fcs) { - fchigh = 10; - fclow = 8; - } else { - fchigh = (fcs >> 8) & 0x00FF; - fclow = fcs & 0x00FF; - } - } - //get bit clock length - if (!rfLen) { - int firstClockEdge = 0; //todo - align grid on graph with this... - rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge); - if (!rfLen) rfLen = 50; - } - int startIdx = 0; - int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); - if (size > 0) { - setDemodBuf(bits, size, 0); - setClockGrid(rfLen, startIdx); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(bits); + if (BitLen == 0) return 0; - // Now output the bitstream to the scrollback by line of 16 bits - if (verbose || g_debugMode) { - PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow); - PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert)); - printDemodBuff(); - } - return 1; - } else { - if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); - } - return 0; + //get field clock lengths + uint16_t fcs = 0; + if (!fchigh || !fclow) { + fcs = countFC(bits, BitLen, true); + if (!fcs) { + fchigh = 10; + fclow = 8; + } else { + fchigh = (fcs >> 8) & 0x00FF; + fclow = fcs & 0x00FF; + } + } + //get bit clock length + if (!rfLen) { + int firstClockEdge = 0; //todo - align grid on graph with this... + rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge); + if (!rfLen) rfLen = 50; + } + int startIdx = 0; + int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); + if (size > 0) { + setDemodBuf(bits, size, 0); + setClockGrid(rfLen, startIdx); + + // Now output the bitstream to the scrollback by line of 16 bits + if (verbose || g_debugMode) { + PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow); + PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert)); + printDemodBuff(); + } + return 1; + } else { + if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); + } + return 0; } //by marshmellow @@ -1090,113 +1090,113 @@ int FSKrawDemod(const char *Cmd, bool verbose) { //takes 4 arguments - Clock, invert, fchigh, fclow //defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) int CmdFSKrawdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs(); - return FSKrawDemod(Cmd, true); + return FSKrawDemod(Cmd, true); } //by marshmellow //attempt to psk1 demod graph buffer int PSKDemod(const char *Cmd, bool verbose) { - int invert = 0, clk = 0, maxErr = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); - if (clk == 1) { - invert = 1; - clk = 0; - } - if (invert != 0 && invert != 1) { - if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); - return 0; - } - + int invert = 0, clk = 0, maxErr = 100; + sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); + if (clk == 1) { + invert = 1; + clk = 0; + } + if (invert != 0 && invert != 1) { + if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); + return 0; + } + if (getSignalProperties()->isnoise) return 0; - - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen == 0) return 0; - int errCnt = 0; - int startIdx = 0; - errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx); - if (errCnt > maxErr){ - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); - return 0; - } - if (errCnt < 0|| BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); - return 0; - } - if (verbose || g_debugMode){ - PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%d",clk, invert, BitLen); - if (errCnt > 0){ - PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt); - } - } - //prime demod buffer for output - setDemodBuf(BitStream, BitLen, 0); - setClockGrid(clk, startIdx); - return 1; + + uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(BitStream); + if (BitLen == 0) return 0; + int errCnt = 0; + int startIdx = 0; + errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx); + if (errCnt > maxErr){ + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); + return 0; + } + if (errCnt < 0|| BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); + return 0; + } + if (verbose || g_debugMode){ + PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%d",clk, invert, BitLen); + if (errCnt > 0){ + PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt); + } + } + //prime demod buffer for output + setDemodBuf(BitStream, BitLen, 0); + setClockGrid(clk, startIdx); + return 1; } int CmdPSKIdteck(const char *Cmd) { - if (!PSKDemod("", false)) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); - return 0; - } - size_t size = DemodBufferLen; + if (!PSKDemod("", false)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); + return 0; + } + size_t size = DemodBufferLen; - //get binary from PSK1 wave - int idx = detectIdteck(DemodBuffer, &size); - if (idx < 0){ + //get binary from PSK1 wave + int idx = detectIdteck(DemodBuffer, &size); + if (idx < 0){ - if (idx == -1) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); - else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); - else if (idx == -3) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); - else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); - else - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); + if (idx == -1) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); + else if (idx == -2) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); + else if (idx == -3) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); + else if (idx == -4) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); + else + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); - // if didn't find preamble try again inverting - if (!PSKDemod("1", false)) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); - return 0; - } - idx = detectIdteck(DemodBuffer, &size); - if (idx < 0){ + // if didn't find preamble try again inverting + if (!PSKDemod("1", false)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); + return 0; + } + idx = detectIdteck(DemodBuffer, &size); + if (idx < 0){ - if (idx == -1) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); - else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); - else if (idx == -3) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); - else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); - else - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); + if (idx == -1) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); + else if (idx == -2) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); + else if (idx == -3) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); + else if (idx == -4) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); + else + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); - return 0; - } - } - setDemodBuf(DemodBuffer, 64, idx); + return 0; + } + } + setDemodBuf(DemodBuffer, 64, idx); - //got a good demod - uint32_t id = 0; - uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); - uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + //got a good demod + uint32_t id = 0; + uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); - //parity check (TBD) - //checksum check (TBD) + //parity check (TBD) + //checksum check (TBD) - //output - PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2); - return 1; + //output + PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2); + return 1; } // by marshmellow @@ -1205,56 +1205,56 @@ int CmdPSKIdteck(const char *Cmd) { // prints binary found and saves in demodbuffer for further commands int NRZrawDemod(const char *Cmd, bool verbose) { - int errCnt = 0, clkStartIdx = 0; - int invert = 0, clk = 0, maxErr = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); - if (clk == 1){ - invert = 1; - clk = 0; - } + int errCnt = 0, clkStartIdx = 0; + int invert = 0, clk = 0, maxErr = 100; + sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); + if (clk == 1){ + invert = 1; + clk = 0; + } + + if (invert != 0 && invert != 1) { + PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); + return 0; + } - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); - return 0; - } - if (getSignalProperties()->isnoise) return 0; - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(bits); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(bits); - if (BitLen == 0) return 0; + if (BitLen == 0) return 0; - errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx); - if (errCnt > maxErr){ - PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); - return 0; - } - if (errCnt < 0 || BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) - PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); - return 0; - } - if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen); - //prime demod buffer for output - setDemodBuf(bits, BitLen, 0); - setClockGrid(clk, clkStartIdx); + errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx); + if (errCnt > maxErr){ + PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); + return 0; + } + if (errCnt < 0 || BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) + PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); + return 0; + } + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen); + //prime demod buffer for output + setDemodBuf(bits, BitLen, 0); + setClockGrid(clk, clkStartIdx); - if (errCnt > 0 && (verbose || g_debugMode)) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Errors during Demoding (shown as 7 in bit stream): %d", errCnt); - if (verbose || g_debugMode) { - PrintAndLogEx(NORMAL, "NRZ demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - } - return 1; + if (errCnt > 0 && (verbose || g_debugMode)) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Errors during Demoding (shown as 7 in bit stream): %d", errCnt); + if (verbose || g_debugMode) { + PrintAndLogEx(NORMAL, "NRZ demoded bitstream:"); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + } + return 1; } int CmdNRZrawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr(); - return NRZrawDemod(Cmd, true); + return NRZrawDemod(Cmd, true); } // by marshmellow @@ -1262,569 +1262,569 @@ int CmdNRZrawDemod(const char *Cmd) { // attempts to demodulate psk only // prints binary found and saves in demodbuffer for further commands int CmdPSK1rawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1(); - int ans = PSKDemod(Cmd, true); - //output - if (!ans){ - if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); - return 0; - } - PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - return 1; + int ans = PSKDemod(Cmd, true); + //output + if (!ans){ + if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); + return 0; + } + PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:"); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + return 1; } // by marshmellow // takes same args as cmdpsk1rawdemod int CmdPSK2rawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2(); - int ans = PSKDemod(Cmd, true); - if (!ans){ - if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); - return 0; - } - psk1TOpsk2(DemodBuffer, DemodBufferLen); - PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - return 1; + int ans = PSKDemod(Cmd, true); + if (!ans){ + if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); + return 0; + } + psk1TOpsk2(DemodBuffer, DemodBufferLen); + PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:"); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + return 1; } // by marshmellow - combines all raw demod functions into one menu command int CmdRawDemod(const char *Cmd) { - int ans = 0; + int ans = 0; - if (strlen(Cmd) > 35 || strlen(Cmd) < 2) - return usage_data_rawdemod(); + if (strlen(Cmd) > 35 || strlen(Cmd) < 2) + return usage_data_rawdemod(); - str_lower( (char *)Cmd); + str_lower( (char *)Cmd); - if (str_startswith(Cmd, "fs")) ans = CmdFSKrawdemod(Cmd+2); - else if(str_startswith(Cmd, "ab")) ans = Cmdaskbiphdemod(Cmd+2); - else if(str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd+2); - else if(str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd+2); - else if(str_startswith(Cmd, "nr")) ans = CmdNRZrawDemod(Cmd+2); - else if(str_startswith(Cmd, "p1")) ans = CmdPSK1rawDemod(Cmd+2); - else if(str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd+2); - else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure"); + if (str_startswith(Cmd, "fs")) ans = CmdFSKrawdemod(Cmd+2); + else if(str_startswith(Cmd, "ab")) ans = Cmdaskbiphdemod(Cmd+2); + else if(str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd+2); + else if(str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd+2); + else if(str_startswith(Cmd, "nr")) ans = CmdNRZrawDemod(Cmd+2); + else if(str_startswith(Cmd, "p1")) ans = CmdPSK1rawDemod(Cmd+2); + else if(str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd+2); + else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure"); - return ans; + return ans; } void setClockGrid(int clk, int offset) { - g_DemodStartIdx = offset; - g_DemodClock = clk; - PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk); + g_DemodStartIdx = offset; + g_DemodClock = clk; + PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk); - if (offset > clk) offset %= clk; - if (offset < 0) offset += clk; + if (offset > clk) offset %= clk; + if (offset < 0) offset += clk; - if (offset > GraphTraceLen || offset < 0) return; - if (clk < 8 || clk > GraphTraceLen) { - GridLocked = false; - GridOffset = 0; - PlotGridX = 0; - PlotGridXdefault = 0; - RepaintGraphWindow(); - } else { - GridLocked = true; - GridOffset = offset; - PlotGridX = clk; - PlotGridXdefault = clk; - RepaintGraphWindow(); - } + if (offset > GraphTraceLen || offset < 0) return; + if (clk < 8 || clk > GraphTraceLen) { + GridLocked = false; + GridOffset = 0; + PlotGridX = 0; + PlotGridXdefault = 0; + RepaintGraphWindow(); + } else { + GridLocked = true; + GridOffset = offset; + PlotGridX = clk; + PlotGridXdefault = clk; + RepaintGraphWindow(); + } } int CmdGrid(const char *Cmd) { - sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); - PlotGridXdefault = PlotGridX; - PlotGridYdefault = PlotGridY; - RepaintGraphWindow(); - return 0; + sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); + PlotGridXdefault = PlotGridX; + PlotGridYdefault = PlotGridY; + RepaintGraphWindow(); + return 0; } int CmdSetGraphMarkers(const char *Cmd) { - sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos); - RepaintGraphWindow(); - return 0; + sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos); + RepaintGraphWindow(); + return 0; } int CmdHexsamples(const char *Cmd) { - int i, j, requested = 0, offset = 0; - char string_buf[25]; - char* string_ptr = string_buf; - uint8_t got[BIGBUF_SIZE]; + int i, j, requested = 0, offset = 0; + char string_buf[25]; + char* string_ptr = string_buf; + uint8_t got[BIGBUF_SIZE]; - sscanf(Cmd, "%i %i", &requested, &offset); + sscanf(Cmd, "%i %i", &requested, &offset); - /* if no args send something */ - if (requested == 0) - requested = 8; + /* if no args send something */ + if (requested == 0) + requested = 8; - if (offset + requested > sizeof(got)) { - PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE); - return 0; - } + if (offset + requested > sizeof(got)) { + PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE); + return 0; + } - if ( !GetFromDevice(BIG_BUF, got, requested, offset, NULL, 2500, false)) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } + if ( !GetFromDevice(BIG_BUF, got, requested, offset, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "command execution time out"); + return false; + } - i = 0; - for (j = 0; j < requested; j++) { - i++; - string_ptr += sprintf(string_ptr, "%02x ", got[j]); - if (i == 8) { - *(string_ptr - 1) = '\0'; // remove the trailing space - PrintAndLogEx(NORMAL, "%s", string_buf); - string_buf[0] = '\0'; - string_ptr = string_buf; - i = 0; - } - if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes - *(string_ptr - 1) = '\0'; - PrintAndLogEx(NORMAL, "%s", string_buf); - string_buf[0] = '\0'; - } - } - return 0; + i = 0; + for (j = 0; j < requested; j++) { + i++; + string_ptr += sprintf(string_ptr, "%02x ", got[j]); + if (i == 8) { + *(string_ptr - 1) = '\0'; // remove the trailing space + PrintAndLogEx(NORMAL, "%s", string_buf); + string_buf[0] = '\0'; + string_ptr = string_buf; + i = 0; + } + if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes + *(string_ptr - 1) = '\0'; + PrintAndLogEx(NORMAL, "%s", string_buf); + string_buf[0] = '\0'; + } + } + return 0; } int CmdHide(const char *Cmd) { - HideGraphWindow(); - return 0; + HideGraphWindow(); + return 0; } //zero mean GraphBuffer int CmdHpf(const char *Cmd) { - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - removeSignalOffset(bits, size); - // push it back to graph - setGraphBuf(bits, size); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + removeSignalOffset(bits, size); + // push it back to graph + setGraphBuf(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } bool _headBit( BitstreamOut *stream) { - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = (stream->position++) & 7; // mask out 00000111 - return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; + int bytepos = stream->position >> 3; // divide by 8 + int bitpos = (stream->position++) & 7; // mask out 00000111 + return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; } uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) { - uint8_t val = 0; - for(int i = 0 ; i < bits_per_sample; i++) - val |= (_headBit(b) << (7-i)); + uint8_t val = 0; + for(int i = 0 ; i < bits_per_sample; i++) + val |= (_headBit(b) << (7-i)); - return val; + return val; } int getSamples(int n, bool silent) { - //If we get all but the last byte in bigbuf, - // we don't have to worry about remaining trash - // in the last byte in case the bits-per-sample - // does not line up on byte boundaries - uint8_t got[BIGBUF_SIZE-1] = { 0 }; + //If we get all but the last byte in bigbuf, + // we don't have to worry about remaining trash + // in the last byte in case the bits-per-sample + // does not line up on byte boundaries + uint8_t got[BIGBUF_SIZE-1] = { 0 }; - if ( n == 0 || n > sizeof(got)) - n = sizeof(got); + if ( n == 0 || n > sizeof(got)) + n = sizeof(got); - if (!silent) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); + if (!silent) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); - UsbCommand response; - if ( !GetFromDevice(BIG_BUF, got, n, 0, &response, 10000, true) ) { + UsbCommand response; + if ( !GetFromDevice(BIG_BUF, got, n, 0, &response, 10000, true) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return 1; } - if (!silent) PrintAndLogEx(NORMAL, "Data fetched"); + if (!silent) PrintAndLogEx(NORMAL, "Data fetched"); - uint8_t bits_per_sample = 8; + uint8_t bits_per_sample = 8; - //Old devices without this feature would send 0 at arg[0] - if (response.arg[0] > 0) { - sample_config *sc = (sample_config *) response.d.asBytes; - if (!silent) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); - bits_per_sample = sc->bits_per_sample; - } + //Old devices without this feature would send 0 at arg[0] + if (response.arg[0] > 0) { + sample_config *sc = (sample_config *) response.d.asBytes; + if (!silent) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); + bits_per_sample = sc->bits_per_sample; + } - if (bits_per_sample < 8) { + if (bits_per_sample < 8) { - if (!silent) PrintAndLogEx(NORMAL, "Unpacking..."); + if (!silent) PrintAndLogEx(NORMAL, "Unpacking..."); - BitstreamOut bout = { got, bits_per_sample * n, 0}; - int j =0; - for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { - uint8_t sample = getByte(bits_per_sample, &bout); - GraphBuffer[j] = ((int) sample )- 128; - } - GraphTraceLen = j; + BitstreamOut bout = { got, bits_per_sample * n, 0}; + int j =0; + for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { + uint8_t sample = getByte(bits_per_sample, &bout); + GraphBuffer[j] = ((int) sample )- 128; + } + GraphTraceLen = j; - if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples" , j ); + if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples" , j ); - } else { - for (int j = 0; j < n; j++) { - GraphBuffer[j] = ((int)got[j]) - 128; - } - GraphTraceLen = n; - } + } else { + for (int j = 0; j < n; j++) { + GraphBuffer[j] = ((int)got[j]) - 128; + } + GraphTraceLen = n; + } - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - setClockGrid(0, 0); - DemodBufferLen = 0; - RepaintGraphWindow(); - return 0; + setClockGrid(0, 0); + DemodBufferLen = 0; + RepaintGraphWindow(); + return 0; } int CmdSamples(const char *Cmd) { - int n = strtol(Cmd, NULL, 0); - return getSamples(n, false); + int n = strtol(Cmd, NULL, 0); + return getSamples(n, false); } int CmdTuneSamples(const char *Cmd) { -#define NON_VOLTAGE 1000 -#define LF_UNUSABLE_V 2000 -#define LF_MARGINAL_V 10000 -#define HF_UNUSABLE_V 3000 -#define HF_MARGINAL_V 5000 -#define ANTENNA_ERROR 1.03 // current algo has 3% error margin. +#define NON_VOLTAGE 1000 +#define LF_UNUSABLE_V 2000 +#define LF_MARGINAL_V 10000 +#define HF_UNUSABLE_V 3000 +#define HF_MARGINAL_V 5000 +#define ANTENNA_ERROR 1.03 // current algo has 3% error margin. - // hide demod plot line - DemodBufferLen = 0; - setClockGrid(0, 0); - RepaintGraphWindow(); + // hide demod plot line + DemodBufferLen = 0; + setClockGrid(0, 0); + RepaintGraphWindow(); - int timeout = 0; - PrintAndLogEx(INFO, "\nmeasuring antenna characteristics, please wait..."); + int timeout = 0; + PrintAndLogEx(INFO, "\nmeasuring antenna characteristics, please wait..."); - UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - while (!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING, &resp, 2000)) { - timeout++; - printf("."); fflush(stdout); - if (timeout > 7) { - PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); - return 1; - } - } - PrintAndLogEx(NORMAL, "\n"); + UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + while (!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING, &resp, 2000)) { + timeout++; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); + return 1; + } + } + PrintAndLogEx(NORMAL, "\n"); - uint32_t v_lf125 = resp.arg[0]; - uint32_t v_lf134 = resp.arg[0] >> 32; + uint32_t v_lf125 = resp.arg[0]; + uint32_t v_lf134 = resp.arg[0] >> 32; - uint32_t v_hf = resp.arg[1]; - uint32_t peakf = resp.arg[2]; - uint32_t peakv = resp.arg[2] >> 32; + uint32_t v_hf = resp.arg[1]; + uint32_t peakf = resp.arg[2]; + uint32_t peakv = resp.arg[2] >> 32; - if ( v_lf125 > NON_VOLTAGE ) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 125.00 kHz", (v_lf125 * ANTENNA_ERROR)/1000.0); - if ( v_lf134 > NON_VOLTAGE ) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 134.00 kHz", (v_lf134 * ANTENNA_ERROR)/1000.0); - if ( peakv > NON_VOLTAGE && peakf > 0 ) - PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (peakv * ANTENNA_ERROR)/1000.0, 12000.0/(peakf+1)); + if ( v_lf125 > NON_VOLTAGE ) + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 125.00 kHz", (v_lf125 * ANTENNA_ERROR)/1000.0); + if ( v_lf134 > NON_VOLTAGE ) + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 134.00 kHz", (v_lf134 * ANTENNA_ERROR)/1000.0); + if ( peakv > NON_VOLTAGE && peakf > 0 ) + PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (peakv * ANTENNA_ERROR)/1000.0, 12000.0/(peakf+1)); - char judgement[20]; - memset(judgement, 0, sizeof(judgement)); - // LF evaluation - if (peakv < LF_UNUSABLE_V) - sprintf(judgement, _RED_(UNUSABLE) ); - else if (peakv < LF_MARGINAL_V) - sprintf(judgement, _YELLOW_(MARGINAL) ); - else - sprintf(judgement, _GREEN_(OK) ); + char judgement[20]; + memset(judgement, 0, sizeof(judgement)); + // LF evaluation + if (peakv < LF_UNUSABLE_V) + sprintf(judgement, _RED_(UNUSABLE) ); + else if (peakv < LF_MARGINAL_V) + sprintf(judgement, _YELLOW_(MARGINAL) ); + else + sprintf(judgement, _GREEN_(OK) ); - PrintAndLogEx(NORMAL, "%sLF antenna is %s \n" - , (peakv < LF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) - , judgement - ); + PrintAndLogEx(NORMAL, "%sLF antenna is %s \n" + , (peakv < LF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) + , judgement + ); - // HF evaluation - if ( v_hf > NON_VOLTAGE ) - PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (v_hf * ANTENNA_ERROR)/1000.0); + // HF evaluation + if ( v_hf > NON_VOLTAGE ) + PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (v_hf * ANTENNA_ERROR)/1000.0); - memset(judgement, 0, sizeof(judgement)); + memset(judgement, 0, sizeof(judgement)); - if (v_hf < HF_UNUSABLE_V) - sprintf(judgement, _RED_(UNUSABLE) ); - else if (v_hf < HF_MARGINAL_V) - sprintf(judgement, _YELLOW_(MARGINAL) ); - else - sprintf(judgement, _GREEN_(OK) ); + if (v_hf < HF_UNUSABLE_V) + sprintf(judgement, _RED_(UNUSABLE) ); + else if (v_hf < HF_MARGINAL_V) + sprintf(judgement, _YELLOW_(MARGINAL) ); + else + sprintf(judgement, _GREEN_(OK) ); - PrintAndLogEx(NORMAL, "%sHF antenna is %s" - , (v_hf < HF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) - , judgement - ); + PrintAndLogEx(NORMAL, "%sHF antenna is %s" + , (v_hf < HF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) + , judgement + ); - // graph LF measurements - // even here, these values has 3% error. - uint16_t test = 0; - for (int i = 0; i < 256; i++) { - GraphBuffer[i] = resp.d.asBytes[i] - 128; - test += resp.d.asBytes[i]; - } - if ( test > 0 ) { - PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor 89 is 134khz, 95 is 125khz.\n\n"); - GraphTraceLen = 256; - ShowGraphWindow(); - RepaintGraphWindow(); - } else { + // graph LF measurements + // even here, these values has 3% error. + uint16_t test = 0; + for (int i = 0; i < 256; i++) { + GraphBuffer[i] = resp.d.asBytes[i] - 128; + test += resp.d.asBytes[i]; + } + if ( test > 0 ) { + PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor 89 is 134khz, 95 is 125khz.\n\n"); + GraphTraceLen = 256; + ShowGraphWindow(); + RepaintGraphWindow(); + } else { - PrintAndLogEx(FAILED, "\nNot showing LF tuning graph since all values is zero.\n\n"); - } + PrintAndLogEx(FAILED, "\nNot showing LF tuning graph since all values is zero.\n\n"); + } - return 0; + return 0; } int CmdLoad(const char *Cmd) { - char filename[FILE_PATH_SIZE] = {0x00}; - int len = 0; + char filename[FILE_PATH_SIZE] = {0x00}; + int len = 0; + + len = strlen(Cmd); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); + + FILE *f = fopen(filename, "r"); + if (!f) { + PrintAndLogEx(WARNING, "couldn't open '%s'", filename); + return 0; + } + + GraphTraceLen = 0; + char line[80]; + while (fgets(line, sizeof (line), f)) { + GraphBuffer[GraphTraceLen] = atoi(line); + GraphTraceLen++; - len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); - - FILE *f = fopen(filename, "r"); - if (!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); - return 0; - } - - GraphTraceLen = 0; - char line[80]; - while (fgets(line, sizeof (line), f)) { - GraphBuffer[GraphTraceLen] = atoi(line); - GraphTraceLen++; - if ( GraphTraceLen >= MAX_GRAPH_TRACE_LEN ) break; - } - - if (f) - fclose(f); + } - PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); + if (f) + fclose(f); - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - - removeSignalOffset(bits, size); - setGraphBuf(bits, size); - computeSignalProperties(bits, size); + PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); - setClockGrid(0,0); - DemodBufferLen = 0; - RepaintGraphWindow(); - return 0; + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + + removeSignalOffset(bits, size); + setGraphBuf(bits, size); + computeSignalProperties(bits, size); + + setClockGrid(0,0); + DemodBufferLen = 0; + RepaintGraphWindow(); + return 0; } // trim graph from the end int CmdLtrim(const char *Cmd) { - // sanitycheck - if (GraphTraceLen <= 0) return 1; + // sanitycheck + if (GraphTraceLen <= 0) return 1; - int ds = atoi(Cmd); - for (int i = ds; i < GraphTraceLen; ++i) - GraphBuffer[i-ds] = GraphBuffer[i]; + int ds = atoi(Cmd); + for (int i = ds; i < GraphTraceLen; ++i) + GraphBuffer[i-ds] = GraphBuffer[i]; - GraphTraceLen -= ds; - RepaintGraphWindow(); - return 0; + GraphTraceLen -= ds; + RepaintGraphWindow(); + return 0; } // trim graph from the beginning int CmdRtrim(const char *Cmd) { - int ds = atoi(Cmd); + int ds = atoi(Cmd); - // sanitycheck - if (GraphTraceLen <= ds) return 1; + // sanitycheck + if (GraphTraceLen <= ds) return 1; - GraphTraceLen = ds; - RepaintGraphWindow(); - return 0; + GraphTraceLen = ds; + RepaintGraphWindow(); + return 0; } // trim graph (middle) piece int CmdMtrim(const char *Cmd) { - int start = 0, stop = 0; - sscanf(Cmd, "%i %i", &start, &stop); + int start = 0, stop = 0; + sscanf(Cmd, "%i %i", &start, &stop); - if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 1; + if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 1; - // leave start position sample - start++; + // leave start position sample + start++; - GraphTraceLen = stop - start; - for (int i = 0; i < GraphTraceLen; i++) - GraphBuffer[i] = GraphBuffer[start+i]; + GraphTraceLen = stop - start; + for (int i = 0; i < GraphTraceLen; i++) + GraphBuffer[i] = GraphBuffer[start+i]; - return 0; + return 0; } int CmdNorm(const char *Cmd) { - int i; - int max = INT_MIN, min = INT_MAX; + int i; + int max = INT_MIN, min = INT_MAX; - // Find local min, max - for (i = 10; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] > max) max = GraphBuffer[i]; - if (GraphBuffer[i] < min) min = GraphBuffer[i]; - } + // Find local min, max + for (i = 10; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] > max) max = GraphBuffer[i]; + if (GraphBuffer[i] < min) min = GraphBuffer[i]; + } - if (max != min) { - for (i = 0; i < GraphTraceLen; ++i) { - GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min); - //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work - } - } + if (max != min) { + for (i = 0; i < GraphTraceLen; ++i) { + GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min); + //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work + } + } - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } int CmdPlot(const char *Cmd) { - ShowGraphWindow(); - return 0; + ShowGraphWindow(); + return 0; } int CmdSave(const char *Cmd) { - int len = 0; - char filename[FILE_PATH_SIZE] = {0x00}; + int len = 0; + char filename[FILE_PATH_SIZE] = {0x00}; - len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); + len = strlen(Cmd); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); - FILE *f = fopen(filename, "w"); - if(!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); - return 0; - } + FILE *f = fopen(filename, "w"); + if(!f) { + PrintAndLogEx(WARNING, "couldn't open '%s'", filename); + return 0; + } - for (int i = 0; i < GraphTraceLen; i++) - fprintf(f, "%d\n", GraphBuffer[i]); + for (int i = 0; i < GraphTraceLen; i++) + fprintf(f, "%d\n", GraphBuffer[i]); - if (f) - fclose(f); + if (f) + fclose(f); - PrintAndLogEx(SUCCESS, "saved to '%s'", Cmd); - return 0; + PrintAndLogEx(SUCCESS, "saved to '%s'", Cmd); + return 0; } int CmdScale(const char *Cmd) { - CursorScaleFactor = atoi(Cmd); - if (CursorScaleFactor == 0) { - PrintAndLogEx(FAILED, "bad, can't have zero scale"); - CursorScaleFactor = 1; - } - RepaintGraphWindow(); - return 0; + CursorScaleFactor = atoi(Cmd); + if (CursorScaleFactor == 0) { + PrintAndLogEx(FAILED, "bad, can't have zero scale"); + CursorScaleFactor = 1; + } + RepaintGraphWindow(); + return 0; } int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down) { - int lastValue = in[0]; + int lastValue = in[0]; - // Will be changed at the end, but init 0 as we adjust to last samples - // value if no threshold kicks in. - out[0] = 0; + // Will be changed at the end, but init 0 as we adjust to last samples + // value if no threshold kicks in. + out[0] = 0; - for (size_t i = 1; i < len; ++i) { - // Apply first threshold to samples heading up - if (in[i] >= up && in[i] > lastValue) - { - lastValue = out[i]; // Buffer last value as we overwrite it. - out[i] = 1; - } - // Apply second threshold to samples heading down - else if (in[i] <= down && in[i] < lastValue) - { - lastValue = out[i]; // Buffer last value as we overwrite it. - out[i] = -1; - } - else - { - lastValue = out[i]; // Buffer last value as we overwrite it. - out[i] = out[i-1]; - } - } + for (size_t i = 1; i < len; ++i) { + // Apply first threshold to samples heading up + if (in[i] >= up && in[i] > lastValue) + { + lastValue = out[i]; // Buffer last value as we overwrite it. + out[i] = 1; + } + // Apply second threshold to samples heading down + else if (in[i] <= down && in[i] < lastValue) + { + lastValue = out[i]; // Buffer last value as we overwrite it. + out[i] = -1; + } + else + { + lastValue = out[i]; // Buffer last value as we overwrite it. + out[i] = out[i-1]; + } + } - // Align with first edited sample. - out[0] = out[1]; - return 0; + // Align with first edited sample. + out[0] = out[1]; + return 0; } int CmdDirectionalThreshold(const char *Cmd) { - int8_t up = param_get8(Cmd, 0); - int8_t down = param_get8(Cmd, 1); + int8_t up = param_get8(Cmd, 0); + int8_t down = param_get8(Cmd, 1); - PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); + PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); - directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); + directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); - // set signal properties low/high/mean/amplitude and isnoice detection - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noice detection - computeSignalProperties(bits, size); + // set signal properties low/high/mean/amplitude and isnoice detection + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noice detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } int CmdZerocrossings(const char *Cmd) { - // Zero-crossings aren't meaningful unless the signal is zero-mean. - CmdHpf(""); + // Zero-crossings aren't meaningful unless the signal is zero-mean. + CmdHpf(""); - int sign = 1, zc = 0, lastZc = 0; + int sign = 1, zc = 0, lastZc = 0; - for (int i = 0; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] * sign >= 0) { - // No change in sign, reproduce the previous sample count. - zc++; - GraphBuffer[i] = lastZc; - } else { - // Change in sign, reset the sample count. - sign = -sign; - GraphBuffer[i] = lastZc; - if (sign > 0) { - lastZc = zc; - zc = 0; - } - } - } + for (int i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] * sign >= 0) { + // No change in sign, reproduce the previous sample count. + zc++; + GraphBuffer[i] = lastZc; + } else { + // Change in sign, reset the sample count. + sign = -sign; + GraphBuffer[i] = lastZc; + if (sign > 0) { + lastZc = zc; + zc = 0; + } + } + } - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } /** @@ -1833,304 +1833,304 @@ int CmdZerocrossings(const char *Cmd) { * @return */ int Cmdbin2hex(const char *Cmd) { - int bg = 0, en = 0; - if (param_getptr(Cmd, &bg, &en, 0)) - return usage_data_bin2hex(); + int bg = 0, en = 0; + if (param_getptr(Cmd, &bg, &en, 0)) + return usage_data_bin2hex(); - //Number of digits supplied as argument - size_t length = en - bg + 1; - size_t bytelen = (length+7) / 8; - uint8_t* arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t)); - memset(arr, 0, bytelen); - BitstreamOut bout = { arr, 0, 0 }; + //Number of digits supplied as argument + size_t length = en - bg + 1; + size_t bytelen = (length+7) / 8; + uint8_t* arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t)); + memset(arr, 0, bytelen); + BitstreamOut bout = { arr, 0, 0 }; - for (; bg <= en; bg++) { - char c = Cmd[bg]; - if( c == '1') - pushBit(&bout, 1); - else if( c == '0') - pushBit(&bout, 0); - else - PrintAndLogEx(NORMAL, "Ignoring '%c'", c); - } + for (; bg <= en; bg++) { + char c = Cmd[bg]; + if( c == '1') + pushBit(&bout, 1); + else if( c == '0') + pushBit(&bout, 0); + else + PrintAndLogEx(NORMAL, "Ignoring '%c'", c); + } - if (bout.numbits % 8 != 0) - PrintAndLogEx(NORMAL, "[padded with %d zeroes]", 8 - (bout.numbits % 8)); + if (bout.numbits % 8 != 0) + PrintAndLogEx(NORMAL, "[padded with %d zeroes]", 8 - (bout.numbits % 8)); - PrintAndLogEx(NORMAL, "%s", sprint_hex(arr, bytelen)); - free(arr); - return 0; + PrintAndLogEx(NORMAL, "%s", sprint_hex(arr, bytelen)); + free(arr); + return 0; } int Cmdhex2bin(const char *Cmd) { - int bg = 0, en = 0; - if (param_getptr(Cmd, &bg, &en, 0)) return usage_data_hex2bin(); + int bg = 0, en = 0; + if (param_getptr(Cmd, &bg, &en, 0)) return usage_data_hex2bin(); - while (bg <= en ) { - char x = Cmd[bg++]; - // capitalize - if (x >= 'a' && x <= 'f') - x -= 32; - // convert to numeric value - if (x >= '0' && x <= '9') - x -= '0'; - else if (x >= 'A' && x <= 'F') - x -= 'A' - 10; - else - continue; + while (bg <= en ) { + char x = Cmd[bg++]; + // capitalize + if (x >= 'a' && x <= 'f') + x -= 32; + // convert to numeric value + if (x >= '0' && x <= '9') + x -= '0'; + else if (x >= 'A' && x <= 'F') + x -= 'A' - 10; + else + continue; - //Uses printf instead of PrintAndLog since the latter - // adds linebreaks to each printout - this way was more convenient since we don't have to - // allocate a string and write to that first... - for(int i = 0 ; i < 4 ; ++i) - PrintAndLogEx(NORMAL, "%d",(x >> (3 - i)) & 1); - } - PrintAndLogEx(NORMAL, "\n"); - return 0; + //Uses printf instead of PrintAndLog since the latter + // adds linebreaks to each printout - this way was more convenient since we don't have to + // allocate a string and write to that first... + for(int i = 0 ; i < 4 ; ++i) + PrintAndLogEx(NORMAL, "%d",(x >> (3 - i)) & 1); + } + PrintAndLogEx(NORMAL, "\n"); + return 0; } - /* // example of FSK2 RF/50 Tones - static const int LowTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 - }; - static const int HighTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder) - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder - }; - */ + /* // example of FSK2 RF/50 Tones + static const int LowTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 + }; + static const int HighTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder) + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder + }; + */ void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighToneFC) { - int i,j=0; - int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2); - int Right_Modifier = (clk % LowToneFC) / 2; - //int HighToneMod = clk mod HighToneFC; - int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate - int FCs_per_clk = clk / LowToneFC; + int i,j=0; + int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2); + int Right_Modifier = (clk % LowToneFC) / 2; + //int HighToneMod = clk mod HighToneFC; + int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate + int FCs_per_clk = clk / LowToneFC; - // need to correctly split up the clock to field clocks. - // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk + // need to correctly split up the clock to field clocks. + // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk - // start with LowTone - // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk - for (i = 0; i < Left_Modifier; i++) { - LowTone[i] = 1; - } + // start with LowTone + // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk + for (i = 0; i < Left_Modifier; i++) { + LowTone[i] = 1; + } - // loop # of field clocks inside the main clock - for (i = 0; i < (FCs_per_clk); i++) { - // loop # of samples per field clock - for (j = 0; j < LowToneFC; j++) { - LowTone[ (i * LowToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; - } - } + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < LowToneFC; j++) { + LowTone[ (i * LowToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } - int k; - // add last -1 modifiers - for (k = 0; k < Right_Modifier; k++) { - LowTone[ ( (i-1) * LowToneFC) + Left_Modifier + j + k] = -1; - } + int k; + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + LowTone[ ( (i-1) * LowToneFC) + Left_Modifier + j + k] = -1; + } - // now do hightone - Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2); - Right_Modifier = (clk % HighToneFC) / 2; - LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate - FCs_per_clk = clk/HighToneFC; + // now do hightone + Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2); + Right_Modifier = (clk % HighToneFC) / 2; + LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate + FCs_per_clk = clk/HighToneFC; - for (i = 0; i < Left_Modifier; i++) { - HighTone[i] = 1; - } + for (i = 0; i < Left_Modifier; i++) { + HighTone[i] = 1; + } - // loop # of field clocks inside the main clock - for (i = 0; i < (FCs_per_clk); i++) { - // loop # of samples per field clock - for (j = 0; j < HighToneFC; j++) { - HighTone[(i * HighToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; - } - } + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < HighToneFC; j++) { + HighTone[(i * HighToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } - // add last -1 modifiers - for (k = 0; k < Right_Modifier; k++) { - PrintAndLogEx(NORMAL, "(i-1)*HighToneFC+lm+j+k %i", ((i-1) * HighToneFC) + Left_Modifier + j + k); - HighTone[ ( (i-1) * HighToneFC) + Left_Modifier + j + k] = -1; - } - if (g_debugMode == 2) { - for ( i = 0; i < clk; i++) { - PrintAndLogEx(NORMAL, "Low: %i, High: %i", LowTone[i], HighTone[i]); - } - } + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + PrintAndLogEx(NORMAL, "(i-1)*HighToneFC+lm+j+k %i", ((i-1) * HighToneFC) + Left_Modifier + j + k); + HighTone[ ( (i-1) * HighToneFC) + Left_Modifier + j + k] = -1; + } + if (g_debugMode == 2) { + for ( i = 0; i < clk; i++) { + PrintAndLogEx(NORMAL, "Low: %i, High: %i", LowTone[i], HighTone[i]); + } + } } //old CmdFSKdemod adapted by marshmellow //converts FSK to clear NRZ style wave. (or demodulates) int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { - uint8_t ans = 0; - if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) { - int firstClockEdge=0; - ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, &firstClockEdge); - if (g_debugMode > 1) { - PrintAndLog ("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); - } - } - // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...) - if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) { - if (g_debugMode > 1) { - PrintAndLog ("DEBUG FSKtoNRZ: no fsk clocks found"); - } - return 0; - } + uint8_t ans = 0; + if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) { + int firstClockEdge=0; + ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, &firstClockEdge); + if (g_debugMode > 1) { + PrintAndLog ("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); + } + } + // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...) + if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) { + if (g_debugMode > 1) { + PrintAndLog ("DEBUG FSKtoNRZ: no fsk clocks found"); + } + return 0; + } - int i, j; - int LowTone[clk]; - int HighTone[clk]; - GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC); + int i, j; + int LowTone[clk]; + int HighTone[clk]; + GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC); - // loop through ([all samples] - clk) - for (i = 0; i < *dataLen - clk; ++i) { - int lowSum = 0, highSum = 0; + // loop through ([all samples] - clk) + for (i = 0; i < *dataLen - clk; ++i) { + int lowSum = 0, highSum = 0; - // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data) - for (j = 0; j < clk; ++j) { - lowSum += LowTone[j] * data[i + j]; - highSum += HighTone[j] * data[i + j]; - } - // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts) - lowSum = abs(100 * lowSum / clk); - highSum = abs(100 * highSum / clk); - // save these back to buffer for later use - data[i] = (highSum << 16) | lowSum; - } + // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data) + for (j = 0; j < clk; ++j) { + lowSum += LowTone[j] * data[i + j]; + highSum += HighTone[j] * data[i + j]; + } + // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts) + lowSum = abs(100 * lowSum / clk); + highSum = abs(100 * highSum / clk); + // save these back to buffer for later use + data[i] = (highSum << 16) | lowSum; + } - // now we have the abs( [average sample value per clk] * 100 ) for each tone - // loop through again [all samples] - clk - 16 - // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc - for(i = 0; i < *dataLen - clk - LowToneFC; ++i) { - int lowTot = 0, highTot = 0; + // now we have the abs( [average sample value per clk] * 100 ) for each tone + // loop through again [all samples] - clk - 16 + // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc + for(i = 0; i < *dataLen - clk - LowToneFC; ++i) { + int lowTot = 0, highTot = 0; - // sum a field clock width of abs( [average sample values per clk] * 100) for each tone - for (j = 0; j < LowToneFC; ++j) { //10 for fsk2 - lowTot += (data[i + j] & 0xffff); - } - for (j = 0; j < HighToneFC; j++) { //8 for fsk2 - highTot += (data[i + j] >> 16); - } + // sum a field clock width of abs( [average sample values per clk] * 100) for each tone + for (j = 0; j < LowToneFC; ++j) { //10 for fsk2 + lowTot += (data[i + j] & 0xffff); + } + for (j = 0; j < HighToneFC; j++) { //8 for fsk2 + highTot += (data[i + j] >> 16); + } - // subtract the sum of lowTone averages by the sum of highTone averages as it - // and write back the new graph value - data[i] = lowTot - highTot; - } - // update dataLen to what we put back to the data sample buffer - *dataLen -= (clk + LowToneFC); - return 0; + // subtract the sum of lowTone averages by the sum of highTone averages as it + // and write back the new graph value + data[i] = lowTot - highTot; + } + // update dataLen to what we put back to the data sample buffer + *dataLen -= (clk + LowToneFC); + return 0; } int CmdFSKToNRZ(const char *Cmd) { - // take clk, fc_low, fc_high - // blank = auto; - bool errors = false; - char cmdp = 0; - int clk = 0, fc_low = 10, fc_high = 8; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_fsktonrz(); - case 'c': - clk = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'f': - fc_high = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'l': - fc_low = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - if(errors) break; - } - //Validations - if (errors) return usage_data_fsktonrz(); + // take clk, fc_low, fc_high + // blank = auto; + bool errors = false; + char cmdp = 0; + int clk = 0, fc_low = 10, fc_high = 8; + while (param_getchar(Cmd, cmdp) != 0x00) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_data_fsktonrz(); + case 'c': + clk = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'f': + fc_high = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'l': + fc_low = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + //Validations + if (errors) return usage_data_fsktonrz(); - setClockGrid(0, 0); - DemodBufferLen = 0; - int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high); - CmdNorm(""); - RepaintGraphWindow(); - return ans; + setClockGrid(0, 0); + DemodBufferLen = 0; + int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high); + CmdNorm(""); + RepaintGraphWindow(); + return ans; } int CmdDataIIR(const char *Cmd){ - uint8_t k = param_get8(Cmd, 0); - //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); - iceSimple_Filter(GraphBuffer, GraphTraceLen, k); + uint8_t k = param_get8(Cmd, 0); + //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); + iceSimple_Filter(GraphBuffer, GraphTraceLen, k); - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); + RepaintGraphWindow(); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, - {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, - {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, - {"bin2hex", Cmdbin2hex, 1, " -- Converts binary to hexadecimal"}, - {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, - {"buffclear", CmdBuffClear, 1, "Clears bigbuff on deviceside and graph window"}, - {"dec", CmdDec, 1, "Decimate samples"}, - {"detectclock", CmdDetectClockRate, 1, "[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"}, - {"fsktonrz", CmdFSKToNRZ, 1, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"}, + {"help", CmdHelp, 1, "This help"}, + {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, + {"autocorr", CmdAutoCorr, 1, "[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)"}, + {"biphaserawdecode",CmdBiphaseDecodeRaw,1, "[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"}, + {"bin2hex", Cmdbin2hex, 1, " -- Converts binary to hexadecimal"}, + {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, + {"buffclear", CmdBuffClear, 1, "Clears bigbuff on deviceside and graph window"}, + {"dec", CmdDec, 1, "Decimate samples"}, + {"detectclock", CmdDetectClockRate, 1, "[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"}, + {"fsktonrz", CmdFSKToNRZ, 1, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"}, - {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, - {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, - {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, - {"hex2bin", Cmdhex2bin, 1, " -- Converts hexadecimal to binary"}, - {"hide", CmdHide, 1, "Hide graph window"}, - {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, - {"load", CmdLoad, 1, " -- Load trace (to graph window"}, - {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, - {"rtrim", CmdRtrim, 1, " -- Trim samples from right of trace"}, - {"mtrim", CmdMtrim, 1, " -- Trim out samples from the specified start to the specified stop"}, - {"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"}, - {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, - {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, - {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, - {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, - {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, - {"save", CmdSave, 1, " -- Save trace (from graph window)"}, - {"setgraphmarkers", CmdSetGraphMarkers, 1, "[orange_marker] [blue_marker] (in graph window)"}, - {"scale", CmdScale, 1, " -- Set cursor display scale"}, - {"setdebugmode", CmdSetDebugMode, 1, "<0|1|2> -- Turn on or off Debugging Level for lf demods"}, - {"shiftgraphzero", CmdGraphShiftZero, 1, " -- Shift 0 for Graphed wave + or - shift value"}, - {"dirthreshold", CmdDirectionalThreshold, 1, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, - {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"}, - {"undec", CmdUndec, 1, "Un-decimate samples by 2"}, - {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, - {"iir", CmdDataIIR, 0, "apply IIR buttersworth filter on plotdata"}, - {NULL, NULL, 0, NULL} + {"getbitstream", CmdGetBitStream, 1, "Convert GraphBuffer's >=1 values to 1 and <1 to 0"}, + {"grid", CmdGrid, 1, " -- overlay grid on graph window, use zero value to turn off either"}, + {"hexsamples", CmdHexsamples, 0, " [] -- Dump big buffer as hex bytes"}, + {"hex2bin", Cmdhex2bin, 1, " -- Converts hexadecimal to binary"}, + {"hide", CmdHide, 1, "Hide graph window"}, + {"hpf", CmdHpf, 1, "Remove DC offset from trace"}, + {"load", CmdLoad, 1, " -- Load trace (to graph window"}, + {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, + {"rtrim", CmdRtrim, 1, " -- Trim samples from right of trace"}, + {"mtrim", CmdMtrim, 1, " -- Trim out samples from the specified start to the specified stop"}, + {"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"}, + {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, + {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, + {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, + {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, + {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, + {"save", CmdSave, 1, " -- Save trace (from graph window)"}, + {"setgraphmarkers", CmdSetGraphMarkers, 1, "[orange_marker] [blue_marker] (in graph window)"}, + {"scale", CmdScale, 1, " -- Set cursor display scale"}, + {"setdebugmode", CmdSetDebugMode, 1, "<0|1|2> -- Turn on or off Debugging Level for lf demods"}, + {"shiftgraphzero", CmdGraphShiftZero, 1, " -- Shift 0 for Graphed wave + or - shift value"}, + {"dirthreshold", CmdDirectionalThreshold, 1, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, + {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"}, + {"undec", CmdUndec, 1, "Un-decimate samples by 2"}, + {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, + {"iir", CmdDataIIR, 0, "apply IIR buttersworth filter on plotdata"}, + {NULL, NULL, 0, NULL} }; int CmdData(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmddata.h b/client/cmddata.h index 27c446ecb..605bc3298 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -22,7 +22,7 @@ #include // for CmdNorm INT_MIN && INT_MAX #include "util.h" #include "cmdmain.h" -#include "proxmark3.h" // sendcommand +#include "proxmark3.h"// sendcommand #include "ui.h" // for show graph controls #include "graph.h" // for graph data #include "comms.h" diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index b576f43f7..f6a6e8518 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -27,435 +27,435 @@ static int CmdHelp(const char *Cmd); int usage_flashmem_spibaud(void){ - PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); - PrintAndLogEx(NORMAL, " "); - PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); - PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); - PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem spibaud 48"); - return 0; + PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); + PrintAndLogEx(NORMAL, " "); + PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); + PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); + PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem spibaud 48"); + return 0; } int usage_flashmem_read(void){ - PrintAndLogEx(NORMAL, "Read flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem read o l "); - PrintAndLogEx(NORMAL, " o : offset in memory"); - PrintAndLogEx(NORMAL, " l : length"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 - PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024 - return 0; + PrintAndLogEx(NORMAL, "Read flash memory on device"); + PrintAndLogEx(NORMAL, "Usage: mem read o l "); + PrintAndLogEx(NORMAL, " o : offset in memory"); + PrintAndLogEx(NORMAL, " l : length"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 + PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024 + return 0; } int usage_flashmem_load(void){ - PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem load o f m t i"); - PrintAndLogEx(NORMAL, " o : offset in memory"); - PrintAndLogEx(NORMAL, " f : file name"); - PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)"); - PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)"); - PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 - PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 - PrintAndLogEx(NORMAL, " mem load f default_keys m"); - PrintAndLogEx(NORMAL, " mem load f default_pwd t"); - PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i"); - return 0; + PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); + PrintAndLogEx(NORMAL, "Usage: mem load o f m t i"); + PrintAndLogEx(NORMAL, " o : offset in memory"); + PrintAndLogEx(NORMAL, " f : file name"); + PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)"); + PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)"); + PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 + PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 + PrintAndLogEx(NORMAL, " mem load f default_keys m"); + PrintAndLogEx(NORMAL, " mem load f default_pwd t"); + PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i"); + return 0; } int usage_flashmem_save(void){ - PrintAndLogEx(NORMAL, "Saves flash memory on device into the file"); - PrintAndLogEx(NORMAL, " Usage: mem save o l f "); - PrintAndLogEx(NORMAL, " o : offset in memory"); - PrintAndLogEx(NORMAL, " l : length"); - PrintAndLogEx(NORMAL, " f : file name"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile - PrintAndLogEx(NORMAL, " mem save f myfile l 4096"); // download 4096 bytes from default offset 0 to file myfile - PrintAndLogEx(NORMAL, " mem save f myfile o 1024 l 4096"); // downlowd 4096 bytes from offset 1024 to file myfile - return 0; + PrintAndLogEx(NORMAL, "Saves flash memory on device into the file"); + PrintAndLogEx(NORMAL, " Usage: mem save o l f "); + PrintAndLogEx(NORMAL, " o : offset in memory"); + PrintAndLogEx(NORMAL, " l : length"); + PrintAndLogEx(NORMAL, " f : file name"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile + PrintAndLogEx(NORMAL, " mem save f myfile l 4096"); // download 4096 bytes from default offset 0 to file myfile + PrintAndLogEx(NORMAL, " mem save f myfile o 1024 l 4096"); // downlowd 4096 bytes from offset 1024 to file myfile + return 0; } int usage_flashmem_wipe(void){ - PrintAndLogEx(WARNING, "[OBS] use with caution."); - PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n"); + PrintAndLogEx(WARNING, "[OBS] use with caution."); + PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n"); - PrintAndLogEx(NORMAL, " Usage: mem wipe p "); - PrintAndLogEx(NORMAL, " p : 0,1,2 page memory"); -// PrintAndLogEx(NORMAL, " i : inital total wipe"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem wipe "); // wipe page 0,1,2 - PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page. - return 0; + PrintAndLogEx(NORMAL, " Usage: mem wipe p "); + PrintAndLogEx(NORMAL, " p : 0,1,2 page memory"); +// PrintAndLogEx(NORMAL, " i : inital total wipe"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem wipe "); // wipe page 0,1,2 + PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page. + return 0; } int usage_flashmem_info(void){ - PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n"); - PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]"); - PrintAndLogEx(NORMAL, " s : create a signature"); - PrintAndLogEx(NORMAL, " w : write signature to flash memory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem info"); - PrintAndLogEx(NORMAL, " mem info s"); - return 0; + PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n"); + PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]"); + PrintAndLogEx(NORMAL, " s : create a signature"); + PrintAndLogEx(NORMAL, " w : write signature to flash memory"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem info"); + PrintAndLogEx(NORMAL, " mem info s"); + return 0; } int CmdFlashMemRead(const char *Cmd) { - uint8_t cmdp = 0; - bool errors = false; - uint32_t start_index = 0, len = 0; + uint8_t cmdp = 0; + bool errors = false; + uint32_t start_index = 0, len = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'l': - len = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'h': - return usage_flashmem_read(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'l': + len = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'h': + return usage_flashmem_read(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_read(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_read(); - if (start_index + len > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory"); - return 1; - } + if (start_index + len > FLASH_MEM_MAX_SIZE) { + PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory"); + return 1; + } - UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdFlashmemSpiBaudrate(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud(); - uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); - baudrate = baudrate * 1000000; - if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); - UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; - SendCommand(&c); - return 0; + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud(); + uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); + baudrate = baudrate * 1000000; + if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); + UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; + SendCommand(&c); + return 0; } int CmdFlashMemLoad(const char *Cmd){ - uint32_t start_index = 0; - char filename[FILE_PATH_SIZE] = {0}; - bool errors = false; - uint8_t cmdp = 0; - Dictionary_t d = DICTIONARY_NONE; + uint32_t start_index = 0; + char filename[FILE_PATH_SIZE] = {0}; + bool errors = false; + uint8_t cmdp = 0; + Dictionary_t d = DICTIONARY_NONE; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_flashmem_load(); - case 'f': - if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'm': - d = DICTIONARY_MIFARE; - cmdp++; - break; - case 't': - d = DICTIONARY_T55XX; - cmdp++; - break; - case 'i': - d = DICTIONARY_ICLASS; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_flashmem_load(); + case 'f': + if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { + PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + break; + } + cmdp += 2; + break; + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'm': + d = DICTIONARY_MIFARE; + cmdp++; + break; + case 't': + d = DICTIONARY_T55XX; + cmdp++; + break; + case 'i': + d = DICTIONARY_ICLASS; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_load(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_load(); - size_t datalen = 0; - uint16_t keycount = 0; - int res = 0; - uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); + size_t datalen = 0; + uint16_t keycount = 0; + int res = 0; + uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); - switch (d) { - case DICTIONARY_MIFARE: - start_index = DEFAULT_MF_KEYS_OFFSET; - res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount ); - if ( res || !keycount) { - free(data); - return 1; - } - data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; - break; - case DICTIONARY_T55XX: - start_index = DEFAULT_T55XX_KEYS_OFFSET; - res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount ); - if ( res || !keycount) { - free(data); - return 1; - } - data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; - break; - case DICTIONARY_ICLASS: - start_index = DEFAULT_ICLASS_KEYS_OFFSET; - res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount ); - if ( res || !keycount) { - free(data); - return 1; - } - data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; - break; - default: + switch (d) { + case DICTIONARY_MIFARE: + start_index = DEFAULT_MF_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + case DICTIONARY_T55XX: + start_index = DEFAULT_T55XX_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + case DICTIONARY_ICLASS: + start_index = DEFAULT_ICLASS_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + default: - res = loadFile(filename, "bin", data, &datalen); - //int res = loadFileEML( filename, "eml", data, &datalen); - if ( res ) { - free(data); - return 1; - } + res = loadFile(filename, "bin", data, &datalen); + //int res = loadFileEML( filename, "eml", data, &datalen); + if ( res ) { + free(data); + return 1; + } - if (datalen > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); - free(data); - return 1; - } - break; - } + if (datalen > FLASH_MEM_MAX_SIZE) { + PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); + free(data); + return 1; + } + break; + } - data = realloc(data, datalen); + data = realloc(data, datalen); - //Send to device - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = datalen; + //Send to device + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = datalen; - while (bytes_remaining > 0){ - uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + while (bytes_remaining > 0){ + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; + UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; - memcpy(c.d.asBytes, data + bytes_sent, bytes_in_packet); - clearCommandBuffer(); - SendCommand(&c); + memcpy(c.d.asBytes, data + bytes_sent, bytes_in_packet); + clearCommandBuffer(); + SendCommand(&c); - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - free(data); - return 1; - } + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + free(data); + return 1; + } - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); + uint8_t isok = resp.arg[0] & 0xFF; + if (!isok) + PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - } - free(data); + } + free(data); - PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); - return 0; + PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); + return 0; } int CmdFlashMemSave(const char *Cmd){ - char filename[FILE_PATH_SIZE] = {0}; - uint8_t cmdp = 0; - bool errors = false; - uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; + char filename[FILE_PATH_SIZE] = {0}; + uint8_t cmdp = 0; + bool errors = false; + uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_save(); - case 'l': - len = param_get32ex(Cmd, cmdp+1, FLASH_MEM_MAX_SIZE, 10); - cmdp += 2; - break; - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'f': - //File handling - if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_flashmem_save(); + case 'l': + len = param_get32ex(Cmd, cmdp+1, FLASH_MEM_MAX_SIZE, 10); + cmdp += 2; + break; + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'f': + //File handling + if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { + PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + break; + } + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_save(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_save(); - uint8_t* dump = calloc(len, sizeof(uint8_t)); - if (!dump) { - PrintAndLogDevice(WARNING, "error, cannot allocate memory "); - return 1; - } + uint8_t* dump = calloc(len, sizeof(uint8_t)); + if (!dump) { + PrintAndLogDevice(WARNING, "error, cannot allocate memory "); + return 1; + } - PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len); - if ( !GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true) ) { - PrintAndLogEx(FAILED, "ERROR; downloading flashmem"); - free(dump); - return 1; - } + PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len); + if ( !GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true) ) { + PrintAndLogEx(FAILED, "ERROR; downloading flashmem"); + free(dump); + return 1; + } - saveFile(filename, "bin", dump, len); - saveFileEML(filename, "eml", dump, len, 16); - free(dump); - return 0; + saveFile(filename, "bin", dump, len); + saveFileEML(filename, "eml", dump, len, 16); + free(dump); + return 0; } int CmdFlashMemWipe(const char *Cmd){ - uint8_t cmdp = 0; - bool errors = false; - bool initalwipe = false; - uint8_t page = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_wipe(); - case 'p': - page = param_get8ex(Cmd, cmdp+1, 0, 10); - if ( page > 2 ) { - PrintAndLogEx(WARNING, "page must be 0, 1 or 2"); - errors = true; - break; - } - cmdp += 2; - break; - case 'i': - initalwipe = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + uint8_t cmdp = 0; + bool errors = false; + bool initalwipe = false; + uint8_t page = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_flashmem_wipe(); + case 'p': + page = param_get8ex(Cmd, cmdp+1, 0, 10); + if ( page > 2 ) { + PrintAndLogEx(WARNING, "page must be 0, 1 or 2"); + errors = true; + break; + } + cmdp += 2; + break; + case 'i': + initalwipe = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_wipe(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_wipe(); - UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 8000) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; - } - uint8_t isok = resp.arg[0] & 0xFF; - if (isok) - PrintAndLogEx(SUCCESS, "Flash WIPE ok"); - else - PrintAndLogEx(FAILED, "Flash WIPE failed"); + UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 8000) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return 1; + } + uint8_t isok = resp.arg[0] & 0xFF; + if (isok) + PrintAndLogEx(SUCCESS, "Flash WIPE ok"); + else + PrintAndLogEx(FAILED, "Flash WIPE failed"); - return 0; + return 0; } int CmdFlashMemInfo(const char *Cmd){ - uint8_t sha_hash[20] = {0}; - mbedtls_rsa_context rsa; + uint8_t sha_hash[20] = {0}; + mbedtls_rsa_context rsa; - uint8_t cmdp = 0; - bool errors = false, shall_write = false, shall_sign = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_info(); - case 's': { - shall_sign = true; - cmdp++; - break; - } - case 'w': - shall_write = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + uint8_t cmdp = 0; + bool errors = false, shall_write = false, shall_sign = false; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_flashmem_info(); + case 's': { + shall_sign = true; + cmdp++; + break; + } + case 'w': + shall_write = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors ) return usage_flashmem_info(); + //Validations + if (errors ) return usage_flashmem_info(); - UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; - } + UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return 1; + } - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) { - PrintAndLogEx(FAILED, "failed"); - return 1; - } + uint8_t isok = resp.arg[0] & 0xFF; + if (!isok) { + PrintAndLogEx(FAILED, "failed"); + return 1; + } - // validate signature here - rdv40_validation_t mem; - memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t)); + // validate signature here + rdv40_validation_t mem; + memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t)); - // Flash ID hash (sha1) - mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); + // Flash ID hash (sha1) + mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); - // print header - PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid) )); - PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash))); - PrintAndLogEx(INFO, "RSA SIGNATURE |"); - print_hex_break( mem.signature, sizeof(mem.signature), 32); + // print header + PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid) )); + PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash))); + PrintAndLogEx(INFO, "RSA SIGNATURE |"); + print_hex_break( mem.signature, sizeof(mem.signature), 32); //------------------------------------------------------------------------------- // Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c) @@ -514,98 +514,98 @@ int CmdFlashMemInfo(const char *Cmd){ #define KEY_LEN 128 - mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); + mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); - rsa.len = KEY_LEN; + rsa.len = KEY_LEN; - mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ); - mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ); - mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ); - mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ); - mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ); - mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ); - mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ); - mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); + mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ); + mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ); + mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ); + mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ); + mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ); + mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ); + mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ); + mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); - PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); + PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); - bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 ); - if (is_keyok) - PrintAndLogEx(SUCCESS, "RSA key validation ok"); - else - PrintAndLogEx(FAILED, "RSA key validation failed"); + bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 ); + if (is_keyok) + PrintAndLogEx(SUCCESS, "RSA key validation ok"); + else + PrintAndLogEx(FAILED, "RSA key validation failed"); - // - uint8_t from_device[KEY_LEN]; - uint8_t sign[KEY_LEN]; + // + uint8_t from_device[KEY_LEN]; + uint8_t sign[KEY_LEN]; - // to be verified - memcpy(from_device, mem.signature, KEY_LEN); + // to be verified + memcpy(from_device, mem.signature, KEY_LEN); - // to be signed (all zeros - memset(sign, 0, KEY_LEN); + // to be signed (all zeros + memset(sign, 0, KEY_LEN); - // Signing (private key) - if (shall_sign) { + // Signing (private key) + if (shall_sign) { - int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign ); - if (is_signed == 0) - PrintAndLogEx(SUCCESS, "RSA Signing ok"); - else - PrintAndLogEx(FAILED, "RSA Signing failed"); + int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign ); + if (is_signed == 0) + PrintAndLogEx(SUCCESS, "RSA Signing ok"); + else + PrintAndLogEx(FAILED, "RSA Signing failed"); - if (shall_write) { - // save to mem - c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; - memcpy(c.d.asBytes, sign, sizeof(sign)); - clearCommandBuffer(); - SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - } else { + if (shall_write) { + // save to mem + c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; + memcpy(c.d.asBytes, sign, sizeof(sign)); + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + } else { - if (!resp.arg[0]) - PrintAndLogEx(FAILED, "Writing signature failed"); - else - PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET); + if (!resp.arg[0]) + PrintAndLogEx(FAILED, "Writing signature failed"); + else + PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET); - } - } - PrintAndLogEx(INFO, "Signed | "); - print_hex_break( sign, sizeof(sign), 32); - } + } + } + PrintAndLogEx(INFO, "Signed | "); + print_hex_break( sign, sizeof(sign), 32); + } - // Verify (public key) - int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device ); - if (is_verified == 0) - PrintAndLogEx(SUCCESS, "RSA Verification ok"); - else - PrintAndLogEx(FAILED, "RSA Verification failed"); + // Verify (public key) + int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device ); + if (is_verified == 0) + PrintAndLogEx(SUCCESS, "RSA Verification ok"); + else + PrintAndLogEx(FAILED, "RSA Verification failed"); - mbedtls_rsa_free(&rsa); - return 0; + mbedtls_rsa_free(&rsa); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"spibaud", CmdFlashmemSpiBaudrate, 1, "Set Flash memory Spi baudrate [rdv40]"}, - {"read", CmdFlashMemRead, 1, "Read Flash memory [rdv40]"}, - {"info", CmdFlashMemInfo, 1, "Flash memory information [rdv40]"}, - {"load", CmdFlashMemLoad, 1, "Load data into flash memory [rdv40]"}, - {"save", CmdFlashMemSave, 1, "Save data from flash memory [rdv40]"}, - {"wipe", CmdFlashMemWipe, 1, "Wipe data from flash memory [rdv40]"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"spibaud", CmdFlashmemSpiBaudrate, 1, "Set Flash memory Spi baudrate [rdv40]"}, + {"read", CmdFlashMemRead, 1, "Read Flash memory [rdv40]"}, + {"info", CmdFlashMemInfo, 1, "Flash memory information [rdv40]"}, + {"load", CmdFlashMemLoad, 1, "Load data into flash memory [rdv40]"}, + {"save", CmdFlashMemSave, 1, "Save data from flash memory [rdv40]"}, + {"wipe", CmdFlashMemWipe, 1, "Wipe data from flash memory [rdv40]"}, + {NULL, NULL, 0, NULL} }; int CmdFlashMem(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } #endif diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index ee661bf18..c7c6f8979 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -22,15 +22,15 @@ #include "cmdparser.h" #include "common.h" #include "util.h" -#include "util_posix.h" // msclock -#include "loclass/fileutils.h" //saveFile -#include "comms.h" //getfromdevice +#include "util_posix.h" // msclock +#include "loclass/fileutils.h" //saveFile +#include "comms.h" //getfromdevice typedef enum { - DICTIONARY_NONE = 0, - DICTIONARY_MIFARE, - DICTIONARY_T55XX, - DICTIONARY_ICLASS + DICTIONARY_NONE = 0, + DICTIONARY_MIFARE, + DICTIONARY_T55XX, + DICTIONARY_ICLASS } Dictionary_t; extern int CmdFlashMem(const char *Cmd); diff --git a/client/cmdhf.c b/client/cmdhf.c index 6931f5c14..475a2659d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -13,128 +13,128 @@ static int CmdHelp(const char *Cmd); int usage_hf_search(){ - PrintAndLogEx(NORMAL, "Usage: hf search"); - PrintAndLogEx(NORMAL, "Will try to find a HF read out of the unknown tag. Stops when found."); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, ""); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf search"); + PrintAndLogEx(NORMAL, "Will try to find a HF read out of the unknown tag. Stops when found."); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, ""); + return 0; } int usage_hf_snoop(){ - PrintAndLogEx(NORMAL, "Usage: hf snoop "); - PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for snooped data"); - PrintAndLogEx(NORMAL, "User the 'data samples' command to download from device, and 'data plot' to look at it"); - PrintAndLogEx(NORMAL, "Press button to quit the snooping."); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, " - skip sample pairs"); - PrintAndLogEx(NORMAL, " - skip number of triggers"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf snoop"); - PrintAndLogEx(NORMAL, " hf snoop 1000 0"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf snoop "); + PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for snooped data"); + PrintAndLogEx(NORMAL, "User the 'data samples' command to download from device, and 'data plot' to look at it"); + PrintAndLogEx(NORMAL, "Press button to quit the snooping."); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " - skip sample pairs"); + PrintAndLogEx(NORMAL, " - skip number of triggers"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf snoop"); + PrintAndLogEx(NORMAL, " hf snoop 1000 0"); + return 0; } int CmdHFSearch(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_search(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_search(); - int ans = CmdHF14AInfo("s"); - if (ans > 0) { - PrintAndLogEx(SUCCESS, "\nValid ISO14443-A Tag Found\n"); - return ans; - } - ans = HF15Reader("", false); - if (ans) { - PrintAndLogEx(SUCCESS, "\nValid ISO15693 Tag Found\n"); - return ans; - } - ans = HFLegicReader("", false); - if ( ans == 0) { - PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n"); - return 1; - } - ans = CmdHFTopazReader("s"); - if (ans == 0) { - PrintAndLogEx(SUCCESS, "\nValid Topaz Tag Found\n"); - return 1; - } - // 14b and iclass is the longest test (put last) - ans = HF14BReader(false); //CmdHF14BReader("s"); - if (ans) { - PrintAndLogEx(SUCCESS, "\nValid ISO14443-B Tag Found\n"); - return ans; - } - ans = HFiClassReader("", false, false); - if (ans) { - PrintAndLogEx(SUCCESS, "\nValid iClass Tag (or PicoPass Tag) Found\n"); - return ans; - } + int ans = CmdHF14AInfo("s"); + if (ans > 0) { + PrintAndLogEx(SUCCESS, "\nValid ISO14443-A Tag Found\n"); + return ans; + } + ans = HF15Reader("", false); + if (ans) { + PrintAndLogEx(SUCCESS, "\nValid ISO15693 Tag Found\n"); + return ans; + } + ans = HFLegicReader("", false); + if ( ans == 0) { + PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n"); + return 1; + } + ans = CmdHFTopazReader("s"); + if (ans == 0) { + PrintAndLogEx(SUCCESS, "\nValid Topaz Tag Found\n"); + return 1; + } + // 14b and iclass is the longest test (put last) + ans = HF14BReader(false); //CmdHF14BReader("s"); + if (ans) { + PrintAndLogEx(SUCCESS, "\nValid ISO14443-B Tag Found\n"); + return ans; + } + ans = HFiClassReader("", false, false); + if (ans) { + PrintAndLogEx(SUCCESS, "\nValid iClass Tag (or PicoPass Tag) Found\n"); + return ans; + } - /* - ans = CmdHFFelicaReader("s"); - if (ans) { - PrintAndLogEx(NORMAL, "\nValid ISO18092 / FeliCa Found\n"); - return ans; - } - */ + /* + ans = CmdHFFelicaReader("s"); + if (ans) { + PrintAndLogEx(NORMAL, "\nValid ISO18092 / FeliCa Found\n"); + return ans; + } + */ - PrintAndLogEx(FAILED, "\nno known/supported 13.56 MHz tags found\n"); - return 0; + PrintAndLogEx(FAILED, "\nno known/supported 13.56 MHz tags found\n"); + return 0; } int CmdHFTune(const char *Cmd) { - PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit"); - UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit"); + UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHFSnoop(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_snoop(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_snoop(); - int skippairs = param_get32ex(Cmd, 0, 0, 10); - int skiptriggers = param_get32ex(Cmd, 1, 0, 10); + int skippairs = param_get32ex(Cmd, 0, 0, 10); + int skiptriggers = param_get32ex(Cmd, 1, 0, 10); - UsbCommand c = {CMD_HF_SNIFFER, {skippairs, skiptriggers, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_HF_SNIFFER, {skippairs, skiptriggers, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, - {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, - {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, - {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, - {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, - {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, - {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, - {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, - {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, - {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, - {"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"}, - {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, - {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, - {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, - {"snoop", CmdHFSnoop, 0, " Generic HF Snoop"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, + {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, + {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, + {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, + {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, + {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, + {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"}, + {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, + {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, + {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, + {"snoop", CmdHFSnoop, 0, " Generic HF Snoop"}, + {NULL, NULL, 0, NULL} }; int CmdHF(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdhf.h b/client/cmdhf.h index b2dcc10f1..6511cc2b8 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -18,20 +18,20 @@ #include "graph.h" #include "ui.h" #include "cmdparser.h" -#include "cmdhf14a.h" // ISO14443-A -#include "cmdhf14b.h" // ISO14443-B -#include "cmdhf15.h" // ISO15693 +#include "cmdhf14a.h" // ISO14443-A +#include "cmdhf14b.h" // ISO14443-B +#include "cmdhf15.h" // ISO15693 #include "cmdhfepa.h" -#include "cmdhflegic.h" // LEGIC -#include "cmdhficlass.h" // ICLASS -#include "cmdhfmf.h" // CLASSIC -#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc -#include "cmdhfmfp.h" // Mifare Plus -#include "cmdhfmfdes.h" // DESFIRE -#include "cmdhftopaz.h" // TOPAZ -#include "cmdhffelica.h" // ISO18092 / FeliCa -#include "cmdhffido.h" // FIDO authenticators -#include "cmdtrace.h" // trace list +#include "cmdhflegic.h" // LEGIC +#include "cmdhficlass.h" // ICLASS +#include "cmdhfmf.h" // CLASSIC +#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc +#include "cmdhfmfp.h" // Mifare Plus +#include "cmdhfmfdes.h" // DESFIRE +#include "cmdhftopaz.h" // TOPAZ +#include "cmdhffelica.h" // ISO18092 / FeliCa +#include "cmdhffido.h" // FIDO authenticators +#include "cmdtrace.h" // trace list extern int CmdHF(const char *Cmd); extern int CmdHFTune(const char *Cmd); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 98a6168b2..d88746e3f 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -18,135 +18,135 @@ static int CmdHelp(const char *Cmd); static int waitCmd(uint8_t iLen); static const manufactureName manufactureMapping[] = { - // ID, "Vendor Country" - { 0x01, "Motorola UK" }, - { 0x02, "ST Microelectronics SA France" }, - { 0x03, "Hitachi, Ltd Japan" }, - { 0x04, "NXP Semiconductors Germany" }, - { 0x05, "Infineon Technologies AG Germany" }, - { 0x06, "Cylink USA" }, - { 0x07, "Texas Instrument France" }, - { 0x08, "Fujitsu Limited Japan" }, - { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, - { 0x0A, "NEC Japan" }, - { 0x0B, "Oki Electric Industry Co. Ltd Japan" }, - { 0x0C, "Toshiba Corp. Japan" }, - { 0x0D, "Mitsubishi Electric Corp. Japan" }, - { 0x0E, "Samsung Electronics Co. Ltd Korea" }, - { 0x0F, "Hynix / Hyundai, Korea" }, - { 0x10, "LG-Semiconductors Co. Ltd Korea" }, - { 0x11, "Emosyn-EM Microelectronics USA" }, - { 0x12, "INSIDE Technology France" }, - { 0x13, "ORGA Kartensysteme GmbH Germany" }, - { 0x14, "SHARP Corporation Japan" }, - { 0x15, "ATMEL France" }, - { 0x16, "EM Microelectronic-Marin SA Switzerland" }, - { 0x17, "KSW Microtec GmbH Germany" }, - { 0x18, "ZMD AG Germany" }, - { 0x19, "XICOR, Inc. USA" }, - { 0x1A, "Sony Corporation Japan" }, - { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, - { 0x1C, "Emosyn USA" }, - { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, - { 0x1E, "Magellan Technology Pty Limited Australia" }, - { 0x1F, "Melexis NV BO Switzerland" }, - { 0x20, "Renesas Technology Corp. Japan" }, - { 0x21, "TAGSYS France" }, - { 0x22, "Transcore USA" }, - { 0x23, "Shanghai belling corp., ltd. China" }, - { 0x24, "Masktech Germany Gmbh Germany" }, - { 0x25, "Innovision Research and Technology Plc UK" }, - { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" }, - { 0x27, "Cypak AB Sweden" }, - { 0x28, "Ricoh Japan" }, - { 0x29, "ASK France" }, - { 0x2A, "Unicore Microsystems, LLC Russian Federation" }, - { 0x2B, "Dallas Semiconductor/Maxim USA" }, - { 0x2C, "Impinj, Inc. USA" }, - { 0x2D, "RightPlug Alliance USA" }, - { 0x2E, "Broadcom Corporation USA" }, - { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" }, - { 0x30, "BeeDar Technology Inc. USA" }, - { 0x31, "RFIDsec Denmark" }, - { 0x32, "Schweizer Electronic AG Germany" }, - { 0x33, "AMIC Technology Corp Taiwan" }, - { 0x34, "Mikron JSC Russia" }, - { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" }, - { 0x36, "IDS Microchip AG Switzerland" }, - { 0x37, "Kovio USA" }, - { 0x38, "HMT Microelectronic Ltd Switzerland" }, - { 0x39, "Silicon Craft Technology Thailand" }, - { 0x3A, "Advanced Film Device Inc. Japan" }, - { 0x3B, "Nitecrest Ltd UK" }, - { 0x3C, "Verayo Inc. USA" }, - { 0x3D, "HID Global USA" }, - { 0x3E, "Productivity Engineering Gmbh Germany" }, - { 0x3F, "Austriamicrosystems AG (reserved) Austria" }, - { 0x40, "Gemalto SA France" }, - { 0x41, "Renesas Electronics Corporation Japan" }, - { 0x42, "3Alogics Inc Korea" }, - { 0x43, "Top TroniQ Asia Limited Hong Kong" }, - { 0x44, "Gentag Inc. USA" }, - { 0x45, "Invengo Information Technology Co.Ltd China" }, - { 0x46, "Guangzhou Sysur Microelectronics, Inc China" }, - { 0x47, "CEITEC S.A. Brazil" }, - { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" }, - { 0x49, "MediaTek Inc Taiwan" }, - { 0x4A, "Angstrem PJSC Russia" }, - { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" }, - { 0x4C, "LEGIC Identsystems AG Switzerland" }, - { 0x4D, "Balluff GmbH Germany" }, - { 0x4E, "Oberthur Technologies France" }, - { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" }, - { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" }, - { 0x51, "Giesecke & Devrient GmbH Germany" }, - { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" }, - { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" }, - { 0x54, "Intel Corporation USA" }, - { 0x55, "Microsensys GmbH Germany" }, - { 0x56, "Sonix Technology Co., Ltd. Taiwan" }, - { 0x57, "Qualcomm Technologies Inc USA" }, - { 0x58, "Realtek Semiconductor Corp Taiwan" }, - { 0x59, "Freevision Technologies Co. Ltd China" }, - { 0x5A, "Giantec Semiconductor Inc. China" }, - { 0x5B, "JSC Angstrem-T Russia" }, - { 0x5C, "STARCHIP France" }, - { 0x5D, "SPIRTECH France" }, - { 0x5E, "GANTNER Electronic GmbH Austria" }, - { 0x5F, "Nordic Semiconductor Norway" }, - { 0x60, "Verisiti Inc USA" }, - { 0x61, "Wearlinks Technology Inc. China" }, - { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, - { 0x63, "Pragmatic Printing Ltd. UK" }, - { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, - { 0x65, "Tendyron Corporation China" }, - { 0x66, "MUTO Smart Co., Ltd. Korea" }, - { 0x67, "ON Semiconductor USA" }, - { 0x68, "TUBITAK BILGEM Turkey" }, - { 0x69, "Huada Semiconductor Co., Ltd China" }, - { 0x6A, "SEVENEY France" }, - { 0x6B, "ISSM France" }, - { 0x6C, "Wisesec Ltd Israel" }, - { 0x7C, "DB HiTek Co Ltd Korea" }, - { 0x7D, "SATO Vicinity Australia" }, - { 0x7E, "Holtek Taiwan" }, - { 0x00, "no tag-info available" } // must be the last entry + // ID, "Vendor Country" + { 0x01, "Motorola UK" }, + { 0x02, "ST Microelectronics SA France" }, + { 0x03, "Hitachi, Ltd Japan" }, + { 0x04, "NXP Semiconductors Germany" }, + { 0x05, "Infineon Technologies AG Germany" }, + { 0x06, "Cylink USA" }, + { 0x07, "Texas Instrument France" }, + { 0x08, "Fujitsu Limited Japan" }, + { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, + { 0x0A, "NEC Japan" }, + { 0x0B, "Oki Electric Industry Co. Ltd Japan" }, + { 0x0C, "Toshiba Corp. Japan" }, + { 0x0D, "Mitsubishi Electric Corp. Japan" }, + { 0x0E, "Samsung Electronics Co. Ltd Korea" }, + { 0x0F, "Hynix / Hyundai, Korea" }, + { 0x10, "LG-Semiconductors Co. Ltd Korea" }, + { 0x11, "Emosyn-EM Microelectronics USA" }, + { 0x12, "INSIDE Technology France" }, + { 0x13, "ORGA Kartensysteme GmbH Germany" }, + { 0x14, "SHARP Corporation Japan" }, + { 0x15, "ATMEL France" }, + { 0x16, "EM Microelectronic-Marin SA Switzerland" }, + { 0x17, "KSW Microtec GmbH Germany" }, + { 0x18, "ZMD AG Germany" }, + { 0x19, "XICOR, Inc. USA" }, + { 0x1A, "Sony Corporation Japan" }, + { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, + { 0x1C, "Emosyn USA" }, + { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, + { 0x1E, "Magellan Technology Pty Limited Australia" }, + { 0x1F, "Melexis NV BO Switzerland" }, + { 0x20, "Renesas Technology Corp. Japan" }, + { 0x21, "TAGSYS France" }, + { 0x22, "Transcore USA" }, + { 0x23, "Shanghai belling corp., ltd. China" }, + { 0x24, "Masktech Germany Gmbh Germany" }, + { 0x25, "Innovision Research and Technology Plc UK" }, + { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" }, + { 0x27, "Cypak AB Sweden" }, + { 0x28, "Ricoh Japan" }, + { 0x29, "ASK France" }, + { 0x2A, "Unicore Microsystems, LLC Russian Federation" }, + { 0x2B, "Dallas Semiconductor/Maxim USA" }, + { 0x2C, "Impinj, Inc. USA" }, + { 0x2D, "RightPlug Alliance USA" }, + { 0x2E, "Broadcom Corporation USA" }, + { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" }, + { 0x30, "BeeDar Technology Inc. USA" }, + { 0x31, "RFIDsec Denmark" }, + { 0x32, "Schweizer Electronic AG Germany" }, + { 0x33, "AMIC Technology Corp Taiwan" }, + { 0x34, "Mikron JSC Russia" }, + { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" }, + { 0x36, "IDS Microchip AG Switzerland" }, + { 0x37, "Kovio USA" }, + { 0x38, "HMT Microelectronic Ltd Switzerland" }, + { 0x39, "Silicon Craft Technology Thailand" }, + { 0x3A, "Advanced Film Device Inc. Japan" }, + { 0x3B, "Nitecrest Ltd UK" }, + { 0x3C, "Verayo Inc. USA" }, + { 0x3D, "HID Global USA" }, + { 0x3E, "Productivity Engineering Gmbh Germany" }, + { 0x3F, "Austriamicrosystems AG (reserved) Austria" }, + { 0x40, "Gemalto SA France" }, + { 0x41, "Renesas Electronics Corporation Japan" }, + { 0x42, "3Alogics Inc Korea" }, + { 0x43, "Top TroniQ Asia Limited Hong Kong" }, + { 0x44, "Gentag Inc. USA" }, + { 0x45, "Invengo Information Technology Co.Ltd China" }, + { 0x46, "Guangzhou Sysur Microelectronics, Inc China" }, + { 0x47, "CEITEC S.A. Brazil" }, + { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" }, + { 0x49, "MediaTek Inc Taiwan" }, + { 0x4A, "Angstrem PJSC Russia" }, + { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" }, + { 0x4C, "LEGIC Identsystems AG Switzerland" }, + { 0x4D, "Balluff GmbH Germany" }, + { 0x4E, "Oberthur Technologies France" }, + { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" }, + { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" }, + { 0x51, "Giesecke & Devrient GmbH Germany" }, + { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" }, + { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" }, + { 0x54, "Intel Corporation USA" }, + { 0x55, "Microsensys GmbH Germany" }, + { 0x56, "Sonix Technology Co., Ltd. Taiwan" }, + { 0x57, "Qualcomm Technologies Inc USA" }, + { 0x58, "Realtek Semiconductor Corp Taiwan" }, + { 0x59, "Freevision Technologies Co. Ltd China" }, + { 0x5A, "Giantec Semiconductor Inc. China" }, + { 0x5B, "JSC Angstrem-T Russia" }, + { 0x5C, "STARCHIP France" }, + { 0x5D, "SPIRTECH France" }, + { 0x5E, "GANTNER Electronic GmbH Austria" }, + { 0x5F, "Nordic Semiconductor Norway" }, + { 0x60, "Verisiti Inc USA" }, + { 0x61, "Wearlinks Technology Inc. China" }, + { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, + { 0x63, "Pragmatic Printing Ltd. UK" }, + { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, + { 0x65, "Tendyron Corporation China" }, + { 0x66, "MUTO Smart Co., Ltd. Korea" }, + { 0x67, "ON Semiconductor USA" }, + { 0x68, "TUBITAK BILGEM Turkey" }, + { 0x69, "Huada Semiconductor Co., Ltd China" }, + { 0x6A, "SEVENEY France" }, + { 0x6B, "ISSM France" }, + { 0x6C, "Wisesec Ltd Israel" }, + { 0x7C, "DB HiTek Co Ltd Korea" }, + { 0x7D, "SATO Vicinity Australia" }, + { 0x7E, "Holtek Taiwan" }, + { 0x00, "no tag-info available" } // must be the last entry }; // get a product description based on the UID -// uid[8] tag uid +// uid[8] tag uid // returns description of the best match char* getTagInfo(uint8_t uid) { - int i; - int len = sizeof(manufactureMapping) / sizeof(manufactureName); + int i; + int len = sizeof(manufactureMapping) / sizeof(manufactureName); - for ( i = 0; i < len; ++i ) - if ( uid == manufactureMapping[i].uid) - return manufactureMapping[i].desc; + for ( i = 0; i < len; ++i ) + if ( uid == manufactureMapping[i].uid) + return manufactureMapping[i].desc; - //No match, return default - return manufactureMapping[len-1].desc; + //No match, return default + return manufactureMapping[len-1].desc; } // iso14a apdu input frame length @@ -154,647 +154,647 @@ static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; int usage_hf_14a_sim(void) { -// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); - PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [x] [e] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " t : 1 = MIFARE Classic 1k"); - PrintAndLogEx(NORMAL, " 2 = MIFARE Ultralight"); - PrintAndLogEx(NORMAL, " 3 = MIFARE Desfire"); - PrintAndLogEx(NORMAL, " 4 = ISO/IEC 14443-4"); - PrintAndLogEx(NORMAL, " 5 = MIFARE Tnp3xxx"); - PrintAndLogEx(NORMAL, " 6 = MIFARE Mini"); - PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080"); - PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k"); - PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); -// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); - PrintAndLogEx(NORMAL, " u : 4, 7 byte UID"); - PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); - PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); - PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344 x"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344556677"); -// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n"); - return 0; +// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); + PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n"); + PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [x] [e] [v]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " t : 1 = MIFARE Classic 1k"); + PrintAndLogEx(NORMAL, " 2 = MIFARE Ultralight"); + PrintAndLogEx(NORMAL, " 3 = MIFARE Desfire"); + PrintAndLogEx(NORMAL, " 4 = ISO/IEC 14443-4"); + PrintAndLogEx(NORMAL, " 5 = MIFARE Tnp3xxx"); + PrintAndLogEx(NORMAL, " 6 = MIFARE Mini"); + PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080"); + PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k"); + PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); +// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); + PrintAndLogEx(NORMAL, " u : 4, 7 byte UID"); + PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); + PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); + PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344 x"); + PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344"); + PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344556677"); +// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n"); + return 0; } int usage_hf_14a_sniff(void) { - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]"); - PrintAndLogEx(NORMAL, "c - triggered by first data from card"); - PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf 14a sniff c r"); - return 0; + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); + PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'"); + PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]"); + PrintAndLogEx(NORMAL, "c - triggered by first data from card"); + PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf 14a sniff c r"); + return 0; } int usage_hf_14a_raw(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] [-b] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); - PrintAndLogEx(NORMAL, " -a active signal field ON without select"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - PrintAndLogEx(NORMAL, " -b number of bits to send. Useful for send partial byte"); - PrintAndLogEx(NORMAL, " -t timeout in ms"); - PrintAndLogEx(NORMAL, " -T use Topaz protocol to send command"); - PrintAndLogEx(NORMAL, " -3 ISO14443-3 select only (skip RATS)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] [-b] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -r do not read response"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); + PrintAndLogEx(NORMAL, " -a active signal field ON without select"); + PrintAndLogEx(NORMAL, " -s active signal field ON with select"); + PrintAndLogEx(NORMAL, " -b number of bits to send. Useful for send partial byte"); + PrintAndLogEx(NORMAL, " -t timeout in ms"); + PrintAndLogEx(NORMAL, " -T use Topaz protocol to send command"); + PrintAndLogEx(NORMAL, " -3 ISO14443-3 select only (skip RATS)"); + return 0; } int usage_hf_14a_reader(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]"); - PrintAndLogEx(NORMAL, " k keep the field active after command executed"); - PrintAndLogEx(NORMAL, " s silent (no messages)"); - PrintAndLogEx(NORMAL, " x just drop the signal field"); - PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]"); + PrintAndLogEx(NORMAL, " k keep the field active after command executed"); + PrintAndLogEx(NORMAL, " s silent (no messages)"); + PrintAndLogEx(NORMAL, " x just drop the signal field"); + PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)"); + return 0; } int usage_hf_14a_info(void){ - PrintAndLogEx(NORMAL, "This command makes more extensive tests against a ISO14443a tag in order to collect information"); - PrintAndLogEx(NORMAL, "Usage: hf 14a info [h|s]"); - PrintAndLogEx(NORMAL, " s silent (no messages)"); - PrintAndLogEx(NORMAL, " n test for nack bug"); - return 0; + PrintAndLogEx(NORMAL, "This command makes more extensive tests against a ISO14443a tag in order to collect information"); + PrintAndLogEx(NORMAL, "Usage: hf 14a info [h|s]"); + PrintAndLogEx(NORMAL, " s silent (no messages)"); + PrintAndLogEx(NORMAL, " n test for nack bug"); + return 0; } int CmdHF14AList(const char *Cmd) { - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); - CmdTraceList("14a"); - return 0; + //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); + CmdTraceList("14a"); + return 0; } int Hf14443_4aGetCardData(iso14a_card_select_t * card) { - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; - SendCommand(&c); + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); - memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - if(select_status == 0) { - PrintAndLog("E->iso14443a card select failed"); - return 1; - } + if(select_status == 0) { + PrintAndLog("E->iso14443a card select failed"); + return 1; + } - if(select_status == 2) { - PrintAndLog("E->Card doesn't support iso14443-4 mode"); - return 1; - } + if(select_status == 2) { + PrintAndLog("E->Card doesn't support iso14443-4 mode"); + return 1; + } - if(select_status == 3) { - PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); - PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); - return 1; - } + if(select_status == 3) { + PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); + PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); + return 1; + } - PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen)); - PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]); - PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); - if(card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); - return 1; - } - PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); + PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen)); + PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]); + PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); + if(card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); + return 1; + } + PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); - return 0; + return 0; } int CmdHF14AReader(const char *Cmd) { - uint32_t cm = ISO14A_CONNECT; - bool disconnectAfter = true, silent = false; - int cmdp = 0; + uint32_t cm = ISO14A_CONNECT; + bool disconnectAfter = true, silent = false; + int cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_14a_reader(); - case '3': - cm |= ISO14A_NO_RATS; - break; - case 'k': - disconnectAfter = false; - break; - case 's': - silent = true; - break; - case 'x': - cm &= ~ISO14A_CONNECT; - break; - default: - PrintAndLogEx(WARNING, "Unknown command."); - return 1; - } - cmdp++; - } + while (param_getchar(Cmd, cmdp) != 0x00) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_14a_reader(); + case '3': + cm |= ISO14A_NO_RATS; + break; + case 'k': + disconnectAfter = false; + break; + case 's': + silent = true; + break; + case 'x': + cm &= ~ISO14A_CONNECT; + break; + default: + PrintAndLogEx(WARNING, "Unknown command."); + return 1; + } + cmdp++; + } - if (!disconnectAfter) - cm |= ISO14A_NO_DISCONNECT; + if (!disconnectAfter) + cm |= ISO14A_NO_DISCONNECT; - UsbCommand c = {CMD_READER_ISO_14443a, {cm, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_READER_ISO_14443a, {cm, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); - if (ISO14A_CONNECT & cm) { - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 1; - } + if (ISO14A_CONNECT & cm) { + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 1; + } - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - /* - 0: couldn't read - 1: OK, with ATS - 2: OK, no ATS - 3: proprietary Anticollision - */ - uint64_t select_status = resp.arg[0]; + /* + 0: couldn't read + 1: OK, with ATS + 2: OK, no ATS + 3: proprietary Anticollision + */ + uint64_t select_status = resp.arg[0]; - if (select_status == 0) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 1; - } + if (select_status == 0) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 1; + } - if (select_status == 3) { - PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - DropField(); - return 1; - } + if (select_status == 3) { + PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + DropField(); + return 1; + } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); - if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); - } + if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + } - if (!disconnectAfter) { - if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands"); - } - } + if (!disconnectAfter) { + if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands"); + } + } - if (disconnectAfter) { - if (!silent) PrintAndLogEx(SUCCESS, "field dropped."); - } + if (disconnectAfter) { + if (!silent) PrintAndLogEx(SUCCESS, "field dropped."); + } - return 0; + return 0; } int CmdHF14AInfo(const char *Cmd) { - if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_hf_14a_info(); + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_hf_14a_info(); - bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); - bool do_nack_test = (Cmd[0] == 'n' || Cmd[0] == 'N'); + bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); + bool do_nack_test = (Cmd[0] == 'n' || Cmd[0] == 'N'); - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 0; - } + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 0; + } - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - /* - 0: couldn't read - 1: OK, with ATS - 2: OK, no ATS - 3: proprietary Anticollision - */ - uint64_t select_status = resp.arg[0]; + /* + 0: couldn't read + 1: OK, with ATS + 2: OK, no ATS + 3: proprietary Anticollision + */ + uint64_t select_status = resp.arg[0]; - if (select_status == 0) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 0; - } + if (select_status == 0) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 0; + } - if (select_status == 3) { - PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - DropField(); - return select_status; - } + if (select_status == 3) { + PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + DropField(); + return select_status; + } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); - bool isMifareClassic = true; - switch (card.sak) { - case 0x00: - isMifareClassic = false; + bool isMifareClassic = true; + switch (card.sak) { + case 0x00: + isMifareClassic = false; - // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) - DropField(); + // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) + DropField(); - uint32_t tagT = GetHF14AMfU_Type(); - if (tagT != UL_ERROR) - ul_print_type(tagT, 0); - else - PrintAndLogEx(NORMAL, "TYPE: Possible AZTEK (iso14443a compliant)"); + uint32_t tagT = GetHF14AMfU_Type(); + if (tagT != UL_ERROR) + ul_print_type(tagT, 0); + else + PrintAndLogEx(NORMAL, "TYPE: Possible AZTEK (iso14443a compliant)"); - // reconnect for further tests - c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT; - c.arg[1] = 0; - c.arg[2] = 0; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK, &resp); + // reconnect for further tests + c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT; + c.arg[1] = 0; + c.arg[2] = 0; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + WaitForResponse(CMD_ACK, &resp); - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS + select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS - if(select_status == 0) { - DropField(); - return 0; - } - break; - case 0x01: PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance"); break; - case 0x04: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; break; - case 0x08: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); break; - case 0x09: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k"); break; - case 0x0A: PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)"); break; - case 0x10: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2"); break; - case 0x11: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2"); break; - case 0x18: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); break; - case 0x20: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; break; - case 0x24: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; break; - case 0x28: PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1"); break; - case 0x38: PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; - case 0x88: PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K"); break; - case 0x98: PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS"); break; - default: ; - } + if(select_status == 0) { + DropField(); + return 0; + } + break; + case 0x01: PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance"); break; + case 0x04: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; break; + case 0x08: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); break; + case 0x09: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k"); break; + case 0x0A: PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)"); break; + case 0x10: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2"); break; + case 0x11: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2"); break; + case 0x18: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); break; + case 0x20: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; break; + case 0x24: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; break; + case 0x28: PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1"); break; + case 0x38: PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; + case 0x88: PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K"); break; + case 0x98: PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS"); break; + default: ; + } - // Double & triple sized UID, can be mapped to a manufacturer. - if ( card.uidlen > 4 ) { - PrintAndLogEx(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0])); - } + // Double & triple sized UID, can be mapped to a manufacturer. + if ( card.uidlen > 4 ) { + PrintAndLogEx(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0])); + } - // try to request ATS even if tag claims not to support it - if (select_status == 2) { - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; - c.arg[1] = 2; - c.arg[2] = 0; - memcpy(c.d.asBytes, rats, 2); - clearCommandBuffer(); - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); + // try to request ATS even if tag claims not to support it + if (select_status == 2) { + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; + c.arg[1] = 2; + c.arg[2] = 0; + memcpy(c.d.asBytes, rats, 2); + clearCommandBuffer(); + SendCommand(&c); + WaitForResponse(CMD_ACK,&resp); - memcpy(card.ats, resp.d.asBytes, resp.arg[0]); - card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes - } + memcpy(card.ats, resp.d.asBytes, resp.arg[0]); + card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes + } - if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - bool ta1 = 0, tb1 = 0, tc1 = 0; - int pos; + if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + bool ta1 = 0, tb1 = 0, tc1 = 0; + int pos; - if (select_status == 2) { - PrintAndLogEx(NORMAL, "SAK incorrectly claims that card doesn't support RATS"); - } - PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); - PrintAndLogEx(NORMAL, " - TL : length is %d bytes", card.ats[0]); - if (card.ats[0] != card.ats_len - 2) { - PrintAndLogEx(NORMAL, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); - } + if (select_status == 2) { + PrintAndLogEx(NORMAL, "SAK incorrectly claims that card doesn't support RATS"); + } + PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + PrintAndLogEx(NORMAL, " - TL : length is %d bytes", card.ats[0]); + if (card.ats[0] != card.ats_len - 2) { + PrintAndLogEx(NORMAL, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); + } - if (card.ats[0] > 1) { // there is a format byte (T0) - ta1 = (card.ats[1] & 0x10) == 0x10; - tb1 = (card.ats[1] & 0x20) == 0x20; - tc1 = (card.ats[1] & 0x40) == 0x40; - int16_t fsci = card.ats[1] & 0x0f; + if (card.ats[0] > 1) { // there is a format byte (T0) + ta1 = (card.ats[1] & 0x10) == 0x10; + tb1 = (card.ats[1] & 0x20) == 0x20; + tc1 = (card.ats[1] & 0x40) == 0x40; + int16_t fsci = card.ats[1] & 0x0f; - PrintAndLogEx(NORMAL, " - T0 : TA1 is%s present, TB1 is%s present, " - "TC1 is%s present, FSCI is %d (FSC = %ld)", - (ta1 ? "" : " NOT"), - (tb1 ? "" : " NOT"), - (tc1 ? "" : " NOT"), - fsci, - fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1 - ); - } - pos = 2; - if (ta1) { - char dr[16], ds[16]; - dr[0] = ds[0] = '\0'; - if (card.ats[pos] & 0x10) strcat(ds, "2, "); - if (card.ats[pos] & 0x20) strcat(ds, "4, "); - if (card.ats[pos] & 0x40) strcat(ds, "8, "); - if (card.ats[pos] & 0x01) strcat(dr, "2, "); - if (card.ats[pos] & 0x02) strcat(dr, "4, "); - if (card.ats[pos] & 0x04) strcat(dr, "8, "); - if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; - if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; - PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, " - "DR: [%s], DS: [%s]", - (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); - pos++; - } - if (tb1) { - uint32_t sfgi = card.ats[pos] & 0x0F; - uint32_t fwi = card.ats[pos] >> 4; - PrintAndLogEx(NORMAL, " - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", - (sfgi), - sfgi ? "" : "(not needed) ", - sfgi ? (1 << 12) << sfgi : 0, - fwi, - (1 << 12) << fwi - ); - pos++; - } - if (tc1) { - PrintAndLogEx(NORMAL, " - TC1 : NAD is%s supported, CID is%s supported", - (card.ats[pos] & 0x01) ? "" : " NOT", - (card.ats[pos] & 0x02) ? "" : " NOT"); - pos++; - } - if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2 ) { - char *tip = ""; - if (card.ats[0] - pos >= 7) { - if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { - tip = "-> MIFARE Plus X 2K or 4K"; - } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { - tip = "-> MIFARE Plus S 2K or 4K"; - } - } - PrintAndLogEx(NORMAL, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); - if (card.ats[pos] == 0xC1) { - PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type"); - PrintAndLogEx(NORMAL, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); - switch (card.ats[pos + 2] & 0xf0) { - case 0x10: PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire"); break; - case 0x20: PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus"); break; - } - switch (card.ats[pos + 2] & 0x0f) { - case 0x00: PrintAndLogEx(NORMAL, " x0 -> <1 kByte"); break; - case 0x01: PrintAndLogEx(NORMAL, " x1 -> 1 kByte"); break; - case 0x02: PrintAndLogEx(NORMAL, " x2 -> 2 kByte"); break; - case 0x03: PrintAndLogEx(NORMAL, " x3 -> 4 kByte"); break; - case 0x04: PrintAndLogEx(NORMAL, " x4 -> 8 kByte"); break; - } - switch (card.ats[pos + 3] & 0xf0) { - case 0x00: PrintAndLogEx(NORMAL, " 0x -> Engineering sample"); break; - case 0x20: PrintAndLogEx(NORMAL, " 2x -> Released"); break; - } - switch (card.ats[pos + 3] & 0x0f) { - case 0x00: PrintAndLogEx(NORMAL, " x0 -> Generation 1"); break; - case 0x01: PrintAndLogEx(NORMAL, " x1 -> Generation 2"); break; - case 0x02: PrintAndLogEx(NORMAL, " x2 -> Generation 3"); break; - } - switch (card.ats[pos + 4] & 0x0f) { - case 0x00: PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported"); break; - case 0x01: PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported"); break; - case 0x0E: PrintAndLogEx(NORMAL, " xE -> no VCS command supported"); break; - } - } - } - } else { - PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); - } + PrintAndLogEx(NORMAL, " - T0 : TA1 is%s present, TB1 is%s present, " + "TC1 is%s present, FSCI is %d (FSC = %ld)", + (ta1 ? "" : " NOT"), + (tb1 ? "" : " NOT"), + (tc1 ? "" : " NOT"), + fsci, + fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1 + ); + } + pos = 2; + if (ta1) { + char dr[16], ds[16]; + dr[0] = ds[0] = '\0'; + if (card.ats[pos] & 0x10) strcat(ds, "2, "); + if (card.ats[pos] & 0x20) strcat(ds, "4, "); + if (card.ats[pos] & 0x40) strcat(ds, "8, "); + if (card.ats[pos] & 0x01) strcat(dr, "2, "); + if (card.ats[pos] & 0x02) strcat(dr, "4, "); + if (card.ats[pos] & 0x04) strcat(dr, "8, "); + if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; + if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; + PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, " + "DR: [%s], DS: [%s]", + (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); + pos++; + } + if (tb1) { + uint32_t sfgi = card.ats[pos] & 0x0F; + uint32_t fwi = card.ats[pos] >> 4; + PrintAndLogEx(NORMAL, " - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", + (sfgi), + sfgi ? "" : "(not needed) ", + sfgi ? (1 << 12) << sfgi : 0, + fwi, + (1 << 12) << fwi + ); + pos++; + } + if (tc1) { + PrintAndLogEx(NORMAL, " - TC1 : NAD is%s supported, CID is%s supported", + (card.ats[pos] & 0x01) ? "" : " NOT", + (card.ats[pos] & 0x02) ? "" : " NOT"); + pos++; + } + if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2 ) { + char *tip = ""; + if (card.ats[0] - pos >= 7) { + if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { + tip = "-> MIFARE Plus X 2K or 4K"; + } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { + tip = "-> MIFARE Plus S 2K or 4K"; + } + } + PrintAndLogEx(NORMAL, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); + if (card.ats[pos] == 0xC1) { + PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type"); + PrintAndLogEx(NORMAL, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); + switch (card.ats[pos + 2] & 0xf0) { + case 0x10: PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire"); break; + case 0x20: PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus"); break; + } + switch (card.ats[pos + 2] & 0x0f) { + case 0x00: PrintAndLogEx(NORMAL, " x0 -> <1 kByte"); break; + case 0x01: PrintAndLogEx(NORMAL, " x1 -> 1 kByte"); break; + case 0x02: PrintAndLogEx(NORMAL, " x2 -> 2 kByte"); break; + case 0x03: PrintAndLogEx(NORMAL, " x3 -> 4 kByte"); break; + case 0x04: PrintAndLogEx(NORMAL, " x4 -> 8 kByte"); break; + } + switch (card.ats[pos + 3] & 0xf0) { + case 0x00: PrintAndLogEx(NORMAL, " 0x -> Engineering sample"); break; + case 0x20: PrintAndLogEx(NORMAL, " 2x -> Released"); break; + } + switch (card.ats[pos + 3] & 0x0f) { + case 0x00: PrintAndLogEx(NORMAL, " x0 -> Generation 1"); break; + case 0x01: PrintAndLogEx(NORMAL, " x1 -> Generation 2"); break; + case 0x02: PrintAndLogEx(NORMAL, " x2 -> Generation 3"); break; + } + switch (card.ats[pos + 4] & 0x0f) { + case 0x00: PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported"); break; + case 0x01: PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported"); break; + case 0x0E: PrintAndLogEx(NORMAL, " xE -> no VCS command supported"); break; + } + } + } + } else { + PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); + } - detect_classic_magic(); + detect_classic_magic(); - if (isMifareClassic) { - int res = detect_classic_prng(); - if ( res == 1 ) - PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_(WEAK)); - else if (res == 0 ) - PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD)); - else - PrintAndLogEx(FAILED, "prng detection: " _RED_(failed)); + if (isMifareClassic) { + int res = detect_classic_prng(); + if ( res == 1 ) + PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_(WEAK)); + else if (res == 0 ) + PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD)); + else + PrintAndLogEx(FAILED, "prng detection: " _RED_(failed)); - if ( do_nack_test ) - detect_classic_nackbug(silent); - } + if ( do_nack_test ) + detect_classic_nackbug(silent); + } - return select_status; + return select_status; } // Collect ISO14443 Type A UIDs int CmdHF14ACUIDs(const char *Cmd) { - // requested number of UIDs - int n = atoi(Cmd); - // collect at least 1 (e.g. if no parameter was given) - n = n > 0 ? n : 1; + // requested number of UIDs + int n = atoi(Cmd); + // collect at least 1 (e.g. if no parameter was given) + n = n > 0 ? n : 1; - uint64_t t1 = msclock(); - PrintAndLogEx(SUCCESS, "collecting %d UIDs", n); + uint64_t t1 = msclock(); + PrintAndLogEx(SUCCESS, "collecting %d UIDs", n); - // repeat n times - for (int i = 0; i < n; i++) { + // repeat n times + for (int i = 0; i < n; i++) { - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); - break; - } + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); + break; + } - // execute anticollision procedure - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; - SendCommand(&c); + // execute anticollision procedure + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; + SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); - iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes; + iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes; - // check if command failed - if (resp.arg[0] == 0) { - PrintAndLogEx(WARNING, "card select failed."); - } else { - char uid_string[20]; - for (uint16_t i = 0; i < card->uidlen; i++) { - sprintf(&uid_string[2*i], "%02X", card->uid[i]); - } - PrintAndLogEx(NORMAL, "%s", uid_string); - } - } - PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock()-t1)/1000); - return 1; + // check if command failed + if (resp.arg[0] == 0) { + PrintAndLogEx(WARNING, "card select failed."); + } else { + char uid_string[20]; + for (uint16_t i = 0; i < card->uidlen; i++) { + sprintf(&uid_string[2*i], "%02X", card->uid[i]); + } + PrintAndLogEx(NORMAL, "%s", uid_string); + } + } + PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock()-t1)/1000); + return 1; } // ## simulate iso14443a tag int CmdHF14ASim(const char *Cmd) { - bool errors = false; - uint8_t flags = 0; - uint8_t tagtype = 1; - uint8_t cmdp = 0; - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - int uidlen = 0; - bool useUIDfromEML = true; - bool setEmulatorMem = false; - bool verbose = false; - nonces_t data[1]; + bool errors = false; + uint8_t flags = 0; + uint8_t tagtype = 1; + uint8_t cmdp = 0; + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + int uidlen = 0; + bool useUIDfromEML = true; + bool setEmulatorMem = false; + bool verbose = false; + nonces_t data[1]; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_14a_sim(); - case 't': - case 'T': - // Retrieve the tag type - tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); - if (tagtype == 0) - errors = true; - cmdp += 2; - break; - case 'u': - case 'U': - // Retrieve the full 4,7,10 byte long uid - param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); - switch(uidlen) { - //case 20: flags |= FLAG_10B_UID_IN_DATA; break; - case 14: flags |= FLAG_7B_UID_IN_DATA; break; - case 8: flags |= FLAG_4B_UID_IN_DATA; break; - default: errors = true; break; - } - if (!errors) { - PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); - useUIDfromEML = false; - } - cmdp += 2; - break; - case 'v': - case 'V': - verbose = true; - cmdp++; - break; - case 'x': - case 'X': - flags |= FLAG_NR_AR_ATTACK; - cmdp++; - break; - case 'e': - case 'E': - setEmulatorMem = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_14a_sim(); + case 't': + case 'T': + // Retrieve the tag type + tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); + if (tagtype == 0) + errors = true; + cmdp += 2; + break; + case 'u': + case 'U': + // Retrieve the full 4,7,10 byte long uid + param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); + switch(uidlen) { + //case 20: flags |= FLAG_10B_UID_IN_DATA; break; + case 14: flags |= FLAG_7B_UID_IN_DATA; break; + case 8: flags |= FLAG_4B_UID_IN_DATA; break; + default: errors = true; break; + } + if (!errors) { + PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); + useUIDfromEML = false; + } + cmdp += 2; + break; + case 'v': + case 'V': + verbose = true; + cmdp++; + break; + case 'x': + case 'X': + flags |= FLAG_NR_AR_ATTACK; + cmdp++; + break; + case 'e': + case 'E': + setEmulatorMem = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0) return usage_hf_14a_sim(); + //Validations + if (errors || cmdp == 0) return usage_hf_14a_sim(); - if ( useUIDfromEML ) - flags |= FLAG_UID_IN_EMUL; + if ( useUIDfromEML ) + flags |= FLAG_UID_IN_EMUL; - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; - memcpy(c.d.asBytes, uid, uidlen>>1); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; + memcpy(c.d.asBytes, uid, uidlen>>1); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); + PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); - while( !ukbhit() ){ - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - if ( !(flags & FLAG_NR_AR_ATTACK) ) break; - if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; + while( !ukbhit() ){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; + if ( !(flags & FLAG_NR_AR_ATTACK) ) break; + if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - memcpy(data, resp.d.asBytes, sizeof(data) ); - readerAttack(data[0], setEmulatorMem, verbose); - } - showSectorTable(); - return 0; + memcpy(data, resp.d.asBytes, sizeof(data) ); + readerAttack(data[0], setEmulatorMem, verbose); + } + showSectorTable(); + return 0; } int CmdHF14ASniff(const char *Cmd) { - int param = 0; - uint8_t ctmp; - for (int i = 0; i < 2; i++) { - ctmp = tolower(param_getchar(Cmd, i)); - if (ctmp == 'h') return usage_hf_14a_sniff(); - if (ctmp == 'c') param |= 0x01; - if (ctmp == 'r') param |= 0x02; - } - UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + int param = 0; + uint8_t ctmp; + for (int i = 0; i < 2; i++) { + ctmp = tolower(param_getchar(Cmd, i)); + if (ctmp == 'h') return usage_hf_14a_sniff(); + if (ctmp == 'c') param |= 0x01; + if (ctmp == 'r') param |= 0x02; + } + UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - static bool responseNum = false; - uint16_t cmdc = 0; - *dataoutlen = 0; + static bool responseNum = false; + uint16_t cmdc = 0; + *dataoutlen = 0; - if (activateField) { - responseNum = false; - UsbCommand resp; + if (activateField) { + responseNum = false; + UsbCommand resp; - // Anticollision + SELECT card - UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - SendCommand(&ca); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + // Anticollision + SELECT card + UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&ca); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - // check result - if (resp.arg[0] == 0) { - PrintAndLogEx(ERR, "No card in field."); - return 1; - } + // check result + if (resp.arg[0] == 0) { + PrintAndLogEx(ERR, "No card in field."); + return 1; + } - if (resp.arg[0] != 1 && resp.arg[0] != 2) { - PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); - return 1; - } + if (resp.arg[0] != 1 && resp.arg[0] != 2) { + PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + return 1; + } - if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - memcpy(cr.d.asBytes, rats, 2); - SendCommand(&cr); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + memcpy(cr.d.asBytes, rats, 2); + SendCommand(&cr); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - if (resp.arg[0] <= 0) { // ats_len - PrintAndLogEx(ERR, "Can't get ATS."); - return 1; - } - } - } + if (resp.arg[0] <= 0) { // ats_len + PrintAndLogEx(ERR, "Can't get ATS."); + return 1; + } + } + } - if (leaveSignalON) - cmdc |= ISO14A_NO_DISCONNECT; + if (leaveSignalON) + cmdc |= ISO14A_NO_DISCONNECT; - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; - uint8_t header[] = {0x0a | responseNum, 0x00}; - responseNum ^= 1; - memcpy(c.d.asBytes, header, 2); - memcpy(&c.d.asBytes[2], datain, datainlen); - SendCommand(&c); + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; + uint8_t header[] = {0x0a | responseNum, 0x00}; + responseNum ^= 1; + memcpy(c.d.asBytes, header, 2); + memcpy(&c.d.asBytes[2], datain, datainlen); + SendCommand(&c); uint8_t *recv; UsbCommand resp; @@ -804,132 +804,132 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav int iLen = resp.arg[0]; if(!iLen) { - PrintAndLogEx(ERR, "No card response."); + PrintAndLogEx(ERR, "No card response."); return 1; - } + } - *dataoutlen = iLen - 2; - if (*dataoutlen < 0) - *dataoutlen = 0; + *dataoutlen = iLen - 2; + if (*dataoutlen < 0) + *dataoutlen = 0; - if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); - return 2; - } + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { + PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + return 2; + } - if (recv[0] != header[0]) { - PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]); - return 2; - } + if (recv[0] != header[0]) { + PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]); + return 2; + } - memcpy(dataout, &recv[2], *dataoutlen); + memcpy(dataout, &recv[2], *dataoutlen); - // CRC Check - if (iLen == -1) { - PrintAndLogEx(ERR, "ISO 14443A CRC error."); - return 3; - } + // CRC Check + if (iLen == -1) { + PrintAndLogEx(ERR, "ISO 14443A CRC error."); + return 3; + } } else { PrintAndLogEx(ERR, "Reply timeout."); - return 4; + return 4; } - return 0; + return 0; } int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { UsbCommand resp; - frameLength = 0; + frameLength = 0; - if (card) - memset(card, 0, sizeof(iso14a_card_select_t)); + if (card) + memset(card, 0, sizeof(iso14a_card_select_t)); - DropField(); + DropField(); - // Anticollision + SELECT card - UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - SendCommand(&ca); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + // Anticollision + SELECT card + UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&ca); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - // check result - if (resp.arg[0] == 0) { - PrintAndLogEx(ERR, "No card in field."); - return 1; - } + // check result + if (resp.arg[0] == 0) { + PrintAndLogEx(ERR, "No card in field."); + return 1; + } - if (resp.arg[0] != 1 && resp.arg[0] != 2) { - PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); - return 1; - } + if (resp.arg[0] != 1 && resp.arg[0] != 2) { + PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + return 1; + } - if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - memcpy(cr.d.asBytes, rats, 2); - SendCommand(&cr); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + memcpy(cr.d.asBytes, rats, 2); + SendCommand(&cr); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - if (resp.arg[0] <= 0) { // ats_len - PrintAndLogEx(ERR, "Can't get ATS."); - return 1; - } + if (resp.arg[0] <= 0) { // ats_len + PrintAndLogEx(ERR, "Can't get ATS."); + return 1; + } - // get frame length from ATS in data field - if (resp.arg[0] > 1) { - uint8_t fsci = resp.d.asBytes[1] & 0x0f; - if (fsci < sizeof(atsFSC)) - frameLength = atsFSC[fsci]; - } - } else { - // get frame length from ATS in card data structure - iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes; - if (vcard->ats_len > 1) { - uint8_t fsci = vcard->ats[1] & 0x0f; - if (fsci < sizeof(atsFSC)) - frameLength = atsFSC[fsci]; - } + // get frame length from ATS in data field + if (resp.arg[0] > 1) { + uint8_t fsci = resp.d.asBytes[1] & 0x0f; + if (fsci < sizeof(atsFSC)) + frameLength = atsFSC[fsci]; + } + } else { + // get frame length from ATS in card data structure + iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes; + if (vcard->ats_len > 1) { + uint8_t fsci = vcard->ats[1] & 0x0f; + if (fsci < sizeof(atsFSC)) + frameLength = atsFSC[fsci]; + } - if (card) - memcpy(card, vcard, sizeof(iso14a_card_select_t)); - } + if (card) + memcpy(card, vcard, sizeof(iso14a_card_select_t)); + } - if (disconnect) - DropField(); + if (disconnect) + DropField(); - return 0; + return 0; } int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) { - *chainingout = false; + *chainingout = false; - if (activateField) { - // select with no disconnect and set frameLength - int selres = SelectCard14443_4(false, NULL); - if (selres) - return selres; - } + if (activateField) { + // select with no disconnect and set frameLength + int selres = SelectCard14443_4(false, NULL); + if (selres) + return selres; + } - uint16_t cmdc = 0; - if (chainingin) - cmdc = ISO14A_SEND_CHAINING; + uint16_t cmdc = 0; + if (chainingin) + cmdc = ISO14A_SEND_CHAINING; - // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes - // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size - // here length USB_CMD_DATA_SIZE=512 - // timeout must be authomatically set by "get ATS" - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; - memcpy(c.d.asBytes, datain, datainlen); - SendCommand(&c); + // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes + // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size + // here length USB_CMD_DATA_SIZE=512 + // timeout must be authomatically set by "get ATS" + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; + memcpy(c.d.asBytes, datain, datainlen); + SendCommand(&c); uint8_t *recv; UsbCommand resp; @@ -937,177 +937,177 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.d.asBytes; int iLen = resp.arg[0]; - uint8_t res = resp.arg[1]; + uint8_t res = resp.arg[1]; - int dlen = iLen - 2; - if (dlen < 0) - dlen = 0; - *dataoutlen += dlen; + int dlen = iLen - 2; + if (dlen < 0) + dlen = 0; + *dataoutlen += dlen; - if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); - return 2; - } + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { + PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + return 2; + } - // I-block ACK - if ((res & 0xf2) == 0xa2) { - *dataoutlen = 0; - *chainingout = true; - return 0; - } + // I-block ACK + if ((res & 0xf2) == 0xa2) { + *dataoutlen = 0; + *chainingout = true; + return 0; + } if(!iLen) { - PrintAndLogEx(ERR, "APDU: No APDU response."); + PrintAndLogEx(ERR, "APDU: No APDU response."); return 1; - } + } - // check apdu length - if (iLen < 2 && iLen >= 0) { - PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); - return 2; - } + // check apdu length + if (iLen < 2 && iLen >= 0) { + PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); + return 2; + } - // check block TODO - if (iLen == -2) { - PrintAndLogEx(ERR, "APDU: Block type mismatch."); - return 2; - } + // check block TODO + if (iLen == -2) { + PrintAndLogEx(ERR, "APDU: Block type mismatch."); + return 2; + } - memcpy(dataout, recv, dlen); + memcpy(dataout, recv, dlen); - // chaining - if ((res & 0x10) != 0) { - *chainingout = true; - } + // chaining + if ((res & 0x10) != 0) { + *chainingout = true; + } - // CRC Check - if (iLen == -1) { - PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error."); - return 3; - } + // CRC Check + if (iLen == -1) { + PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error."); + return 3; + } } else { PrintAndLogEx(ERR, "APDU: Reply timeout."); - return 4; + return 4; } - return 0; + return 0; } int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - *dataoutlen = 0; - bool chaining = false; - int res; + *dataoutlen = 0; + bool chaining = false; + int res; - // 3 byte here - 1b framing header, 2b crc16 - if (APDUInFramingEnable && - ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { - int clen = 0; + // 3 byte here - 1b framing header, 2b crc16 + if (APDUInFramingEnable && + ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { + int clen = 0; - bool vActivateField = activateField; + bool vActivateField = activateField; - do { - int vlen = MIN(frameLength - 3, datainlen - clen); - bool chainBlockNotLast = ((clen + vlen) < datainlen); + do { + int vlen = MIN(frameLength - 3, datainlen - clen); + bool chainBlockNotLast = ((clen + vlen) < datainlen); - *dataoutlen = 0; - res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining); - if (res) { - if (!leaveSignalON) - DropField(); + *dataoutlen = 0; + res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining); + if (res) { + if (!leaveSignalON) + DropField(); - return 200; - } + return 200; + } - // check R-block ACK - if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) { - if (!leaveSignalON) - DropField(); + // check R-block ACK + if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) { + if (!leaveSignalON) + DropField(); - return 201; - } + return 201; + } - clen += vlen; - vActivateField = false; - if (*dataoutlen) { - if (clen != datainlen) - PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); - break; - } - } while (clen < datainlen); - } else { - res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); - if (res) { - if (!leaveSignalON) - DropField(); + clen += vlen; + vActivateField = false; + if (*dataoutlen) { + if (clen != datainlen) + PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); + break; + } + } while (clen < datainlen); + } else { + res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); + if (res) { + if (!leaveSignalON) + DropField(); - return res; - } - } + return res; + } + } - while (chaining) { - // I-block with chaining - res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); + while (chaining) { + // I-block with chaining + res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); - if (res) { - if (!leaveSignalON) - DropField(); + if (res) { + if (!leaveSignalON) + DropField(); - return 100; - } - } + return 100; + } + } - if (!leaveSignalON) - DropField(); + if (!leaveSignalON) + DropField(); - return 0; + return 0; } // ISO14443-4. 7. Half-duplex block transmission protocol int CmdHF14AAPDU(const char *cmd) { - uint8_t data[USB_CMD_DATA_SIZE]; - int datalen = 0; - bool activateField = false; - bool leaveSignalON = false; - bool decodeTLV = false; + uint8_t data[USB_CMD_DATA_SIZE]; + int datalen = 0; + bool activateField = false; + bool leaveSignalON = false; + bool decodeTLV = false; - CLIParserInit("hf 14a apdu", - "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", - "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"); + CLIParserInit("hf 14a apdu", + "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", + "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"); - void* argtable[] = { - arg_param_begin, - arg_lit0("sS", "select", "activate field and select card"), - arg_lit0("kK", "keep", "leave the signal field ON after receive response"), - arg_lit0("tT", "tlv", "executes TLV decoder if it possible"), - arg_strx1(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, false); + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card"), + arg_lit0("kK", "keep", "leave the signal field ON after receive response"), + arg_lit0("tT", "tlv", "executes TLV decoder if it possible"), + arg_strx1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); - activateField = arg_get_lit(1); - leaveSignalON = arg_get_lit(2); - decodeTLV = arg_get_lit(3); - // len = data + PCB(1b) + CRC(2b) - CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2); + activateField = arg_get_lit(1); + leaveSignalON = arg_get_lit(2); + decodeTLV = arg_get_lit(3); + // len = data + PCB(1b) + CRC(2b) + CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2); CLIParserFree(); - PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); + PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); - int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen); + int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen); - if (res) - return res; + if (res) + return res; - PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); + PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); - PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); - // TLV decoder - if (decodeTLV && datalen > 4) { - TLVPrintFromBuffer(data, datalen - 2); - } + // TLV decoder + if (decodeTLV && datalen > 4) { + TLVPrintFromBuffer(data, datalen - 2); + } - return 0; + return 0; } int CmdHF14ACmdRaw(const char *cmd) { @@ -1117,16 +1117,16 @@ int CmdHF14ACmdRaw(const char *cmd) { bool power = false; bool active = false; bool active_select = false; - bool no_rats = false; + bool no_rats = false; uint16_t numbits = 0; - bool bTimeout = false; - uint32_t timeout = 0; - bool topazmode = false; + bool bTimeout = false; + uint32_t timeout = 0; + bool topazmode = false; char buf[5]=""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE]; - uint16_t datalen = 0; - uint32_t temp; + uint16_t datalen = 0; + uint32_t temp; if (strlen(cmd) < 2) return usage_hf_14a_raw(); @@ -1137,9 +1137,9 @@ int CmdHF14ACmdRaw(const char *cmd) { if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; } if (cmd[i]=='-') { switch (cmd[i+1]) { - case 'H': - case 'h': - return usage_hf_14a_raw(); + case 'H': + case 'h': + return usage_hf_14a_raw(); case 'r': reply = false; break; @@ -1162,20 +1162,20 @@ int CmdHF14ACmdRaw(const char *cmd) { while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } i-=2; break; - case 't': - bTimeout = true; - sscanf(cmd+i+2, "%d", &temp); - timeout = temp; - i+=3; - while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } - i-=2; - break; + case 't': + bTimeout = true; + sscanf(cmd+i+2, "%d", &temp); + timeout = temp; + i+=3; + while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } + i-=2; + break; case 'T': - topazmode = true; - break; - case '3': - no_rats = true; - break; + topazmode = true; + break; + case '3': + no_rats = true; + break; default: return usage_hf_14a_raw(); } @@ -1193,11 +1193,11 @@ int CmdHF14ACmdRaw(const char *cmd) { sscanf(buf, "%x", &temp); data[datalen] = (uint8_t)(temp & 0xff); *buf = 0; - if (++datalen >= sizeof(data)){ - if (crc) - PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); - break; - } + if (++datalen >= sizeof(data)){ + if (crc) + PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); + break; + } } continue; } @@ -1207,11 +1207,11 @@ int CmdHF14ACmdRaw(const char *cmd) { if (crc && datalen > 0 && datalen < sizeof(data)-2) { uint8_t first, second; - if (topazmode) { - compute_crc(CRC_14443_B, data, datalen, &first, &second); - } else { - compute_crc(CRC_14443_A, data, datalen, &first, &second); - } + if (topazmode) { + compute_crc(CRC_14443_B, data, datalen, &first, &second); + } else { + compute_crc(CRC_14443_A, data, datalen, &first, &second); + } data[datalen++] = first; data[datalen++] = second; } @@ -1222,45 +1222,45 @@ int CmdHF14ACmdRaw(const char *cmd) { c.arg[0] |= ISO14A_NO_SELECT; } - if (bTimeout){ - #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s + if (bTimeout){ + #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s c.arg[0] |= ISO14A_SET_TIMEOUT; if(timeout > MAX_TIMEOUT) { timeout = MAX_TIMEOUT; PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); } - c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) - } + c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + } if (power) { c.arg[0] |= ISO14A_NO_DISCONNECT; - } + } if (datalen > 0) { c.arg[0] |= ISO14A_RAW; - } + } - if (topazmode) { - c.arg[0] |= ISO14A_TOPAZMODE; - } - if (no_rats) { - c.arg[0] |= ISO14A_NO_RATS; - } + if (topazmode) { + c.arg[0] |= ISO14A_TOPAZMODE; + } + if (no_rats) { + c.arg[0] |= ISO14A_NO_RATS; + } - // Max buffer is USB_CMD_DATA_SIZE - datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; + // Max buffer is USB_CMD_DATA_SIZE + datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; c.arg[1] = (datalen & 0xFFFF) | ((uint32_t)(numbits << 16)); memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); if (reply) { - int res = 0; + int res = 0; if (active_select) - res = waitCmd(1); - if (!res && datalen > 0) + res = waitCmd(1); + if (!res && datalen > 0) waitCmd(0); } return 0; @@ -1271,108 +1271,108 @@ static int waitCmd(uint8_t iSelect) { uint16_t len = 0; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - len = (resp.arg[0] & 0xFFFF); - if (iSelect){ - len = (resp.arg[1] & 0xFFFF); - if (len){ - PrintAndLogEx(NORMAL, "Card selected. UID[%i]:", len); - } else { - PrintAndLogEx(WARNING, "Can't select card."); - } - } else { - PrintAndLogEx(NORMAL, "received %i bytes", len); - } + len = (resp.arg[0] & 0xFFFF); + if (iSelect){ + len = (resp.arg[1] & 0xFFFF); + if (len){ + PrintAndLogEx(NORMAL, "Card selected. UID[%i]:", len); + } else { + PrintAndLogEx(WARNING, "Can't select card."); + } + } else { + PrintAndLogEx(NORMAL, "received %i bytes", len); + } if (!len) return 1; - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 3; + return 3; } - return 0; + return 0; } int CmdHF14AAntiFuzz(const char *cmd) { - CLIParserInit("hf 14a antifuzz", - "Tries to fuzz the ISO14443a anticollision phase", - "Usage:\n" - "\thf 14a antifuzz -4\n"); + CLIParserInit("hf 14a antifuzz", + "Tries to fuzz the ISO14443a anticollision phase", + "Usage:\n" + "\thf 14a antifuzz -4\n"); - void* argtable[] = { - arg_param_begin, - arg_lit0("4", NULL, "4 byte uid"), - arg_lit0("7", NULL, "7 byte uid"), - arg_lit0(NULL, "10", "10 byte uid"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, false); + void* argtable[] = { + arg_param_begin, + arg_lit0("4", NULL, "4 byte uid"), + arg_lit0("7", NULL, "7 byte uid"), + arg_lit0(NULL, "10", "10 byte uid"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); - uint8_t arg0 = FLAG_4B_UID_IN_DATA; - if (arg_get_lit(2)) - arg0 = FLAG_7B_UID_IN_DATA; - if (arg_get_lit(3)) - arg0 = FLAG_10B_UID_IN_DATA; + uint8_t arg0 = FLAG_4B_UID_IN_DATA; + if (arg_get_lit(2)) + arg0 = FLAG_7B_UID_IN_DATA; + if (arg_get_lit(3)) + arg0 = FLAG_10B_UID_IN_DATA; - CLIParserFree(); - UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; - clearCommandBuffer(); + CLIParserFree(); + UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; + clearCommandBuffer(); SendCommand(&c); - return 0; + return 0; } int CmdHF14AChaining(const char *cmd) { - CLIParserInit("hf 14a chaining", - "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", - "Usage:\n" - "\thf 14a chaining disable -> disable chaining\n" - "\thf 14a chaining -> show chaining enable/disable state\n"); + CLIParserInit("hf 14a chaining", + "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", + "Usage:\n" + "\thf 14a chaining disable -> disable chaining\n" + "\thf 14a chaining -> show chaining enable/disable state\n"); - void* argtable[] = { - arg_param_begin, - arg_str0(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - struct arg_str *str = arg_get_str(1); - int len = arg_get_str_len(1); + struct arg_str *str = arg_get_str(1); + int len = arg_get_str_len(1); - if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1"))) - APDUInFramingEnable = true; + if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1"))) + APDUInFramingEnable = true; - if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) - APDUInFramingEnable = false; + if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) + APDUInFramingEnable = false; - CLIParserFree(); + CLIParserFree(); - PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); + PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); - return 0; + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"}, - {"info", CmdHF14AInfo, 0, "Tag information"}, - {"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"}, - {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443-a UIDs in one go"}, - {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, - {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"}, - {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, - {"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"}, - {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, - {"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"}, + {"info", CmdHF14AInfo, 0, "Tag information"}, + {"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"}, + {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443-a UIDs in one go"}, + {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, + {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"}, + {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, + {"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"}, + {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, + {"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, + {NULL, NULL, 0, NULL} }; int CmdHF14A(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 4396c4b79..73cbd069c 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -28,15 +28,15 @@ #include "mifare.h" #include "cmdhfmf.h" #include "cmdhfmfu.h" -#include "cmdhf.h" // list cmd +#include "cmdhf.h" // list cmd #include "mifare/mifarehost.h" #include "emv/apduinfo.h" #include "emv/emvcore.h" // structure and database for uid -> tagtype lookups typedef struct { - uint8_t uid; - char* desc; + uint8_t uid; + char* desc; } manufactureName; extern int CmdHF14A(const char *Cmd); diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index f74ca9a34..c3962a17f 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -15,152 +15,152 @@ static int CmdHelp(const char *Cmd); int usage_hf_14b_info(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " s silently"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b info"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " s silently"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b info"); + return 0; } int usage_hf_14b_reader(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " s silently"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b reader"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " s silently"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b reader"); + return 0; } int usage_hf_14b_raw(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -p leave the field on after receive"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -r do not read response"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -p leave the field on after receive"); + PrintAndLogEx(NORMAL, " -s active signal field ON with select"); + PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); + return 0; } int usage_hf_14b_sniff(void){ - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'"); - PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sniff"); - return 0; + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); + PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'"); + PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sniff"); + return 0; } int usage_hf_14b_sim(void){ - PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI"); - PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " u 4byte UID/PUPI"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sim"); - PrintAndLogEx(NORMAL, " hf 14b sim u 11223344"); - return 0; + PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI"); + PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " u 4byte UID/PUPI"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sim"); + PrintAndLogEx(NORMAL, " hf 14b sim u 11223344"); + return 0; } int usage_hf_14b_read_srx(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sriread 1"); - PrintAndLogEx(NORMAL, " hf 14b sriread 2"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sriread 1"); + PrintAndLogEx(NORMAL, " hf 14b sriread 2"); + return 0; } int usage_hf_14b_write_srx(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); - PrintAndLogEx(NORMAL, " BLOCK number depends on tag, special block == FF"); - PrintAndLogEx(NORMAL, " hex bytes of data to be written"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 7F 11223344"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 FF 11223344"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 15 11223344"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 FF 11223344"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); + PrintAndLogEx(NORMAL, " BLOCK number depends on tag, special block == FF"); + PrintAndLogEx(NORMAL, " hex bytes of data to be written"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 7F 11223344"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 FF 11223344"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 15 11223344"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 FF 11223344"); + return 0; } int usage_hf_14b_dump(void){ - PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" - "\n" - "Usage: hf 14b dump [h] [card memory] \n" - "Options:\n" - "\th this help\n" - "\t[card memory] 1 = SRIX4K (default), 2 = SRI512" - "\tf filename, if no UID will be used as filename\n" - "\n" - "Example:\n" - "\thf 14b dump f\n" - "\thf 14b dump 2 f mydump"); - return 0; + PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" + "\n" + "Usage: hf 14b dump [h] [card memory] \n" + "Options:\n" + "\th this help\n" + "\t[card memory] 1 = SRIX4K (default), 2 = SRI512" + "\tf filename, if no UID will be used as filename\n" + "\n" + "Example:\n" + "\thf 14b dump f\n" + "\thf 14b dump 2 f mydump"); + return 0; } /* static void switch_on_field_14b(void) { - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); } */ static int switch_off_field_14b(void) { - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHF14BList(const char *Cmd) { - CmdTraceList("14b"); - return 0; + CmdTraceList("14b"); + return 0; } int CmdHF14BSim(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_sim(); - uint32_t pupi = 0; - if (cmdp == 'u') { - pupi = param_get32ex(Cmd, 1, 0, 16); - } + uint32_t pupi = 0; + if (cmdp == 'u') { + pupi = param_get32ex(Cmd, 1, 0, 16); + } - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443B, {pupi, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443B, {pupi, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHF14BSniff(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_sniff(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_sniff(); - UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHF14BCmdRaw (const char *Cmd) { - bool reply = true, power = false, select = false; - char buf[5] = ""; - int i = 0; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - uint16_t datalen = 0; - uint32_t flags = ISO14B_CONNECT; - uint32_t temp = 0; + bool reply = true, power = false, select = false; + char buf[5] = ""; + int i = 0; + uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + uint16_t datalen = 0; + uint32_t flags = ISO14B_CONNECT; + uint32_t temp = 0; - if ( strlen(Cmd) < 3 ) return usage_hf_14b_raw(); + if ( strlen(Cmd) < 3 ) return usage_hf_14b_raw(); // strip while (*Cmd==' ' || *Cmd=='\t') ++Cmd; @@ -169,8 +169,8 @@ int CmdHF14BCmdRaw (const char *Cmd) { if (Cmd[i]==' ' || Cmd[i]=='\t') { ++i; continue; } if (Cmd[i]=='-') { switch (tolower(Cmd[i+1])) { - case 'h': - return usage_hf_14b_raw(); + case 'h': + return usage_hf_14b_raw(); case 'r': reply = false; break; @@ -178,17 +178,17 @@ int CmdHF14BCmdRaw (const char *Cmd) { flags |= ISO14B_APPEND_CRC; break; case 'p': - power = true; + power = true; + break; + case 's': + select = true; + if (tolower(Cmd[i+2]) == 's') { + flags |= ISO14B_SELECT_SR; + ++i; + } else { + flags |= ISO14B_SELECT_STD; + } break; - case 's': - select = true; - if (tolower(Cmd[i+2]) == 's') { - flags |= ISO14B_SELECT_SR; - ++i; - } else { - flags |= ISO14B_SELECT_STD; - } - break; default: return usage_hf_14b_raw(); } @@ -206,87 +206,87 @@ int CmdHF14BCmdRaw (const char *Cmd) { sscanf(buf,"%x",&temp); data[datalen++] = (uint8_t)(temp & 0xff); *buf=0; - memset(buf, 0x00, sizeof(buf)); + memset(buf, 0x00, sizeof(buf)); } continue; } PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i)); - return 0; + return 0; } - if (!power) + if (!power) flags |= ISO14B_DISCONNECT; if (datalen > 0) - flags |= ISO14B_RAW; + flags |= ISO14B_RAW; - // Max buffer is USB_CMD_DATA_SIZE - datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; + // Max buffer is USB_CMD_DATA_SIZE + datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; - memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + memcpy(c.d.asBytes, data, datalen); + clearCommandBuffer(); + SendCommand(&c); - if (!reply) return 1; + if (!reply) return 1; - bool success = true; - // get back iso14b_card_select_t, don't print it. - if (select) - success = waitCmd14b(false); + bool success = true; + // get back iso14b_card_select_t, don't print it. + if (select) + success = waitCmd14b(false); - // get back response from the raw bytes you sent. - if (success && datalen>0) waitCmd14b(true); + // get back response from the raw bytes you sent. + if (success && datalen>0) waitCmd14b(true); return 1; } static bool get_14b_UID(iso14b_card_select_t *card) { - if (!card) - return false; + if (!card) + return false; - int8_t retry = 3; - UsbCommand resp; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; + int8_t retry = 3; + UsbCommand resp; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - // test for 14b SR - while (retry--) { + // test for 14b SR + while (retry--) { - clearCommandBuffer(); - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + clearCommandBuffer(); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - uint8_t status = resp.arg[0]; - if ( status == 0) { - memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - return true; - } - } - } // retry + uint8_t status = resp.arg[0]; + if ( status == 0) { + memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + return true; + } + } + } // retry - // test 14b standard - c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT; - retry = 3; - while (retry--) { + // test 14b standard + c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT; + retry = 3; + while (retry--) { - clearCommandBuffer(); - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + clearCommandBuffer(); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - uint8_t status = resp.arg[0]; - if ( status == 0) { - memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - return true; - } - } - } // retry + uint8_t status = resp.arg[0]; + if ( status == 0) { + memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + return true; + } + } + } // retry - if ( retry <= 0 ) - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + if ( retry <= 0 ) + PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return false; + return false; } // print full atqb info @@ -296,122 +296,122 @@ static bool get_14b_UID(iso14b_card_select_t *card) { // 5 = max frame size / -4 info // 6 = FWI / Coding options static void print_atqb_resp(uint8_t *data, uint8_t cid){ - //PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(data+1,4)); - PrintAndLogEx(NORMAL, " App Data: %s", sprint_hex(data,4)); - PrintAndLogEx(NORMAL, " Protocol: %s", sprint_hex(data+4,3)); - uint8_t BitRate = data[4]; - if (!BitRate) PrintAndLogEx(NORMAL, " Bit Rate: 106 kbit/s only PICC <-> PCD"); - if (BitRate & 0x10) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC -> PCD supported"); - if (BitRate & 0x20) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC -> PCD supported"); - if (BitRate & 0x40) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC -> PCD supported"); - if (BitRate & 0x01) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC <- PCD supported"); - if (BitRate & 0x02) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC <- PCD supported"); - if (BitRate & 0x04) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC <- PCD supported"); - if (BitRate & 0x80) PrintAndLogEx(NORMAL, " Same bit rate <-> required"); + //PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(data+1,4)); + PrintAndLogEx(NORMAL, " App Data: %s", sprint_hex(data,4)); + PrintAndLogEx(NORMAL, " Protocol: %s", sprint_hex(data+4,3)); + uint8_t BitRate = data[4]; + if (!BitRate) PrintAndLogEx(NORMAL, " Bit Rate: 106 kbit/s only PICC <-> PCD"); + if (BitRate & 0x10) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC -> PCD supported"); + if (BitRate & 0x20) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC -> PCD supported"); + if (BitRate & 0x40) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC -> PCD supported"); + if (BitRate & 0x01) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC <- PCD supported"); + if (BitRate & 0x02) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC <- PCD supported"); + if (BitRate & 0x04) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC <- PCD supported"); + if (BitRate & 0x80) PrintAndLogEx(NORMAL, " Same bit rate <-> required"); - uint16_t maxFrame = data[5] >> 4; - if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; - else if (maxFrame == 5) maxFrame = 64; - else if (maxFrame == 6) maxFrame = 96; - else if (maxFrame == 7) maxFrame = 128; - else if (maxFrame == 8) maxFrame = 256; - else maxFrame = 257; + uint16_t maxFrame = data[5] >> 4; + if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; + else if (maxFrame == 5) maxFrame = 64; + else if (maxFrame == 6) maxFrame = 96; + else if (maxFrame == 7) maxFrame = 128; + else if (maxFrame == 8) maxFrame = 256; + else maxFrame = 257; - PrintAndLogEx(NORMAL, "Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : ""); + PrintAndLogEx(NORMAL, "Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : ""); - uint8_t protocolT = data[5] & 0xF; - PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); + uint8_t protocolT = data[5] & 0xF; + PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); - uint8_t fwt = data[6]>>4; - if ( fwt < 16 ){ - uint32_t etus = (32 << fwt); - uint32_t fwt_time = (302 << fwt); - PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time); - } else { - PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - RFU", fwt); - } + uint8_t fwt = data[6]>>4; + if ( fwt < 16 ){ + uint32_t etus = (32 << fwt); + uint32_t fwt_time = (302 << fwt); + PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time); + } else { + PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - RFU", fwt); + } - PrintAndLogEx(NORMAL, " App Data Code: Application is %s",(data[6]&4) ? "Standard" : "Proprietary"); - PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported",(data[6]&2) ? "" : "not "); - PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported",(data[6]&1) ? "" : "not "); - PrintAndLogEx(NORMAL, "Tag :"); - PrintAndLogEx(NORMAL, " Max Buf Length: %u (MBLI) %s", cid>>4, (cid & 0xF0) ? "" : "chained frames not supported"); - PrintAndLogEx(NORMAL, " CID : %u", cid & 0x0f); - return; + PrintAndLogEx(NORMAL, " App Data Code: Application is %s",(data[6]&4) ? "Standard" : "Proprietary"); + PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported",(data[6]&2) ? "" : "not "); + PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported",(data[6]&1) ? "" : "not "); + PrintAndLogEx(NORMAL, "Tag :"); + PrintAndLogEx(NORMAL, " Max Buf Length: %u (MBLI) %s", cid>>4, (cid & 0xF0) ? "" : "chained frames not supported"); + PrintAndLogEx(NORMAL, " CID : %u", cid & 0x0f); + return; } // get SRx chip model (from UID) // from ST Microelectronics char *get_ST_Chip_Model(uint8_t data){ - static char model[20]; - char *retStr = model; - memset(model,0, sizeof(model)); + static char model[20]; + char *retStr = model; + memset(model,0, sizeof(model)); - switch (data) { - case 0x0: sprintf(retStr, "SRIX4K (Special)"); break; - case 0x2: sprintf(retStr, "SR176"); break; - case 0x3: sprintf(retStr, "SRIX4K"); break; - case 0x4: sprintf(retStr, "SRIX512"); break; - case 0x6: sprintf(retStr, "SRI512"); break; - case 0x7: sprintf(retStr, "SRI4K"); break; - case 0xC: sprintf(retStr, "SRT512"); break; - default : sprintf(retStr, "Unknown"); break; - } - return retStr; + switch (data) { + case 0x0: sprintf(retStr, "SRIX4K (Special)"); break; + case 0x2: sprintf(retStr, "SR176"); break; + case 0x3: sprintf(retStr, "SRIX4K"); break; + case 0x4: sprintf(retStr, "SRIX512"); break; + case 0x6: sprintf(retStr, "SRI512"); break; + case 0x7: sprintf(retStr, "SRI4K"); break; + case 0xC: sprintf(retStr, "SRT512"); break; + default : sprintf(retStr, "Unknown"); break; + } + return retStr; } // REMAKE: int print_ST_Lock_info(uint8_t model){ - // PrintAndLogEx(NORMAL, "Chip Write Protection Bits:"); - // // now interpret the data - // switch (model){ - // case 0x0: //fall through (SRIX4K special) - // case 0x3: //fall through (SRIx4K) - // case 0x7: // (SRI4K) - // //only need data[3] - // blk1 = 9; - // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+3, 1)); - // PrintAndLogEx(NORMAL, " 07/08:%slocked", (data[3] & 1) ? " not " : " " ); - // for (uint8_t i = 1; i<8; i++){ - // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[3] & (1 << i)) ? " not " : " " ); - // blk1++; - // } - // break; - // case 0x4: //fall through (SRIX512) - // case 0x6: //fall through (SRI512) - // case 0xC: // (SRT512) - // //need data[2] and data[3] - // blk1 = 0; - // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 2)); - // for (uint8_t b=2; b<4; b++){ - // for (uint8_t i=0; i<8; i++){ - // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[b] & (1 << i)) ? " not " : " " ); - // blk1++; - // } - // } - // break; - // case 0x2: // (SR176) - // //need data[2] - // blk1 = 0; - // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 1)); - // for (uint8_t i = 0; i<8; i++){ - // PrintAndLogEx(NORMAL, " %02u/%02u:%slocked", blk1, blk1+1, (data[2] & (1 << i)) ? " " : " not " ); - // blk1+=2; - // } - // break; - // default: - // return rawClose(); - // } - return 1; + // PrintAndLogEx(NORMAL, "Chip Write Protection Bits:"); + // // now interpret the data + // switch (model){ + // case 0x0: //fall through (SRIX4K special) + // case 0x3: //fall through (SRIx4K) + // case 0x7: // (SRI4K) + // //only need data[3] + // blk1 = 9; + // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+3, 1)); + // PrintAndLogEx(NORMAL, " 07/08:%slocked", (data[3] & 1) ? " not " : " " ); + // for (uint8_t i = 1; i<8; i++){ + // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[3] & (1 << i)) ? " not " : " " ); + // blk1++; + // } + // break; + // case 0x4: //fall through (SRIX512) + // case 0x6: //fall through (SRI512) + // case 0xC: // (SRT512) + // //need data[2] and data[3] + // blk1 = 0; + // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 2)); + // for (uint8_t b=2; b<4; b++){ + // for (uint8_t i=0; i<8; i++){ + // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[b] & (1 << i)) ? " not " : " " ); + // blk1++; + // } + // } + // break; + // case 0x2: // (SR176) + // //need data[2] + // blk1 = 0; + // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 1)); + // for (uint8_t i = 0; i<8; i++){ + // PrintAndLogEx(NORMAL, " %02u/%02u:%slocked", blk1, blk1+1, (data[2] & (1 << i)) ? " " : " not " ); + // blk1+=2; + // } + // break; + // default: + // return rawClose(); + // } + return 1; } // print UID info from SRx chips (ST Microelectronics) static void print_st_general_info(uint8_t *data, uint8_t len){ - //uid = first 8 bytes in data - PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data,8,8), len)); - PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6])); - PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2)); - return; + //uid = first 8 bytes in data + PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data,8,8), len)); + PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6])); + PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2)); + return; } //05 00 00 = find one tag in field @@ -435,281 +435,281 @@ static void print_st_general_info(uint8_t *data, uint8_t len){ // 14b get and print Full Info (as much as we know) bool HF14B_Std_Info(bool verbose){ - bool isSuccess = false; + bool isSuccess = false; - // 14b get and print UID only (general info) - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + // 14b get and print UID only (general info) + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - switch_off_field_14b(); - return false; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + switch_off_field_14b(); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; + uint64_t status = resp.arg[0]; - switch( status ){ - case 0: - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); - print_atqb_resp(card.atqb, card.cid); - isSuccess = true; - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); - break; - } + switch( status ){ + case 0: + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); + print_atqb_resp(card.atqb, card.cid); + isSuccess = true; + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); + break; + } - return isSuccess; + return isSuccess; } // SRx get and print full info (needs more info...) bool HF14B_ST_Info(bool verbose){ - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return false; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; - if ( status > 0 ) - return false; + uint64_t status = resp.arg[0]; + if ( status > 0 ) + return false; - print_st_general_info(card.uid, card.uidlen); + print_st_general_info(card.uid, card.uidlen); - //add locking bit information here. uint8_t data[16] = {0x00}; - // uint8_t datalen = 2; - // uint8_t resplen; - // uint8_t blk1; - // data[0] = 0x08; + //add locking bit information here. uint8_t data[16] = {0x00}; + // uint8_t datalen = 2; + // uint8_t resplen; + // uint8_t blk1; + // data[0] = 0x08; - // - // if (model == 0x2) { //SR176 has special command: - // data[1] = 0xf; - // resplen = 4; - // } else { - // data[1] = 0xff; - // resplen = 6; - // } + // + // if (model == 0x2) { //SR176 has special command: + // data[1] = 0xf; + // resplen = 4; + // } else { + // data[1] = 0xff; + // resplen = 6; + // } - // //std read cmd - // if (HF14BCmdRaw(true, true, data, &datalen, false)==0) - // return rawClose(); + // //std read cmd + // if (HF14BCmdRaw(true, true, data, &datalen, false)==0) + // return rawClose(); - // if (datalen != resplen || !crc) return rawClose(); - //print_ST_Lock_info(data[5]>>2); - return true; + // if (datalen != resplen || !crc) return rawClose(); + //print_ST_Lock_info(data[5]>>2); + return true; } // get and print all info known about any known 14b tag bool HF14BInfo(bool verbose){ - // try std 14b (atqb) - if (HF14B_Std_Info(verbose)) return true; + // try std 14b (atqb) + if (HF14B_Std_Info(verbose)) return true; - // try ST 14b - if (HF14B_ST_Info(verbose)) return true; + // try ST 14b + if (HF14B_ST_Info(verbose)) return true; - // try unknown 14b read commands (to be identified later) - // could be read of calypso, CEPAS, moneo, or pico pass. - if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); - return false; + // try unknown 14b read commands (to be identified later) + // could be read of calypso, CEPAS, moneo, or pico pass. + if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); + return false; } // menu command to get and print all info known about any known 14b tag int CmdHF14Binfo(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_info(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_info(); - bool verbose = !(cmdp == 's'); - return HF14BInfo(verbose); + bool verbose = !(cmdp == 's'); + return HF14BInfo(verbose); } bool HF14B_ST_Reader(bool verbose){ - bool isSuccess = false; + bool isSuccess = false; - // SRx get and print general info about SRx chip from UID - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return false; + // SRx get and print general info about SRx chip from UID + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; + uint64_t status = resp.arg[0]; - switch( status ){ - case 0: - print_st_general_info(card.uid, card.uidlen); - isSuccess = true; - break; - case 1: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 random chip id fail"); - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed"); - break; - } - return isSuccess; + switch( status ){ + case 0: + print_st_general_info(card.uid, card.uidlen); + isSuccess = true; + break; + case 1: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 random chip id fail"); + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed"); + break; + } + return isSuccess; } bool HF14B_Std_Reader(bool verbose){ - bool isSuccess = false; + bool isSuccess = false; - // 14b get and print UID only (general info) - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + // 14b get and print UID only (general info) + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return false; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; + uint64_t status = resp.arg[0]; - switch( status ){ - case 0: - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); - print_atqb_resp(card.atqb, card.cid); - isSuccess = true; - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); - break; - } - return isSuccess; + switch( status ){ + case 0: + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); + print_atqb_resp(card.atqb, card.cid); + isSuccess = true; + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); + break; + } + return isSuccess; } // test for other 14b type tags (mimic another reader - don't have tags to identify) bool HF14B_Other_Reader(){ - // uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80}; - // uint8_t datalen = 4; + // uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80}; + // uint8_t datalen = 4; - // // 14b get and print UID only (general info) - // uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; + // // 14b get and print UID only (general info) + // uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; - // UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; - // memcpy(c.d.asBytes, data, datalen); + // UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + // memcpy(c.d.asBytes, data, datalen); - // clearCommandBuffer(); - // SendCommand(&c); - // UsbCommand resp; - // WaitForResponse(CMD_ACK,&resp); + // clearCommandBuffer(); + // SendCommand(&c); + // UsbCommand resp; + // WaitForResponse(CMD_ACK,&resp); - // if (datalen > 2 ) { - // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); - // PrintAndLogEx(NORMAL, "unknown tag type answered to a 0x000b3f80 command ans:"); - // //PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); - // rawclose(); - // return true; - // } + // if (datalen > 2 ) { + // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); + // PrintAndLogEx(NORMAL, "unknown tag type answered to a 0x000b3f80 command ans:"); + // //PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); + // rawclose(); + // return true; + // } - // c.arg1 = 1; - // c.d.asBytes[0] = ISO14443B_AUTHENTICATE; - // clearCommandBuffer(); - // SendCommand(&c); - // UsbCommand resp; - // WaitForResponse(CMD_ACK, &resp); + // c.arg1 = 1; + // c.d.asBytes[0] = ISO14443B_AUTHENTICATE; + // clearCommandBuffer(); + // SendCommand(&c); + // UsbCommand resp; + // WaitForResponse(CMD_ACK, &resp); - // if (datalen > 0) { - // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); - // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0A command ans:"); - // // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); - // rawClose(); - // return true; - // } + // if (datalen > 0) { + // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); + // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0A command ans:"); + // // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); + // rawClose(); + // return true; + // } - // c.arg1 = 1; - // c.d.asBytes[0] = ISO14443B_RESET; - // clearCommandBuffer(); - // SendCommand(&c); - // UsbCommand resp; - // WaitForResponse(CMD_ACK, &resp); + // c.arg1 = 1; + // c.d.asBytes[0] = ISO14443B_RESET; + // clearCommandBuffer(); + // SendCommand(&c); + // UsbCommand resp; + // WaitForResponse(CMD_ACK, &resp); - // if (datalen > 0) { - // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); - // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0C command ans:"); - // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); - // rawClose(); - // return true; - // } + // if (datalen > 0) { + // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); + // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0C command ans:"); + // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); + // rawClose(); + // return true; + // } - // rawClose(); - return false; + // rawClose(); + return false; } // get and print general info about all known 14b chips bool HF14BReader(bool verbose){ - // try std 14b (atqb) - if (HF14B_Std_Reader(verbose)) return true; + // try std 14b (atqb) + if (HF14B_Std_Reader(verbose)) return true; - // try ST Microelectronics 14b - if (HF14B_ST_Reader(verbose)) return true; + // try ST Microelectronics 14b + if (HF14B_ST_Reader(verbose)) return true; - // try unknown 14b read commands (to be identified later) - // could be read of calypso, CEPAS, moneo, or pico pass. - if (HF14B_Other_Reader()) return true; + // try unknown 14b read commands (to be identified later) + // could be read of calypso, CEPAS, moneo, or pico pass. + if (HF14B_Other_Reader()) return true; - if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); - return false; + if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); + return false; } // menu command to get and print general info about all known 14b chips int CmdHF14BReader(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_reader(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_reader(); - bool verbose = !(cmdp == 's'); - return HF14BReader(verbose); + bool verbose = !(cmdp == 's'); + return HF14BReader(verbose); } /* New command to read the contents of a SRI512|SRIX4K tag @@ -717,16 +717,16 @@ int CmdHF14BReader(const char *Cmd){ * this command just dumps the contents of the memory/ */ int CmdHF14BReadSri(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx(); - uint8_t tagtype = param_get8(Cmd, 0); - uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F; + uint8_t tagtype = param_get8(Cmd, 0); + uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F; - UsbCommand c = {CMD_READ_SRI_TAG, {blocks, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_READ_SRI_TAG, {blocks, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } // New command to write a SRI512/SRIX4K tag. int CmdHF14BWriteSri(const char *Cmd){ @@ -740,215 +740,215 @@ int CmdHF14BWriteSri(const char *Cmd){ * Special block FF = otp_lock_reg block. * Data len 4 bytes- */ - char cmdp = tolower(param_getchar(Cmd, 0)); - uint8_t blockno = -1; - uint8_t data[4] = {0x00}; - bool isSrix4k = true; - char str[30]; - memset(str, 0x00, sizeof(str)); + char cmdp = tolower(param_getchar(Cmd, 0)); + uint8_t blockno = -1; + uint8_t data[4] = {0x00}; + bool isSrix4k = true; + char str[30]; + memset(str, 0x00, sizeof(str)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx(); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx(); - if ( cmdp == '2' ) - isSrix4k = false; + if ( cmdp == '2' ) + isSrix4k = false; - //blockno = param_get8(Cmd, 1); + //blockno = param_get8(Cmd, 1); - if ( param_gethex(Cmd, 1, &blockno, 2) ) { - PrintAndLogEx(WARNING, "block number must include 2 HEX symbols"); - return 0; - } + if ( param_gethex(Cmd, 1, &blockno, 2) ) { + PrintAndLogEx(WARNING, "block number must include 2 HEX symbols"); + return 0; + } - if ( isSrix4k ){ - if ( blockno > 0x7f && blockno != 0xff ){ - PrintAndLogEx(FAILED, "block number out of range"); - return 0; - } - } else { - if ( blockno > 0x0f && blockno != 0xff ){ - PrintAndLogEx(FAILED, "block number out of range"); - return 0; - } - } + if ( isSrix4k ){ + if ( blockno > 0x7f && blockno != 0xff ){ + PrintAndLogEx(FAILED, "block number out of range"); + return 0; + } + } else { + if ( blockno > 0x0f && blockno != 0xff ){ + PrintAndLogEx(FAILED, "block number out of range"); + return 0; + } + } - if (param_gethex(Cmd, 2, data, 8)) { - PrintAndLogEx(WARNING, "data must include 8 HEX symbols"); - return 0; - } + if (param_gethex(Cmd, 2, data, 8)) { + PrintAndLogEx(WARNING, "data must include 8 HEX symbols"); + return 0; + } - if ( blockno == 0xff) { - PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]", - (isSrix4k) ? "SRIX4K":"SRI512", - blockno, - sprint_hex(data,4) - ); - } else { - PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]", - (isSrix4k) ? "SRIX4K":"SRI512", - blockno, - sprint_hex(data,4) - ); - } + if ( blockno == 0xff) { + PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]", + (isSrix4k) ? "SRIX4K":"SRI512", + blockno, + sprint_hex(data,4) + ); + } else { + PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]", + (isSrix4k) ? "SRIX4K":"SRI512", + blockno, + sprint_hex(data,4) + ); + } - sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]); - CmdHF14BCmdRaw(str); - return 0; + sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]); + CmdHF14BCmdRaw(str); + return 0; } // need to write to file int CmdHF14BDump(const char*Cmd) { - uint8_t fileNameLen = 0; - char filename[FILE_PATH_SIZE] = {0}; - char * fptr = filename; - bool errors = false; - uint8_t cmdp = 0, cardtype = 1; - uint16_t cardsize = 0; - uint8_t blocks = 0; - iso14b_card_select_t card; + uint8_t fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0}; + char * fptr = filename; + bool errors = false; + uint8_t cmdp = 0, cardtype = 1; + uint16_t cardsize = 0; + uint8_t blocks = 0; + iso14b_card_select_t card; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_14b_dump(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - if (cmdp == 0) { - cardtype = param_get8ex(Cmd, cmdp, 1, 10); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_14b_dump(); + case 'f': + fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + if (cmdp == 0) { + cardtype = param_get8ex(Cmd, cmdp, 1, 10); + cmdp++; + } else { + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + } - //Validations - if (errors) return usage_hf_14b_dump(); + //Validations + if (errors) return usage_hf_14b_dump(); - switch (cardtype){ - case 2: - cardsize = (512/8) + 4; - blocks = 0x0F; - break; - case 1: - default: - cardsize = (4096/8) + 4; - blocks = 0x7F; - break; - } + switch (cardtype){ + case 2: + cardsize = (512/8) + 4; + blocks = 0x0F; + break; + case 1: + default: + cardsize = (4096/8) + 4; + blocks = 0x7F; + break; + } - if (!get_14b_UID(&card)) { - PrintAndLogEx(WARNING, "No tag found."); - return 1; - } + if (!get_14b_UID(&card)) { + PrintAndLogEx(WARNING, "No tag found."); + return 1; + } - if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); - fptr += sprintf(fptr, "hf-14b-"); - FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); - } + if (fileNameLen < 1) { + PrintAndLogEx(INFO, "Using UID as filename"); + fptr += sprintf(fptr, "hf-14b-"); + FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); + } - // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); + // detect blocksize from card :) + PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); - uint8_t data[cardsize]; - memset(data, 0, sizeof(data)); + uint8_t data[cardsize]; + memset(data, 0, sizeof(data)); - int blocknum = 0; - uint8_t *recv = NULL; + int blocknum = 0; + uint8_t *recv = NULL; - UsbCommand resp; - UsbCommand c = {CMD_ISO_14443B_COMMAND, { ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand resp; + UsbCommand c = {CMD_ISO_14443B_COMMAND, { ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); - //select - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - if (resp.arg[0]) { - PrintAndLogEx(INFO, "failed to select %d | %d", resp.arg[0], resp.arg[1]); - goto out; - } - } + //select + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (resp.arg[0]) { + PrintAndLogEx(INFO, "failed to select %d | %d", resp.arg[0], resp.arg[1]); + goto out; + } + } - c.arg[0] = ISO14B_APPEND_CRC | ISO14B_RAW; - c.arg[1] = 2; + c.arg[0] = ISO14B_APPEND_CRC | ISO14B_RAW; + c.arg[1] = 2; - uint8_t *req = c.d.asBytes; - req[0] = ISO14443B_READ_BLK; + uint8_t *req = c.d.asBytes; + req[0] = ISO14443B_READ_BLK; - for (int retry = 0; retry < 5; retry++) { + for (int retry = 0; retry < 5; retry++) { - req[1] = blocknum; + req[1] = blocknum; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t status = resp.arg[0] & 0xFF; - if ( status > 0 ) { - continue; - } + uint8_t status = resp.arg[0] & 0xFF; + if ( status > 0 ) { + continue; + } - uint16_t len = (resp.arg[1] & 0xFFFF); - recv = resp.d.asBytes; + uint16_t len = (resp.arg[1] & 0xFFFF); + recv = resp.d.asBytes; - if ( !check_crc(CRC_14443_B, recv, len) ) { - PrintAndLogEx(FAILED, "crc fail, retrying one more time"); - continue; - } + if ( !check_crc(CRC_14443_B, recv, len) ) { + PrintAndLogEx(FAILED, "crc fail, retrying one more time"); + continue; + } - memcpy(data + (blocknum * 4), resp.d.asBytes, 4); + memcpy(data + (blocknum * 4), resp.d.asBytes, 4); - if ( blocknum == 0xFF) { - //last read. - break; - } + if ( blocknum == 0xFF) { + //last read. + break; + } - retry = 0; - blocknum++; - if ( blocknum > blocks ) { - // read config block - blocknum = 0xFF; - } + retry = 0; + blocknum++; + if ( blocknum > blocks ) { + // read config block + blocknum = 0xFF; + } - printf("."); fflush(stdout); - } - } + printf("."); fflush(stdout); + } + } - if ( blocknum != 0xFF) { - PrintAndLogEx(NORMAL, "\n Dump failed"); - goto out; - } + if ( blocknum != 0xFF) { + PrintAndLogEx(NORMAL, "\n Dump failed"); + goto out; + } - PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "block# | data | ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+----------"); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "block# | data | ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+----------"); - for (int i = 0; i <= blocks; i++) { - PrintAndLogEx(NORMAL, - "%3d/0x%02X | %s | %s", - i, - i, - sprint_hex(data + (i*4), 4 ), - sprint_ascii(data + (i*4), 4) - ); - } + for (int i = 0; i <= blocks; i++) { + PrintAndLogEx(NORMAL, + "%3d/0x%02X | %s | %s", + i, + i, + sprint_hex(data + (i*4), 4 ), + sprint_ascii(data + (i*4), 4) + ); + } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "\n"); - size_t datalen = (blocks+1) * 4; - saveFileEML(filename, "eml", data, datalen, 4); - saveFile(filename, "bin", data, datalen); + size_t datalen = (blocks+1) * 4; + saveFileEML(filename, "eml", data, datalen, 4); + saveFile(filename, "bin", data, datalen); out: - return switch_off_field_14b(); + return switch_off_field_14b(); } uint32_t srix4kEncode(uint32_t value) { @@ -956,162 +956,162 @@ uint32_t srix4kEncode(uint32_t value) { // vv = value // pp = position // vv vv vv pp -4 bytes : 00 1A 20 01 +4 bytes : 00 1A 20 01 */ - // only the lower crumbs. - uint8_t block = (value & 0xFF); - uint8_t i = 0; - uint8_t valuebytes[] = {0,0,0}; + // only the lower crumbs. + uint8_t block = (value & 0xFF); + uint8_t i = 0; + uint8_t valuebytes[] = {0,0,0}; - num_to_bytes(value, 3, valuebytes); + num_to_bytes(value, 3, valuebytes); - // Scrambled part - // Crumb swapping of value. - uint8_t temp[] = {0,0}; - temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14 ) << 2 | CRUMB(value, 6)) << 4; - temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12 ) << 2 | CRUMB(value, 4); - temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10 ) << 2 | CRUMB(value, 2)) << 4; - temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8 ) << 2 | CRUMB(value, 0); + // Scrambled part + // Crumb swapping of value. + uint8_t temp[] = {0,0}; + temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14 ) << 2 | CRUMB(value, 6)) << 4; + temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12 ) << 2 | CRUMB(value, 4); + temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10 ) << 2 | CRUMB(value, 2)) << 4; + temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8 ) << 2 | CRUMB(value, 0); - // chksum part - uint32_t chksum = 0xFF - block; + // chksum part + uint32_t chksum = 0xFF - block; - // chksum is reduced by each nibbles of value. - for (i = 0; i < 3; ++i){ - chksum -= NIBBLE_HIGH(valuebytes[i]); - chksum -= NIBBLE_LOW(valuebytes[i]); - } - - // base4 conversion and left shift twice - i = 3; - uint8_t base4[] = {0,0,0,0}; - while( chksum !=0 ){ - base4[i--] = (chksum % 4 << 2); - chksum /= 4; + // chksum is reduced by each nibbles of value. + for (i = 0; i < 3; ++i){ + chksum -= NIBBLE_HIGH(valuebytes[i]); + chksum -= NIBBLE_LOW(valuebytes[i]); } - // merge scambled and chksum parts - uint32_t encvalue = - ( NIBBLE_LOW ( base4[0]) << 28 ) | - ( NIBBLE_HIGH( temp[0]) << 24 ) | + // base4 conversion and left shift twice + i = 3; + uint8_t base4[] = {0,0,0,0}; + while( chksum !=0 ){ + base4[i--] = (chksum % 4 << 2); + chksum /= 4; + } - ( NIBBLE_LOW ( base4[1]) << 20 ) | - ( NIBBLE_LOW ( temp[0]) << 16 ) | + // merge scambled and chksum parts + uint32_t encvalue = + ( NIBBLE_LOW ( base4[0]) << 28 ) | + ( NIBBLE_HIGH( temp[0]) << 24 ) | - ( NIBBLE_LOW ( base4[2]) << 12 ) | - ( NIBBLE_HIGH( temp[1]) << 8 ) | + ( NIBBLE_LOW ( base4[1]) << 20 ) | + ( NIBBLE_LOW ( temp[0]) << 16 ) | - ( NIBBLE_LOW ( base4[3]) << 4 ) | - NIBBLE_LOW ( temp[1] ); + ( NIBBLE_LOW ( base4[2]) << 12 ) | + ( NIBBLE_HIGH( temp[1]) << 8 ) | - PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue); - return encvalue; + ( NIBBLE_LOW ( base4[3]) << 4 ) | + NIBBLE_LOW ( temp[1] ); + + PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue); + return encvalue; } uint32_t srix4kDecode(uint32_t value) { - switch(value) { - case 0xC04F42C5: return 0x003139; - case 0xC1484807: return 0x002943; - case 0xC0C60848: return 0x001A20; - } - return 0; + switch(value) { + case 0xC04F42C5: return 0x003139; + case 0xC1484807: return 0x002943; + case 0xC0C60848: return 0x001A20; + } + return 0; } uint32_t srix4kDecodeCounter(uint32_t num) { - uint32_t value = ~num; - ++value; - return value; + uint32_t value = ~num; + ++value; + return value; } uint32_t srix4kGetMagicbytes( uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19 ){ #define MASK 0xFFFFFFFF; - uint32_t uid32 = uid & MASK; - uint32_t counter = srix4kDecodeCounter(block6); - uint32_t decodedBlock18 = srix4kDecode(block18); - uint32_t decodedBlock19 = srix4kDecode(block19); - uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1; + uint32_t uid32 = uid & MASK; + uint32_t counter = srix4kDecodeCounter(block6); + uint32_t decodedBlock18 = srix4kDecode(block18); + uint32_t decodedBlock19 = srix4kDecode(block19); + uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1; - uint32_t result = (uid32 * doubleBlock * counter) & MASK; - PrintAndLogEx(SUCCESS, "Magic bytes | %08X", result); - return result; + uint32_t result = (uid32 * doubleBlock * counter) & MASK; + PrintAndLogEx(SUCCESS, "Magic bytes | %08X", result); + return result; } int srix4kValid(const char *Cmd){ - uint64_t uid = 0xD00202501A4532F9; - uint32_t block6 = 0xFFFFFFFF; - uint32_t block18 = 0xC04F42C5; - uint32_t block19 = 0xC1484807; - uint32_t block21 = 0xD1BCABA4; + uint64_t uid = 0xD00202501A4532F9; + uint32_t block6 = 0xFFFFFFFF; + uint32_t block18 = 0xC04F42C5; + uint32_t block19 = 0xC1484807; + uint32_t block21 = 0xD1BCABA4; - uint32_t test_b18 = 0x00313918; - uint32_t test_b18_enc = srix4kEncode(test_b18); - //uint32_t test_b18_dec = srix4kDecode(test_b18_enc); - PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , ""); + uint32_t test_b18 = 0x00313918; + uint32_t test_b18_enc = srix4kEncode(test_b18); + //uint32_t test_b18_dec = srix4kDecode(test_b18_enc); + PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , ""); - uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19); - PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21); - return 0; + uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19); + PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21); + return 0; } bool waitCmd14b(bool verbose) { - bool crc = false; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - uint8_t status = 0; - uint16_t len = 0; + bool crc = false; + uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t status = 0; + uint16_t len = 0; UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - status = (resp.arg[0] & 0xFF); - if ( status > 0 ) return false; + status = (resp.arg[0] & 0xFF); + if ( status > 0 ) return false; - len = (resp.arg[1] & 0xFFFF); + len = (resp.arg[1] & 0xFFFF); - memcpy(data, resp.d.asBytes, len); + memcpy(data, resp.d.asBytes, len); - if (verbose) { - if ( len >= 3 ) { - crc = check_crc(CRC_14443_B, data, len); + if (verbose) { + if ( len >= 3 ) { + crc = check_crc(CRC_14443_B, data, len); - PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s", - len, - sprint_hex(data, len-2), - data[len-2], - data[len-1], - (crc) ? "OK" : "FAIL" - ); - } else { - PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len) ); - } - } - return true; + PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s", + len, + sprint_hex(data, len-2), + data[len-2], + data[len-1], + (crc) ? "OK" : "FAIL" + ); + } else { + PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len) ); + } + } + return true; } else { PrintAndLogEx(WARNING, "command execution timeout"); - return false; + return false; } } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"}, - {"info", CmdHF14Binfo, 0, "Tag information"}, - {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"}, - {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, - {"reader", CmdHF14BReader, 0, "Act as a 14443B reader to identify a tag"}, - {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, - {"sniff", CmdHF14BSniff, 0, "Eavesdrop ISO 14443B"}, - {"sriread", CmdHF14BReadSri, 0, "Read contents of a SRI512 | SRIX4K tag"}, - {"sriwrite", CmdHF14BWriteSri, 0, "Write data to a SRI512 | SRIX4K tag"}, - //{"valid", srix4kValid, 1, "srix4k checksum test"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"}, + {"info", CmdHF14Binfo, 0, "Tag information"}, + {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"}, + {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, + {"reader", CmdHF14BReader, 0, "Act as a 14443B reader to identify a tag"}, + {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, + {"sniff", CmdHF14BSniff, 0, "Eavesdrop ISO 14443B"}, + {"sriread", CmdHF14BReadSri, 0, "Read contents of a SRI512 | SRIX4K tag"}, + {"sriwrite", CmdHF14BWriteSri, 0, "Write data to a SRI512 | SRIX4K tag"}, + //{"valid", srix4kValid, 1, "srix4k checksum test"}, + {NULL, NULL, 0, NULL} }; int CmdHF14B(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 74b279620..f77658c19 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -26,8 +26,8 @@ #include "cmdhf.h" #include "prng.h" #include "mbedtls/sha1.h" -#include "mifare.h" // structs/enum for ISO14B -#include "protocols.h" // definitions of ISO14B protocol +#include "mifare.h" // structs/enum for ISO14B +#include "protocols.h" // definitions of ISO14B protocol int usage_hf_14b_info(void); int usage_hf_14b_reader(void); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index bdec7c339..9164ac70e 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -24,313 +24,313 @@ // variant, but offers the possibility to analyze the waveforms directly. #include "cmdhf15.h" -#define FrameSOF Iso15693FrameSOF -#define Logic0 Iso15693Logic0 -#define Logic1 Iso15693Logic1 -#define FrameEOF Iso15693FrameEOF +#define FrameSOF Iso15693FrameSOF +#define Logic0 Iso15693Logic0 +#define Logic1 Iso15693Logic1 +#define FrameEOF Iso15693FrameEOF -#define Crc(data, len) crc(CRC_15693, (data), (len)) -#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) -#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) +#define Crc(data, len) crc(CRC_15693, (data), (len)) +#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) +#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) -#define sprintUID(target, uid) Iso15693sprintUID((target), (uid)) +#define sprintUID(target, uid) Iso15693sprintUID((target), (uid)) // structure and database for uid -> tagtype lookups typedef struct { - uint64_t uid; - int mask; // how many MSB bits used - char* desc; + uint64_t uid; + int mask; // how many MSB bits used + char* desc; } productName; const productName uidmapping[] = { - // UID, #significant Bits, "Vendor(+Product)" - { 0xE001000000000000LL, 16, "Motorola UK" }, + // UID, #significant Bits, "Vendor(+Product)" + { 0xE001000000000000LL, 16, "Motorola UK" }, - // E0 02 xx - // 02 = ST Microelectronics - // XX = IC id (Chip ID Family) - { 0xE002000000000000LL, 16, "ST Microelectronics SA France" }, - { 0xE002050000000000LL, 24, "ST Microelectronics; LRI64 [IC id = 05]"}, - { 0xE002080000000000LL, 24, "ST Microelectronics; LRI2K [IC id = 08]"}, - { 0xE0020A0000000000LL, 24, "ST Microelectronics; LRIS2K [IC id = 10]"}, - { 0xE002440000000000LL, 24, "ST Microelectronics; LRIS64K [IC id = 68]"}, + // E0 02 xx + // 02 = ST Microelectronics + // XX = IC id (Chip ID Family) + { 0xE002000000000000LL, 16, "ST Microelectronics SA France" }, + { 0xE002050000000000LL, 24, "ST Microelectronics; LRI64 [IC id = 05]"}, + { 0xE002080000000000LL, 24, "ST Microelectronics; LRI2K [IC id = 08]"}, + { 0xE0020A0000000000LL, 24, "ST Microelectronics; LRIS2K [IC id = 10]"}, + { 0xE002440000000000LL, 24, "ST Microelectronics; LRIS64K [IC id = 68]"}, - { 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" }, + { 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" }, - // E0 04 xx - // 04 = Manufacturer code (Philips/NXP) - // XX = IC id (Chip ID Family) - //I-Code SLI SL2 ICS20 [IC id = 01] - //I-Code SLI-S [IC id = 02] - //I-Code SLI-L [IC id = 03] - //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)] - //I-Code SLIX-S [IC id = 02 + bit36 set to 1] - //I-Code SLIX-L [IC id = 03 + bit36 set to 1] - { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, - { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX)" }, - { 0xE004020000000000LL, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" }, - { 0xE004030000000000LL, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" }, + // E0 04 xx + // 04 = Manufacturer code (Philips/NXP) + // XX = IC id (Chip ID Family) + //I-Code SLI SL2 ICS20 [IC id = 01] + //I-Code SLI-S [IC id = 02] + //I-Code SLI-L [IC id = 03] + //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)] + //I-Code SLIX-S [IC id = 02 + bit36 set to 1] + //I-Code SLIX-L [IC id = 03 + bit36 set to 1] + { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, + { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX)" }, + { 0xE004020000000000LL, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" }, + { 0xE004030000000000LL, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" }, - // E0 05 XX .. .. .. - // 05 = Manufacturer code (Infineon) - // XX = IC id (Chip ID Family) - { 0xE005000000000000LL, 16, "Infineon Technologies AG Germany" }, - { 0xE005A10000000000LL, 24, "Infineon; SRF55V01P [IC id = 161] plain mode 1kBit"}, - { 0xE005A80000000000LL, 24, "Infineon; SRF55V01P [IC id = 168] pilot series 1kBit"}, - { 0xE005400000000000LL, 24, "Infineon; SRF55V02P [IC id = 64] plain mode 2kBit"}, - { 0xE005000000000000LL, 24, "Infineon; SRF55V10P [IC id = 00] plain mode 10KBit"}, - { 0xE005500000000000LL, 24, "Infineon; SRF55V02S [IC id = 80] secure mode 2kBit"}, - { 0xE005100000000000LL, 24, "Infineon; SRF55V10S [IC id = 16] secure mode 10KBit"}, - { 0xE0051E0000000000LL, 23, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, - { 0xE005200000000000LL, 21, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, + // E0 05 XX .. .. .. + // 05 = Manufacturer code (Infineon) + // XX = IC id (Chip ID Family) + { 0xE005000000000000LL, 16, "Infineon Technologies AG Germany" }, + { 0xE005A10000000000LL, 24, "Infineon; SRF55V01P [IC id = 161] plain mode 1kBit"}, + { 0xE005A80000000000LL, 24, "Infineon; SRF55V01P [IC id = 168] pilot series 1kBit"}, + { 0xE005400000000000LL, 24, "Infineon; SRF55V02P [IC id = 64] plain mode 2kBit"}, + { 0xE005000000000000LL, 24, "Infineon; SRF55V10P [IC id = 00] plain mode 10KBit"}, + { 0xE005500000000000LL, 24, "Infineon; SRF55V02S [IC id = 80] secure mode 2kBit"}, + { 0xE005100000000000LL, 24, "Infineon; SRF55V10S [IC id = 16] secure mode 10KBit"}, + { 0xE0051E0000000000LL, 23, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, + { 0xE005200000000000LL, 21, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, - { 0xE006000000000000LL, 16, "Cylink USA" }, + { 0xE006000000000000LL, 16, "Cylink USA" }, - // E0 07 xx - // 07 = Texas Instruments - // XX = from bit 41 to bit 43 = product configuration - from bit 44 to bit 47 IC id (Chip ID Family) - //Tag IT RFIDType-I Plus, 2kBit, TI Inlay - //Tag-it HF-I Plus Inlay [IC id = 00] -> b'0000 000 2kBit - //Tag-it HF-I Plus Chip [IC id = 64] -> b'1000 000 2kBit - //Tag-it HF-I Standard Chip / Inlays [IC id = 96] -> b'1100 000 256Bit - //Tag-it HF-I Pro Chip / Inlays [IC id = 98] -> b'1100 010 256Bit, Password protection - { 0xE007000000000000LL, 16, "Texas Instrument France" }, - { 0xE007000000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" }, - { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" }, - { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" }, - { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" }, - { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" }, + // E0 07 xx + // 07 = Texas Instruments + // XX = from bit 41 to bit 43 = product configuration - from bit 44 to bit 47 IC id (Chip ID Family) + //Tag IT RFIDType-I Plus, 2kBit, TI Inlay + //Tag-it HF-I Plus Inlay [IC id = 00] -> b'0000 000 2kBit + //Tag-it HF-I Plus Chip [IC id = 64] -> b'1000 000 2kBit + //Tag-it HF-I Standard Chip / Inlays [IC id = 96] -> b'1100 000 256Bit + //Tag-it HF-I Pro Chip / Inlays [IC id = 98] -> b'1100 010 256Bit, Password protection + { 0xE007000000000000LL, 16, "Texas Instrument France" }, + { 0xE007000000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" }, + { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" }, + { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" }, + { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" }, + { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" }, - { 0xE008000000000000LL, 16, "Fujitsu Limited Japan" }, - { 0xE009000000000000LL, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, - { 0xE00A000000000000LL, 16, "NEC Japan" }, - { 0xE00B000000000000LL, 16, "Oki Electric Industry Co. Ltd Japan" }, - { 0xE00C000000000000LL, 16, "Toshiba Corp. Japan" }, - { 0xE00D000000000000LL, 16, "Mitsubishi Electric Corp. Japan" }, - { 0xE00E000000000000LL, 16, "Samsung Electronics Co. Ltd Korea" }, - { 0xE00F000000000000LL, 16, "Hynix / Hyundai, Korea" }, - { 0xE010000000000000LL, 16, "LG-Semiconductors Co. Ltd Korea" }, - { 0xE011000000000000LL, 16, "Emosyn-EM Microelectronics USA" }, + { 0xE008000000000000LL, 16, "Fujitsu Limited Japan" }, + { 0xE009000000000000LL, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, + { 0xE00A000000000000LL, 16, "NEC Japan" }, + { 0xE00B000000000000LL, 16, "Oki Electric Industry Co. Ltd Japan" }, + { 0xE00C000000000000LL, 16, "Toshiba Corp. Japan" }, + { 0xE00D000000000000LL, 16, "Mitsubishi Electric Corp. Japan" }, + { 0xE00E000000000000LL, 16, "Samsung Electronics Co. Ltd Korea" }, + { 0xE00F000000000000LL, 16, "Hynix / Hyundai, Korea" }, + { 0xE010000000000000LL, 16, "LG-Semiconductors Co. Ltd Korea" }, + { 0xE011000000000000LL, 16, "Emosyn-EM Microelectronics USA" }, - { 0xE012000000000000LL, 16, "HID Corporation" }, - { 0xE012000000000000LL, 16, "INSIDE Technology France" }, - { 0xE013000000000000LL, 16, "ORGA Kartensysteme GmbH Germany" }, - { 0xE014000000000000LL, 16, "SHARP Corporation Japan" }, - { 0xE015000000000000LL, 16, "ATMEL France" }, + { 0xE012000000000000LL, 16, "HID Corporation" }, + { 0xE012000000000000LL, 16, "INSIDE Technology France" }, + { 0xE013000000000000LL, 16, "ORGA Kartensysteme GmbH Germany" }, + { 0xE014000000000000LL, 16, "SHARP Corporation Japan" }, + { 0xE015000000000000LL, 16, "ATMEL France" }, - { 0xE016000000000000LL, 16, "EM Microelectronic-Marin SA Switzerland (Skidata)"}, - { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034 [IC id = 01] (Read/Write - no AFI)"}, - { 0xE0160C0000000000LL, 24, "EM-Marin SA (Skidata); EM4035 [IC id = 03] (Read/Write - replaced by 4233)"}, - { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135 [IC id = 04] (Read/Write - replaced by 4233) 36x64bit start page 13"}, - { 0xE016140000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 05] 28pF"}, - { 0xE016180000000000LL, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"}, - { 0xE0161C0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 07] 23,5pF (Read/Write)"}, - { 0xE016200000000000LL, 24, "EM-Marin SA (Skidata); EM4033 [IC id = 08] 23,5pF (Read Only - no AFI / no DSFID / no security blocks)"}, - { 0xE016240000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 09] 23,5pF CustomerID-102"}, - { 0xE016280000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 10] 23,5pF (1Kb flash memory - not provide High Security mode and QuietStorage feature)" }, - { 0xE0163C0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 15] 23,5pF"}, - { 0xE0167C0000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 31] 95pF"}, - { 0xE016940000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 37] 95pF 51x64bit "}, - { 0xE0169c0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 39] 95pF (Read/Write)" }, - { 0xE016A80000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 42] 97pF" }, - { 0xE016BC0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 47] 97pF" }, + { 0xE016000000000000LL, 16, "EM Microelectronic-Marin SA Switzerland (Skidata)"}, + { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034 [IC id = 01] (Read/Write - no AFI)"}, + { 0xE0160C0000000000LL, 24, "EM-Marin SA (Skidata); EM4035 [IC id = 03] (Read/Write - replaced by 4233)"}, + { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135 [IC id = 04] (Read/Write - replaced by 4233) 36x64bit start page 13"}, + { 0xE016140000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 05] 28pF"}, + { 0xE016180000000000LL, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"}, + { 0xE0161C0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 07] 23,5pF (Read/Write)"}, + { 0xE016200000000000LL, 24, "EM-Marin SA (Skidata); EM4033 [IC id = 08] 23,5pF (Read Only - no AFI / no DSFID / no security blocks)"}, + { 0xE016240000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 09] 23,5pF CustomerID-102"}, + { 0xE016280000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 10] 23,5pF (1Kb flash memory - not provide High Security mode and QuietStorage feature)" }, + { 0xE0163C0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 15] 23,5pF"}, + { 0xE0167C0000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 31] 95pF"}, + { 0xE016940000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 37] 95pF 51x64bit "}, + { 0xE0169c0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 39] 95pF (Read/Write)" }, + { 0xE016A80000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 42] 97pF" }, + { 0xE016BC0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 47] 97pF" }, - { 0xE017000000000000LL, 16, "KSW Microtec GmbH Germany" }, - { 0xE018000000000000LL, 16, "ZMD AG Germany" }, - { 0xE019000000000000LL, 16, "XICOR, Inc. USA" }, - { 0xE01A000000000000LL, 16, "Sony Corporation Japan Identifier Company Country" }, - { 0xE01B000000000000LL, 16, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, - { 0xE01C000000000000LL, 16, "Emosyn USA" }, - { 0xE01D000000000000LL, 16, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, - { 0xE01E000000000000LL, 16, "Magellan Technology Pty Limited Australia" }, - { 0xE01F000000000000LL, 16, "Melexis NV BO Switzerland" }, - { 0xE020000000000000LL, 16, "Renesas Technology Corp. Japan" }, - { 0xE021000000000000LL, 16, "TAGSYS France" }, - { 0xE022000000000000LL, 16, "Transcore USA" }, - { 0xE023000000000000LL, 16, "Shanghai belling corp., ltd. China" }, - { 0xE024000000000000LL, 16, "Masktech Germany Gmbh Germany" }, - { 0xE025000000000000LL, 16, "Innovision Research and Technology Plc UK" }, - { 0xE026000000000000LL, 16, "Hitachi ULSI Systems Co., Ltd. Japan" }, - { 0xE027000000000000LL, 16, "Cypak AB Sweden" }, - { 0xE028000000000000LL, 16, "Ricoh Japan" }, - { 0xE029000000000000LL, 16, "ASK France" }, - { 0xE02A000000000000LL, 16, "Unicore Microsystems, LLC Russian Federation" }, - { 0xE02B000000000000LL, 16, "Dallas Semiconductor/Maxim USA" }, - { 0xE02C000000000000LL, 16, "Impinj, Inc. USA" }, - { 0xE02D000000000000LL, 16, "RightPlug Alliance USA" }, - { 0xE02E000000000000LL, 16, "Broadcom Corporation USA" }, - { 0xE02F000000000000LL, 16, "MStar Semiconductor, Inc Taiwan, ROC" }, - { 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" }, - { 0xE031000000000000LL, 16, "RFIDsec Denmark" }, - { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" }, - { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, - { 0xE034000000000000LL, 16, "Mikron JSC Russia" }, - { 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" }, - { 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" }, - { 0xE037000000000000LL, 16, "Kovio USA" }, - { 0xE038000000000000LL, 16, "HMT Microelectronic Ltd Switzerland Identifier Company Country" }, - { 0xE039000000000000LL, 16, "Silicon Craft Technology Thailand" }, - { 0xE03A000000000000LL, 16, "Advanced Film Device Inc. Japan" }, - { 0xE03B000000000000LL, 16, "Nitecrest Ltd UK" }, - { 0xE03C000000000000LL, 16, "Verayo Inc. USA" }, - { 0xE03D000000000000LL, 16, "HID Global USA" }, - { 0xE03E000000000000LL, 16, "Productivity Engineering Gmbh Germany" }, - { 0xE03F000000000000LL, 16, "Austriamicrosystems AG (reserved) Austria" }, - { 0xE040000000000000LL, 16, "Gemalto SA France" }, - { 0xE041000000000000LL, 16, "Renesas Electronics Corporation Japan" }, - { 0xE042000000000000LL, 16, "3Alogics Inc Korea" }, - { 0xE043000000000000LL, 16, "Top TroniQ Asia Limited Hong Kong" }, - { 0xE044000000000000LL, 16, "Gentag Inc (USA) USA" }, - { 0,0,"no tag-info available" } // must be the last entry + { 0xE017000000000000LL, 16, "KSW Microtec GmbH Germany" }, + { 0xE018000000000000LL, 16, "ZMD AG Germany" }, + { 0xE019000000000000LL, 16, "XICOR, Inc. USA" }, + { 0xE01A000000000000LL, 16, "Sony Corporation Japan Identifier Company Country" }, + { 0xE01B000000000000LL, 16, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, + { 0xE01C000000000000LL, 16, "Emosyn USA" }, + { 0xE01D000000000000LL, 16, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, + { 0xE01E000000000000LL, 16, "Magellan Technology Pty Limited Australia" }, + { 0xE01F000000000000LL, 16, "Melexis NV BO Switzerland" }, + { 0xE020000000000000LL, 16, "Renesas Technology Corp. Japan" }, + { 0xE021000000000000LL, 16, "TAGSYS France" }, + { 0xE022000000000000LL, 16, "Transcore USA" }, + { 0xE023000000000000LL, 16, "Shanghai belling corp., ltd. China" }, + { 0xE024000000000000LL, 16, "Masktech Germany Gmbh Germany" }, + { 0xE025000000000000LL, 16, "Innovision Research and Technology Plc UK" }, + { 0xE026000000000000LL, 16, "Hitachi ULSI Systems Co., Ltd. Japan" }, + { 0xE027000000000000LL, 16, "Cypak AB Sweden" }, + { 0xE028000000000000LL, 16, "Ricoh Japan" }, + { 0xE029000000000000LL, 16, "ASK France" }, + { 0xE02A000000000000LL, 16, "Unicore Microsystems, LLC Russian Federation" }, + { 0xE02B000000000000LL, 16, "Dallas Semiconductor/Maxim USA" }, + { 0xE02C000000000000LL, 16, "Impinj, Inc. USA" }, + { 0xE02D000000000000LL, 16, "RightPlug Alliance USA" }, + { 0xE02E000000000000LL, 16, "Broadcom Corporation USA" }, + { 0xE02F000000000000LL, 16, "MStar Semiconductor, Inc Taiwan, ROC" }, + { 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" }, + { 0xE031000000000000LL, 16, "RFIDsec Denmark" }, + { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" }, + { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, + { 0xE034000000000000LL, 16, "Mikron JSC Russia" }, + { 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" }, + { 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" }, + { 0xE037000000000000LL, 16, "Kovio USA" }, + { 0xE038000000000000LL, 16, "HMT Microelectronic Ltd Switzerland Identifier Company Country" }, + { 0xE039000000000000LL, 16, "Silicon Craft Technology Thailand" }, + { 0xE03A000000000000LL, 16, "Advanced Film Device Inc. Japan" }, + { 0xE03B000000000000LL, 16, "Nitecrest Ltd UK" }, + { 0xE03C000000000000LL, 16, "Verayo Inc. USA" }, + { 0xE03D000000000000LL, 16, "HID Global USA" }, + { 0xE03E000000000000LL, 16, "Productivity Engineering Gmbh Germany" }, + { 0xE03F000000000000LL, 16, "Austriamicrosystems AG (reserved) Austria" }, + { 0xE040000000000000LL, 16, "Gemalto SA France" }, + { 0xE041000000000000LL, 16, "Renesas Electronics Corporation Japan" }, + { 0xE042000000000000LL, 16, "3Alogics Inc Korea" }, + { 0xE043000000000000LL, 16, "Top TroniQ Asia Limited Hong Kong" }, + { 0xE044000000000000LL, 16, "Gentag Inc (USA) USA" }, + { 0,0,"no tag-info available" } // must be the last entry }; // fast method to just read the UID of a tag (collission detection not supported) -// *buf should be large enough to fit the 64bit uid +// *buf should be large enough to fit the 64bit uid // returns 1 if suceeded int getUID(uint8_t *buf) { - UsbCommand resp; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + UsbCommand resp; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - c.d.asBytes[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; - c.d.asBytes[1] = ISO15_CMD_INVENTORY; - c.d.asBytes[2] = 0; // mask length + c.d.asBytes[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; + c.d.asBytes[1] = ISO15_CMD_INVENTORY; + c.d.asBytes[2] = 0; // mask length - AddCrc(c.d.asBytes, 3); - c.arg[0] = 5; // len + AddCrc(c.d.asBytes, 3); + c.arg[0] = 5; // len - uint8_t retry; + uint8_t retry; - // don't give up the at the first try - for (retry = 0; retry < 3; retry++) { + // don't give up the at the first try + for (retry = 0; retry < 3; retry++) { - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t resplen = resp.arg[0]; - if (resplen >= 12 && CheckCrc(resp.d.asBytes, 12)) { - memcpy(buf, resp.d.asBytes + 2, 8); - return 1; - } - } - } // retry + uint8_t resplen = resp.arg[0]; + if (resplen >= 12 && CheckCrc(resp.d.asBytes, 12)) { + memcpy(buf, resp.d.asBytes + 2, 8); + return 1; + } + } + } // retry - if ( retry >= 3 ) - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + if ( retry >= 3 ) + PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 0; + return 0; } // get a product description based on the UID -// uid[8] tag uid +// uid[8] tag uid // returns description of the best match static char* getTagInfo_15(uint8_t *uid) { - uint64_t myuid, mask; - int i = 0, best = -1; - memcpy(&myuid, uid, sizeof(uint64_t)); - while (uidmapping[i].mask > 0) { - mask = (~0LL) << (64-uidmapping[i].mask); - if ((myuid & mask) == uidmapping[i].uid) { - if (best == -1) { - best = i; - } else { - if (uidmapping[i].mask > uidmapping[best].mask) { - best=i; - } - } - } - i++; - } + uint64_t myuid, mask; + int i = 0, best = -1; + memcpy(&myuid, uid, sizeof(uint64_t)); + while (uidmapping[i].mask > 0) { + mask = (~0LL) << (64-uidmapping[i].mask); + if ((myuid & mask) == uidmapping[i].uid) { + if (best == -1) { + best = i; + } else { + if (uidmapping[i].mask > uidmapping[best].mask) { + best=i; + } + } + } + i++; + } - if (best >= 0) - return uidmapping[best].desc; - return uidmapping[i].desc; + if (best >= 0) + return uidmapping[best].desc; + return uidmapping[i].desc; } // return a clear-text message to an errorcode static char* TagErrorStr(uint8_t error) { - switch (error) { - case 0x01: return "The command is not supported"; - case 0x02: return "The command is not recognised"; - case 0x03: return "The option is not supported."; - case 0x0f: return "Unknown error."; - case 0x10: return "The specified block is not available (doesn't exist)."; - case 0x11: return "The specified block is already -locked and thus cannot be locked again"; - case 0x12: return "The specified block is locked and its content cannot be changed."; - case 0x13: return "The specified block was not successfully programmed."; - case 0x14: return "The specified block was not successfully locked."; - default: return "Reserved for Future Use or Custom command error."; - } + switch (error) { + case 0x01: return "The command is not supported"; + case 0x02: return "The command is not recognised"; + case 0x03: return "The option is not supported."; + case 0x0f: return "Unknown error."; + case 0x10: return "The specified block is not available (doesn't exist)."; + case 0x11: return "The specified block is already -locked and thus cannot be locked again"; + case 0x12: return "The specified block is locked and its content cannot be changed."; + case 0x13: return "The specified block was not successfully programmed."; + case 0x14: return "The specified block was not successfully locked."; + default: return "Reserved for Future Use or Custom command error."; + } } int usage_15_demod(void){ - PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" - "Gather samples with 'hf 15 read' / 'hf 15 record'"); - return 0; + PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" + "Gather samples with 'hf 15 read' / 'hf 15 record'"); + return 0; } int usage_15_samples(void){ - PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n" - "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal"); - return 0; + PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n" + "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal"); + return 0; } int usage_15_info(void){ - PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" - "command may fail, depending on tag.\n" - "defaults to '1 out of 4' mode\n" - "\n" - "Usage: hf 15 info [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "Examples:\n" - "\thf 15 info u"); - return 0; + PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" + "command may fail, depending on tag.\n" + "defaults to '1 out of 4' mode\n" + "\n" + "Usage: hf 15 info [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "Examples:\n" + "\thf 15 info u"); + return 0; } int usage_15_record(void){ - PrintAndLogEx(NORMAL, "Record activity without enableing carrier"); - return 0; + PrintAndLogEx(NORMAL, "Record activity without enableing carrier"); + return 0; } int usage_15_reader(void){ - PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n" - "\n" - "Usage: hf 15 reader [h]\n" - "Options:\n" - "\th this help\n" - "\n" - "Example:\n" - "\thf 15 reader"); - return 0; + PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n" + "\n" + "Usage: hf 15 reader [h]\n" + "Options:\n" + "\th this help\n" + "\n" + "Example:\n" + "\thf 15 reader"); + return 0; } int usage_15_sim(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 sim \n" - "\n" - "Example:\n" - "\thf 15 sim E016240000000000"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 sim \n" + "\n" + "Example:\n" + "\thf 15 sim E016240000000000"); + return 0; } int usage_15_findafi(void){ - PrintAndLogEx(NORMAL, "'hf 15 finafi' This command needs a helptext. Feel free to add one!"); - return 0; + PrintAndLogEx(NORMAL, "'hf 15 finafi' This command needs a helptext. Feel free to add one!"); + return 0; } int usage_15_dump(void){ - PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" - "\n" - "Usage: hf 15 dump [h] \n" - "Options:\n" - "\th this help\n" - "\tf filename, if no UID will be used as filename\n" - "\n" - "Example:\n" - "\thf 15 dump f\n" - "\thf 15 dump f mydump"); - return 0; + PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" + "\n" + "Usage: hf 15 dump [h] \n" + "Options:\n" + "\th this help\n" + "\tf filename, if no UID will be used as filename\n" + "\n" + "Example:\n" + "\thf 15 dump f\n" + "\thf 15 dump f mydump"); + return 0; } int usage_15_restore(void){ char *options[][2]={ @@ -358,133 +358,133 @@ int usage_15_raw(void){ return 0; } int usage_15_read(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\tpage#: page number 0-255"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tpage#: page number 0-255"); + return 0; } int usage_15_write(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\t-o set OPTION Flag (needed for TI)\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\tpage#: page number 0-255\n" - "\thexdata: data to be written eg AA BB CC DD"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\t-o set OPTION Flag (needed for TI)\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tpage#: page number 0-255\n" + "\thexdata: data to be written eg AA BB CC DD"); + return 0; } int usage_15_readmulti(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\tstart#: page number to start 0-255\n" - "\tcount#: number of pages"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tstart#: page number to start 0-255\n" + "\tcount#: number of pages"); + return 0; } // Mode 3 //helptext int CmdHF15Demod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_demod(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_demod(); - // The sampling rate is 106.353 ksps/s, for T = 18.8 us - int i, j; - int max = 0, maxPos = 0; - int skip = 4; + // The sampling rate is 106.353 ksps/s, for T = 18.8 us + int i, j; + int max = 0, maxPos = 0; + int skip = 4; - if (GraphTraceLen < 1000) return 0; + if (GraphTraceLen < 1000) return 0; - // First, correlate for SOF - for (i = 0; i < 1000; i++) { - int corr = 0; - for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) { - corr += FrameSOF[j] * GraphBuffer[i + (j / skip)]; - } - if (corr > max) { - max = corr; - maxPos = i; - } - } + // First, correlate for SOF + for (i = 0; i < 1000; i++) { + int corr = 0; + for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) { + corr += FrameSOF[j] * GraphBuffer[i + (j / skip)]; + } + if (corr > max) { + max = corr; + maxPos = i; + } + } - PrintAndLogEx(NORMAL, "SOF at %d, correlation %d", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); + PrintAndLogEx(NORMAL, "SOF at %d, correlation %d", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); - i = maxPos + ARRAYLEN(FrameSOF) / skip; - int k = 0; - uint8_t outBuf[20]; - memset(outBuf, 0, sizeof(outBuf)); - uint8_t mask = 0x01; - for (;;) { - int corr0 = 0, corr1 = 0, corrEOF = 0; - for (j = 0; j < ARRAYLEN(Logic0); j += skip) { - corr0 += Logic0[j] * GraphBuffer[i + (j / skip)]; - } - for (j = 0; j < ARRAYLEN(Logic1); j += skip) { - corr1 += Logic1[j] * GraphBuffer[i + (j / skip)]; - } - for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { - corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)]; - } - // Even things out by the length of the target waveform. - corr0 *= 4; - corr1 *= 4; + i = maxPos + ARRAYLEN(FrameSOF) / skip; + int k = 0; + uint8_t outBuf[20]; + memset(outBuf, 0, sizeof(outBuf)); + uint8_t mask = 0x01; + for (;;) { + int corr0 = 0, corr1 = 0, corrEOF = 0; + for (j = 0; j < ARRAYLEN(Logic0); j += skip) { + corr0 += Logic0[j] * GraphBuffer[i + (j / skip)]; + } + for (j = 0; j < ARRAYLEN(Logic1); j += skip) { + corr1 += Logic1[j] * GraphBuffer[i + (j / skip)]; + } + for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { + corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)]; + } + // Even things out by the length of the target waveform. + corr0 *= 4; + corr1 *= 4; - if (corrEOF > corr1 && corrEOF > corr0) { - PrintAndLogEx(NORMAL, "EOF at %d", i); - break; - } else if (corr1 > corr0) { - i += ARRAYLEN(Logic1) / skip; - outBuf[k] |= mask; - } else { - i += ARRAYLEN(Logic0) / skip; - } - mask <<= 1; - if (mask == 0) { - k++; - mask = 0x01; - } - if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) { - PrintAndLogEx(NORMAL, "ran off end!"); - break; - } - } + if (corrEOF > corr1 && corrEOF > corr0) { + PrintAndLogEx(NORMAL, "EOF at %d", i); + break; + } else if (corr1 > corr0) { + i += ARRAYLEN(Logic1) / skip; + outBuf[k] |= mask; + } else { + i += ARRAYLEN(Logic0) / skip; + } + mask <<= 1; + if (mask == 0) { + k++; + mask = 0x01; + } + if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) { + PrintAndLogEx(NORMAL, "ran off end!"); + break; + } + } - if (mask != 0x01) { - PrintAndLogEx(WARNING, "Error, uneven octet! (discard extra bits!)"); - PrintAndLogEx(NORMAL, " mask = %02x", mask); - } - PrintAndLogEx(NORMAL, "%d octets", k); + if (mask != 0x01) { + PrintAndLogEx(WARNING, "Error, uneven octet! (discard extra bits!)"); + PrintAndLogEx(NORMAL, " mask = %02x", mask); + } + PrintAndLogEx(NORMAL, "%d octets", k); - for (i = 0; i < k; i++) - PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); + for (i = 0; i < k; i++) + PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); - PrintAndLogEx(NORMAL, "CRC %04x", Crc(outBuf, k - 2)); - return 0; + PrintAndLogEx(NORMAL, "CRC %04x", Crc(outBuf, k - 2)); + return 0; } // * Acquire Samples as Reader (enables carrier, sends inquiry) //helptext int CmdHF15Samples(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_samples(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_samples(); - UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); - getSamples(0, false); - return 0; + getSamples(0, false); + return 0; } /** @@ -493,552 +493,552 @@ int CmdHF15Samples(const char *Cmd) { */ int CmdHF15Info(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info(); - UsbCommand resp; - uint8_t *recv; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - char cmdbuf[100]; - char *cmd = cmdbuf; - memset(cmdbuf, 0, sizeof(cmdbuf)); + UsbCommand resp; + uint8_t *recv; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + char cmdbuf[100]; + char *cmd = cmdbuf; + memset(cmdbuf, 0, sizeof(cmdbuf)); - strncpy(cmd, Cmd, 99); + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) + return 0; - AddCrc(req, c.arg[0]); - c.arg[0] += 2; + AddCrc(req, c.arg[0]); + c.arg[0] += 2; - //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + return 1; + } - uint32_t status = resp.arg[0]; + uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); - return 1; - } + if ( status < 2 ) { + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); - PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); - PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); + PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); + PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); - // DSFID - if (recv[1] & 0x01) - PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); - else - PrintAndLogEx(NORMAL, " - DSFID not supported"); + // DSFID + if (recv[1] & 0x01) + PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); + else + PrintAndLogEx(NORMAL, " - DSFID not supported"); - // AFI - if (recv[1] & 0x02) - PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); - else - PrintAndLogEx(NORMAL, " - AFI not supported"); + // AFI + if (recv[1] & 0x02) + PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); + else + PrintAndLogEx(NORMAL, " - AFI not supported"); - // IC reference - if (recv[1] & 0x08) - PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); - else - PrintAndLogEx(NORMAL, " - IC reference not supported"); + // IC reference + if (recv[1] & 0x08) + PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); + else + PrintAndLogEx(NORMAL, " - IC reference not supported"); - // memory - if (recv[1] & 0x04) { - PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); - uint8_t blocks = recv[12]+1; - uint8_t size = (recv[13] & 0x1F); - PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks ); - } else { - PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); - } - PrintAndLogEx(NORMAL, "\n"); - return 0; + // memory + if (recv[1] & 0x04) { + PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); + uint8_t blocks = recv[12]+1; + uint8_t size = (recv[13] & 0x1F); + PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks ); + } else { + PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); + } + PrintAndLogEx(NORMAL, "\n"); + return 0; } // Record Activity without enabeling carrier //helptext int CmdHF15Record(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_record(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_record(); - UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } // used with 'hf search' int HF15Reader(const char *Cmd, bool verbose) { - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - if (!getUID(uid)) { - if (verbose) PrintAndLogEx(WARNING, "No tag found."); - return 0; - } + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + if (!getUID(uid)) { + if (verbose) PrintAndLogEx(WARNING, "No tag found."); + return 0; + } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); - PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); - return 1; + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); + PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); + return 1; } int CmdHF15Reader(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_reader(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_reader(); - HF15Reader(Cmd, true); - return 0; + HF15Reader(Cmd, true); + return 0; } // Simulation is still not working very good // helptext int CmdHF15Sim(const char *Cmd) { - char cmdp =tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); + char cmdp =tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - if (param_gethex(Cmd, 0, uid, 16)) { - PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); - return 0; - } + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + if (param_gethex(Cmd, 0, uid, 16)) { + PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); + return 0; + } - PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); + PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); - UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; - memcpy(c.d.asBytes, uid, 8); - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; + memcpy(c.d.asBytes, uid, 8); + clearCommandBuffer(); + SendCommand(&c); + return 0; } // finds the AFI (Application Family Idendifier) of a card, by trying all values // (There is no standard way of reading the AFI, allthough some tags support this) // helptext int CmdHF15Afi(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_findafi(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_findafi(); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); + PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); - UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } typedef struct { - uint8_t lock; - uint8_t block[4]; + uint8_t lock; + uint8_t block[4]; } t15memory; // Reads all memory pages // need to write to file int CmdHF15Dump(const char*Cmd) { - uint8_t fileNameLen = 0; - char filename[FILE_PATH_SIZE] = {0}; - char * fptr = filename; - bool errors = false; - uint8_t cmdp = 0; - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + uint8_t fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0}; + char * fptr = filename; + bool errors = false; + uint8_t cmdp = 0; + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_15_dump(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_15_dump(); + case 'f': + fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors) return usage_15_dump(); + //Validations + if (errors) return usage_15_dump(); - if (fileNameLen < 1) { + if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); + PrintAndLogEx(INFO, "Using UID as filename"); - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found."); - return 1; - } + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found."); + return 1; + } - fptr += sprintf(fptr, "hf-15-"); - FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); - } - // detect blocksize from card :) + fptr += sprintf(fptr, "hf-15-"); + FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); + } + // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid)); + PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid)); - int blocknum = 0; - uint8_t *recv = NULL; + int blocknum = 0; + uint8_t *recv = NULL; - // memory. - t15memory mem[256]; + // memory. + t15memory mem[256]; - uint8_t data[256*4] = {0}; - memset(data, 0, sizeof(data)); + uint8_t data[256*4] = {0}; + memset(data, 0, sizeof(data)); - UsbCommand resp; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[1] = ISO15_CMD_READ; + UsbCommand resp; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[1] = ISO15_CMD_READ; - // copy uid to read command - memcpy(req+2, uid, sizeof(uid)); + // copy uid to read command + memcpy(req+2, uid, sizeof(uid)); - for (int retry = 0; retry < 5; retry++) { + for (int retry = 0; retry < 5; retry++) { - req[10] = blocknum; - AddCrc(req, 11); - c.arg[0] = 13; + req[10] = blocknum; + AddCrc(req, 11); + c.arg[0] = 13; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t len = resp.arg[0]; - if ( len < 2 ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - continue; - } + uint8_t len = resp.arg[0]; + if ( len < 2 ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + continue; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( !CheckCrc(recv, len) ) { - PrintAndLogEx(FAILED, "crc fail"); - continue; - } + if ( !CheckCrc(recv, len) ) { + PrintAndLogEx(FAILED, "crc fail"); + continue; + } - if (recv[0] & ISO15_RES_ERROR) { - PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); - break; - } + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); + break; + } - mem[blocknum].lock = resp.d.asBytes[0]; - memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); - memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); + mem[blocknum].lock = resp.d.asBytes[0]; + memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); + memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); - retry = 0; - blocknum++; + retry = 0; + blocknum++; - printf("."); fflush(stdout); - } - } - PrintAndLogEx(NORMAL, "\n"); + printf("."); fflush(stdout); + } + } + PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); - for (int i = 0; i < blocknum; i++) { - PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); - } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); + for (int i = 0; i < blocknum; i++) { + PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); + } + PrintAndLogEx(NORMAL, "\n"); - size_t datalen = blocknum * 4; - saveFileEML(filename, "eml", data, datalen, 4); - saveFile(filename, "bin", data, datalen); - return 0; + size_t datalen = blocknum * 4; + saveFileEML(filename, "eml", data, datalen, 4); + saveFile(filename, "bin", data, datalen); + return 0; } int CmdHF15Restore(const char*Cmd) { - FILE *f; + FILE *f; - uint8_t uid[8]={0x00}; - char filename[FILE_PATH_SIZE] = {0x00}; - char buff[255] = {0x00}; - size_t blocksize=4; - uint8_t cmdp = 0; - char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00}; - char param[FILE_PATH_SIZE]=""; - char hex[255]=""; - uint8_t retries = 3, tried = 0, i = 0; - int retval=0; - size_t bytes_read; + uint8_t uid[8]={0x00}; + char filename[FILE_PATH_SIZE] = {0x00}; + char buff[255] = {0x00}; + size_t blocksize=4; + uint8_t cmdp = 0; + char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00}; + char param[FILE_PATH_SIZE]=""; + char hex[255]=""; + uint8_t retries = 3, tried = 0, i = 0; + int retval=0; + size_t bytes_read; - while(param_getchar(Cmd, cmdp) != 0x00) { - switch(tolower(param_getchar(Cmd, cmdp))) { - case '-': - param_getstr(Cmd, cmdp, param, sizeof(param)); - switch(param[1]) - { - case '2': - case 'o': - strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1); - strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1); - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); - return usage_15_restore(); - } - break; - case 'f': - param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp++; - break; - case 'r': - retries=param_get8ex(Cmd, cmdp+1, 3, 10); - cmdp++; - break; - case 'b': - blocksize=param_get8ex(Cmd, cmdp+1, 4, 10); - cmdp++; - break; - case 'u': - param_getstr(Cmd, cmdp+1, buff, FILE_PATH_SIZE); - cmdp++; - snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff); - break; - case 'h': - return usage_15_restore(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - return usage_15_restore(); - } - cmdp++; - } + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(tolower(param_getchar(Cmd, cmdp))) { + case '-': + param_getstr(Cmd, cmdp, param, sizeof(param)); + switch(param[1]) + { + case '2': + case 'o': + strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1); + strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1); + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); + return usage_15_restore(); + } + break; + case 'f': + param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp++; + break; + case 'r': + retries=param_get8ex(Cmd, cmdp+1, 3, 10); + cmdp++; + break; + case 'b': + blocksize=param_get8ex(Cmd, cmdp+1, 4, 10); + cmdp++; + break; + case 'u': + param_getstr(Cmd, cmdp+1, buff, FILE_PATH_SIZE); + cmdp++; + snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff); + break; + case 'h': + return usage_15_restore(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + return usage_15_restore(); + } + cmdp++; + } - PrintAndLogEx(INFO,"Blocksize: %u",blocksize); + PrintAndLogEx(INFO,"Blocksize: %u",blocksize); - if ( !strlen(filename)) { - PrintAndLogEx(WARNING,"Please provide a filename"); - return usage_15_restore(); - } + if ( !strlen(filename)) { + PrintAndLogEx(WARNING,"Please provide a filename"); + return usage_15_restore(); + } - if ((f = fopen(filename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file %s", filename); - return 2; - } + if ((f = fopen(filename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file %s", filename); + return 2; + } - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found"); - fclose(f); - return 3; - } + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found"); + fclose(f); + return 3; + } - while (1) { - tried = 0; - hex[0] = 0x00; - tmpCmd[0] = 0x00; + while (1) { + tried = 0; + hex[0] = 0x00; + tmpCmd[0] = 0x00; - bytes_read = fread( buff, 1, blocksize, f ); - if ( bytes_read == 0) { - PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); - fclose(f); - return 0; - } else if ( bytes_read != blocksize) { - PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize); - fclose(f); - return 2; - } + bytes_read = fread( buff, 1, blocksize, f ); + if ( bytes_read == 0) { + PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); + fclose(f); + return 0; + } else if ( bytes_read != blocksize) { + PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize); + fclose(f); + return 2; + } - for(int j=0; j < blocksize; j++) - snprintf(hex+j*2, 3, "%02X", buff[j]); + for(int j=0; j < blocksize; j++) + snprintf(hex+j*2, 3, "%02X", buff[j]); - for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++) - snprintf(buff+j*2,3,"%02X", uid[j]); + for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++) + snprintf(buff+j*2,3,"%02X", uid[j]); - //TODO: Addressed mode currently not work - //snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex); - snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex); - PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd); + //TODO: Addressed mode currently not work + //snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex); + snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex); + PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd); - for(tried=0; tried < retries; tried++) - if(!(retval = CmdHF15Write(tmpCmd))) - break; - if(tried >= retries) - return retval; + for(tried=0; tried < retries; tried++) + if(!(retval = CmdHF15Write(tmpCmd))) + break; + if(tried >= retries) + return retval; - i++; - } - fclose(f); + i++; + } + fclose(f); } int CmdHF15List(const char *Cmd) { - //PrintAndLogEx(WARNING, "Deprecated command, use 'hf list 15' instead"); - CmdTraceList("15"); - return 0; + //PrintAndLogEx(WARNING, "Deprecated command, use 'hf list 15' instead"); + CmdTraceList("15"); + return 0; } int CmdHF15Raw(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw(); - UsbCommand resp; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - int reply = 1, fast = 1, i = 0; - bool crc = false; - char buf[5] = ""; - uint8_t data[100]; - uint32_t datalen = 0, temp; + UsbCommand resp; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + int reply = 1, fast = 1, i = 0; + bool crc = false; + char buf[5] = ""; + uint8_t data[100]; + uint32_t datalen = 0, temp; - // strip - while (*Cmd==' ' || *Cmd=='\t') Cmd++; + // strip + while (*Cmd==' ' || *Cmd=='\t') Cmd++; - while (Cmd[i]!='\0') { - if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; } - if (Cmd[i]=='-') { - switch (Cmd[i+1]) { - case 'r': - case 'R': - reply = 0; - break; - case '2': - fast = 0; - break; - case 'c': - case 'C': - crc = true; - break; - default: - PrintAndLogEx(WARNING, "Invalid option"); - return 0; - } - i+=2; - continue; - } - if ((Cmd[i]>='0' && Cmd[i]<='9') || - (Cmd[i]>='a' && Cmd[i]<='f') || - (Cmd[i]>='A' && Cmd[i]<='F') ) { - buf[strlen(buf)+1] = 0; - buf[strlen(buf)] = Cmd[i]; - i++; + while (Cmd[i]!='\0') { + if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; } + if (Cmd[i]=='-') { + switch (Cmd[i+1]) { + case 'r': + case 'R': + reply = 0; + break; + case '2': + fast = 0; + break; + case 'c': + case 'C': + crc = true; + break; + default: + PrintAndLogEx(WARNING, "Invalid option"); + return 0; + } + i+=2; + continue; + } + if ((Cmd[i]>='0' && Cmd[i]<='9') || + (Cmd[i]>='a' && Cmd[i]<='f') || + (Cmd[i]>='A' && Cmd[i]<='F') ) { + buf[strlen(buf)+1] = 0; + buf[strlen(buf)] = Cmd[i]; + i++; - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - datalen++; - *buf = 0; - } - continue; - } - PrintAndLogEx(WARNING, "Invalid char on input"); - return 0; - } + if (strlen(buf) >= 2) { + sscanf(buf, "%x", &temp); + data[datalen] = (uint8_t)(temp & 0xff); + datalen++; + *buf = 0; + } + continue; + } + PrintAndLogEx(WARNING, "Invalid char on input"); + return 0; + } - if (crc) { - AddCrc(data, datalen); - datalen += 2; - } + if (crc) { + AddCrc(data, datalen); + datalen += 2; + } - c.arg[0] = datalen; - c.arg[1] = fast; - c.arg[2] = reply; - memcpy(c.d.asBytes, data, datalen); + c.arg[0] = datalen; + c.arg[1] = fast; + c.arg[2] = reply; + memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (reply) { - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t len = resp.arg[0]; - PrintAndLogEx(NORMAL, "received %i octets", len); - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); - } else { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - } - } - return 0; + if (reply) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + uint8_t len = resp.arg[0]; + PrintAndLogEx(NORMAL, "received %i octets", len); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); + } else { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + } + } + return 0; } /** * parses common HF 15 CMD parameters and prepares some data structures * Parameters: - * **cmd command line + * **cmd command line */ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { - int temp; - uint8_t *req = c->d.asBytes; - uint8_t uid[8] = {0x00}; - uint32_t reqlen = 0; + int temp; + uint8_t *req = c->d.asBytes; + uint8_t uid[8] = {0x00}; + uint32_t reqlen = 0; - // strip - while (**cmd==' ' || **cmd=='\t') (*cmd)++; + // strip + while (**cmd==' ' || **cmd=='\t') (*cmd)++; - if (strstr(*cmd, "-2") == *cmd) { - c->arg[1] = 0; // use 1of256 - (*cmd) += 2; - } + if (strstr(*cmd, "-2") == *cmd) { + c->arg[1] = 0; // use 1of256 + (*cmd) += 2; + } - // strip - while (**cmd==' ' || **cmd=='\t') (*cmd)++; + // strip + while (**cmd==' ' || **cmd=='\t') (*cmd)++; - if (strstr(*cmd, "-o") == *cmd) { - req[reqlen] = ISO15_REQ_OPTION; - (*cmd) += 2; - } + if (strstr(*cmd, "-o") == *cmd) { + req[reqlen] = ISO15_REQ_OPTION; + (*cmd) += 2; + } - // strip - while (**cmd == ' ' || **cmd == '\t') (*cmd)++; + // strip + while (**cmd == ' ' || **cmd == '\t') (*cmd)++; - switch (**cmd) { - case 0: - PrintAndLogEx(WARNING, "missing addr"); - return 0; - break; - case 'u': - case 'U': - // unaddressed mode may not be supported by all vendors - req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; - req[reqlen++] = iso15cmd; - break; - case '*': - // we scan for the UID ourself - req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[reqlen++] = iso15cmd; + switch (**cmd) { + case 0: + PrintAndLogEx(WARNING, "missing addr"); + return 0; + break; + case 'u': + case 'U': + // unaddressed mode may not be supported by all vendors + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; + req[reqlen++] = iso15cmd; + break; + case '*': + // we scan for the UID ourself + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = iso15cmd; - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found"); - return 0; - } - memcpy(&req[reqlen], uid, sizeof(uid)); - PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); - reqlen += sizeof(uid); - break; - default: - req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[reqlen++] = iso15cmd; + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found"); + return 0; + } + memcpy(&req[reqlen], uid, sizeof(uid)); + PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); + reqlen += sizeof(uid); + break; + default: + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = iso15cmd; - // parse UID - for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) { - sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp); - uid[7-i] = temp & 0xff; - } + // parse UID + for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) { + sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp); + uid[7-i] = temp & 0xff; + } - PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); - memcpy(&req[reqlen], uid, sizeof(uid)); - reqlen += sizeof(uid); - break; - } - // skip to next space - while (**cmd!=' ' && **cmd!='\t') (*cmd)++; - // skip over the space - while (**cmd==' ' || **cmd=='\t') (*cmd)++; + PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); + memcpy(&req[reqlen], uid, sizeof(uid)); + reqlen += sizeof(uid); + break; + } + // skip to next space + while (**cmd!=' ' && **cmd!='\t') (*cmd)++; + // skip over the space + while (**cmd==' ' || **cmd=='\t') (*cmd)++; - c->arg[0] = reqlen; - return 1; + c->arg[0] = reqlen; + return 1; } /** @@ -1047,81 +1047,81 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { */ int CmdHF15Readmulti(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_readmulti(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_readmulti(); - UsbCommand resp; - uint8_t *recv; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - int reqlen = 0; - uint8_t pagenum, pagecount; - char cmdbuf[100]; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, 99); + UsbCommand resp; + uint8_t *recv; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + int reqlen = 0; + uint8_t pagenum, pagecount; + char cmdbuf[100]; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READMULTI) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READMULTI) ) + return 0; - // add OPTION flag, in order to get lock-info - req[0] |= ISO15_REQ_OPTION; + // add OPTION flag, in order to get lock-info + req[0] |= ISO15_REQ_OPTION; - reqlen = c.arg[0]; + reqlen = c.arg[0]; - // decimal - pagenum = param_get8ex(cmd, 0, 0, 10); - pagecount = param_get8ex(cmd, 1, 0, 10); + // decimal + pagenum = param_get8ex(cmd, 0, 0, 10); + pagecount = param_get8ex(cmd, 1, 0, 10); - //PrintAndLogEx(NORMAL, "ice %d %d\n", pagenum, pagecount); + //PrintAndLogEx(NORMAL, "ice %d %d\n", pagenum, pagecount); - // 0 means 1 page, - // 1 means 2 pages, ... - if (pagecount > 0) pagecount--; + // 0 means 1 page, + // 1 means 2 pages, ... + if (pagecount > 0) pagecount--; - req[reqlen++] = pagenum; - req[reqlen++] = pagecount; - AddCrc(req, reqlen); - c.arg[0] = reqlen+2; + req[reqlen++] = pagenum; + req[reqlen++] = pagecount; + AddCrc(req, reqlen); + c.arg[0] = reqlen+2; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + return 1; + } - uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; - } + uint32_t status = resp.arg[0]; + if ( status < 2 ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if (!CheckCrc(recv, status)) { - PrintAndLogEx(FAILED, "CRC failed"); - return 2; - } + if (!CheckCrc(recv, status)) { + PrintAndLogEx(FAILED, "CRC failed"); + return 2; + } - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - int start = 1; // skip status byte - int stop = (pagecount+1) * 5; - int currblock = pagenum; - // print response - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); - for (int i = start; i < stop; i += 5) { - PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv+i+1, 4 ), recv[i], sprint_ascii(recv+i+1, 4) ); - currblock++; - } + int start = 1; // skip status byte + int stop = (pagecount+1) * 5; + int currblock = pagenum; + // print response + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); + for (int i = start; i < stop; i += 5) { + PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv+i+1, 4 ), recv[i], sprint_ascii(recv+i+1, 4) ); + currblock++; + } - return 0; + return 0; } /** @@ -1130,72 +1130,72 @@ int CmdHF15Readmulti(const char *Cmd) { */ int CmdHF15Read(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_read(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_read(); - UsbCommand resp; - uint8_t *recv; + UsbCommand resp; + uint8_t *recv; - // UsbCommand arg: len, speed, recv? - // arg0 (datalen, cmd len? .arg0 == crc?) - // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) - // arg2 (recv == 1 == expect a response) - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; - uint8_t *req = c.d.asBytes; - int reqlen = 0, blocknum; - char cmdbuf[100]; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, 99); + // UsbCommand arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; + uint8_t *req = c.d.asBytes; + int reqlen = 0, blocknum; + char cmdbuf[100]; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ) ) + return 0; - // add OPTION flag, in order to get lock-info - req[0] |= ISO15_REQ_OPTION; + // add OPTION flag, in order to get lock-info + req[0] |= ISO15_REQ_OPTION; - reqlen = c.arg[0]; + reqlen = c.arg[0]; - blocknum = strtol(cmd, NULL, 0); + blocknum = strtol(cmd, NULL, 0); - req[reqlen++] = (uint8_t)blocknum; + req[reqlen++] = (uint8_t)blocknum; - AddCrc(req, reqlen); + AddCrc(req, reqlen); - c.arg[0] = reqlen+2; + c.arg[0] = reqlen+2; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } - uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; - } + uint32_t status = resp.arg[0]; + if ( status < 2 ) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( !CheckCrc(recv, status) ) { - PrintAndLogEx(NORMAL, "CRC failed"); - return 2; - } + if ( !CheckCrc(recv, status) ) { + PrintAndLogEx(NORMAL, "CRC failed"); + return 2; + } - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - // print response - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum ); - PrintAndLogEx(NORMAL, "------------+---+------" ); - PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv+2, status-4), recv[1], sprint_ascii(recv+2, status-4) ); - PrintAndLogEx(NORMAL, ""); - return 0; + // print response + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum ); + PrintAndLogEx(NORMAL, "------------+---+------" ); + PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv+2, status-4), recv[1], sprint_ascii(recv+2, status-4) ); + PrintAndLogEx(NORMAL, ""); + return 0; } /** @@ -1204,105 +1204,105 @@ int CmdHF15Read(const char *Cmd) { */ int CmdHF15Write(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_write(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_write(); - UsbCommand resp; - uint8_t *recv; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - int reqlen = 0, pagenum, temp; - char cmdbuf[100]; - char *cmd = cmdbuf; - char *cmd2; + UsbCommand resp; + uint8_t *recv; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + int reqlen = 0, pagenum, temp; + char cmdbuf[100]; + char *cmd = cmdbuf; + char *cmd2; - strncpy(cmd, Cmd, 99); + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE) ) + return 0; - reqlen = c.arg[0]; + reqlen = c.arg[0]; - // *cmd -> page num ; *cmd2 -> data - cmd2=cmd; - while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++; - *cmd2 = 0; - cmd2++; + // *cmd -> page num ; *cmd2 -> data + cmd2=cmd; + while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++; + *cmd2 = 0; + cmd2++; - pagenum = strtol(cmd, NULL, 0); + pagenum = strtol(cmd, NULL, 0); - req[reqlen++] = (uint8_t)pagenum; + req[reqlen++] = (uint8_t)pagenum; - while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars - if (*cmd2==' ') { - cmd2++; - continue; - } - sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp); - req[reqlen++]=temp & 0xff; - cmd2+=2; - } - AddCrc(req, reqlen); - c.arg[0] = reqlen+2; + while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars + if (*cmd2==' ') { + cmd2++; + continue; + } + sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp); + req[reqlen++]=temp & 0xff; + cmd2+=2; + } + AddCrc(req, reqlen); + c.arg[0] = reqlen+2; - PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); + PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); + return 1; + } - uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; - } + uint32_t status = resp.arg[0]; + if ( status < 2 ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( !CheckCrc(recv, status) ) { - PrintAndLogEx(FAILED, "CRC failed"); - return 2; - } + if ( !CheckCrc(recv, status) ) { + PrintAndLogEx(FAILED, "CRC failed"); + return 2; + } - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - PrintAndLogEx(NORMAL, "OK"); - return 0; + PrintAndLogEx(NORMAL, "OK"); + return 0; } static command_t CommandTable15[] = { - {"help", CmdHF15Help, 1, "This help"}, - {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"}, - {"dump", CmdHF15Dump, 0, "Read all memory pages of an ISO15693 tag, save to file"}, - {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, - {"info", CmdHF15Info, 0, "Tag information"}, - {"list", CmdHF15List, 0, "[Deprecated] List ISO15693 history"}, - {"raw", CmdHF15Raw, 0, "Send raw hex data to tag"}, - {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, - {"record", CmdHF15Record, 0, "Record Samples (ISO15693)"}, - {"restore", CmdHF15Restore, 0, "Restore from file to all memory pages of an ISO15693 tag"}, - {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, - {"samples", CmdHF15Samples, 0, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, - {"read", CmdHF15Read, 0, "Read a block"}, - {"write", CmdHF15Write, 0, "Write a block"}, - {"readmulti", CmdHF15Readmulti, 0, "Reads multiple Blocks"}, - {NULL, NULL, 0, NULL} + {"help", CmdHF15Help, 1, "This help"}, + {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"}, + {"dump", CmdHF15Dump, 0, "Read all memory pages of an ISO15693 tag, save to file"}, + {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, + {"info", CmdHF15Info, 0, "Tag information"}, + {"list", CmdHF15List, 0, "[Deprecated] List ISO15693 history"}, + {"raw", CmdHF15Raw, 0, "Send raw hex data to tag"}, + {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, + {"record", CmdHF15Record, 0, "Record Samples (ISO15693)"}, + {"restore", CmdHF15Restore, 0, "Restore from file to all memory pages of an ISO15693 tag"}, + {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, + {"samples", CmdHF15Samples, 0, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, + {"read", CmdHF15Read, 0, "Read a block"}, + {"write", CmdHF15Write, 0, "Write a block"}, + {"readmulti", CmdHF15Readmulti, 0, "Reads multiple Blocks"}, + {NULL, NULL, 0, NULL} }; int CmdHF15(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable15, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable15, Cmd); + return 0; } int CmdHF15Help(const char *Cmd) { - CmdsHelp(CommandTable15); - return 0; + CmdsHelp(CommandTable15); + return 0; } \ No newline at end of file diff --git a/client/cmdhf15.h b/client/cmdhf15.h index 2908a9aab..38f4b7801 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -21,10 +21,10 @@ #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "crc16.h" // iso15 crc +#include "crc16.h" // iso15 crc #include "cmdmain.h" -#include "cmddata.h" // getsamples -#include "loclass/fileutils.h" // savefileEML +#include "cmddata.h" // getsamples +#include "loclass/fileutils.h" // savefileEML int CmdHF15(const char *Cmd); diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 4e7510fe0..be8771b86 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -14,168 +14,168 @@ static int CmdHelp(const char *Cmd); // Perform (part of) the PACE protocol int CmdHFEPACollectPACENonces(const char *Cmd) { - // requested nonce size - uint32_t m = 0; - // requested number of Nonces - uint32_t n = 0; - // delay between requests - uint32_t d = 0; + // requested nonce size + uint32_t m = 0; + // requested number of Nonces + uint32_t n = 0; + // delay between requests + uint32_t d = 0; - sscanf(Cmd, "%u %u %u", &m, &n, &d); + sscanf(Cmd, "%u %u %u", &m, &n, &d); - // values are expected to be > 0 - m = m > 0 ? m : 1; - n = n > 0 ? n : 1; + // values are expected to be > 0 + m = m > 0 ? m : 1; + n = n > 0 ? n : 1; - PrintAndLogEx(NORMAL, "Collecting %u %u byte nonces", n, m); - PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock()/1000); - // repeat n times - for (uint32_t i = 0; i < n; i++) { - // execute PACE - UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + PrintAndLogEx(NORMAL, "Collecting %u %u byte nonces", n, m); + PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock()/1000); + // repeat n times + for (uint32_t i = 0; i < n; i++) { + // execute PACE + UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); - // check if command failed - if (resp.arg[0] != 0) { - PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]); - } else { - size_t nonce_length = resp.arg[1]; - char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t)); - for(int j = 0; j < nonce_length; j++) { - sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]); - } - // print nonce - PrintAndLogEx(NORMAL, "Length: %d, Nonce: %s", nonce_length, nonce); - free(nonce); - } - if (i < n - 1) { - sleep(d); - } - } - PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock()/1000); - return 1; + // check if command failed + if (resp.arg[0] != 0) { + PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]); + } else { + size_t nonce_length = resp.arg[1]; + char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t)); + for(int j = 0; j < nonce_length; j++) { + sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]); + } + // print nonce + PrintAndLogEx(NORMAL, "Length: %d, Nonce: %s", nonce_length, nonce); + free(nonce); + } + if (i < n - 1) { + sleep(d); + } + } + PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock()/1000); + return 1; } // perform the PACE protocol by replaying APDUs int CmdHFEPAPACEReplay(const char *Cmd) { - // the 4 APDUs which are replayed + their lengths - uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75]; - uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0}; - // pointers to the arrays to be able to iterate - uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; + // the 4 APDUs which are replayed + their lengths + uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75]; + uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0}; + // pointers to the arrays to be able to iterate + uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; - // usage message - static const char *usage_msg = - "Please specify 5 APDUs separated by spaces. " - "Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D"; + // usage message + static const char *usage_msg = + "Please specify 5 APDUs separated by spaces. " + "Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D"; - // Proxmark response - UsbCommand resp; + // Proxmark response + UsbCommand resp; - int skip = 0, skip_add = 0, scan_return = 0; - // for each APDU - for (int i = 0; i < sizeof(apdu_lengths); i++) { - // scan to next space or end of string - while (Cmd[skip] != ' ' && Cmd[skip] != '\0') { - // convert - scan_return = sscanf(Cmd + skip, "%2X%n", - (unsigned int *) (apdus[i] + apdu_lengths[i]), - &skip_add); - if (scan_return < 1) { - PrintAndLogEx(NORMAL, (char *)usage_msg); - PrintAndLogEx(WARNING, "Not enough APDUs! Try again!"); - return 0; - } - skip += skip_add; + int skip = 0, skip_add = 0, scan_return = 0; + // for each APDU + for (int i = 0; i < sizeof(apdu_lengths); i++) { + // scan to next space or end of string + while (Cmd[skip] != ' ' && Cmd[skip] != '\0') { + // convert + scan_return = sscanf(Cmd + skip, "%2X%n", + (unsigned int *) (apdus[i] + apdu_lengths[i]), + &skip_add); + if (scan_return < 1) { + PrintAndLogEx(NORMAL, (char *)usage_msg); + PrintAndLogEx(WARNING, "Not enough APDUs! Try again!"); + return 0; + } + skip += skip_add; apdu_lengths[i]++; - } + } - // break on EOF - if (Cmd[skip] == '\0') { - if (i < sizeof(apdu_lengths) - 1) { + // break on EOF + if (Cmd[skip] == '\0') { + if (i < sizeof(apdu_lengths) - 1) { - PrintAndLogEx(NORMAL, (char *)usage_msg); - return 0; - } - break; - } - // skip the space - skip++; - } + PrintAndLogEx(NORMAL, (char *)usage_msg); + return 0; + } + break; + } + // skip the space + skip++; + } - // transfer the APDUs to the Proxmark - UsbCommand usb_cmd; - usb_cmd.cmd = CMD_EPA_PACE_REPLAY; - for (int i = 0; i < sizeof(apdu_lengths); i++) { - // APDU number - usb_cmd.arg[0] = i + 1; - // transfer the APDU in several parts if necessary - for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) { - // offset into the APDU - usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes); - // amount of data in this packet - int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes)); - if (packet_length > sizeof(usb_cmd.d.asBytes)) { - packet_length = sizeof(usb_cmd.d.asBytes); - } - usb_cmd.arg[2] = packet_length; + // transfer the APDUs to the Proxmark + UsbCommand usb_cmd; + usb_cmd.cmd = CMD_EPA_PACE_REPLAY; + for (int i = 0; i < sizeof(apdu_lengths); i++) { + // APDU number + usb_cmd.arg[0] = i + 1; + // transfer the APDU in several parts if necessary + for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) { + // offset into the APDU + usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes); + // amount of data in this packet + int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes)); + if (packet_length > sizeof(usb_cmd.d.asBytes)) { + packet_length = sizeof(usb_cmd.d.asBytes); + } + usb_cmd.arg[2] = packet_length; - memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)), - apdus[i] + (j * sizeof(usb_cmd.d.asBytes)), - packet_length); + memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)), + apdus[i] + (j * sizeof(usb_cmd.d.asBytes)), + packet_length); - clearCommandBuffer(); - SendCommand(&usb_cmd); - WaitForResponse(CMD_ACK, &resp); - if (resp.arg[0] != 0) { - PrintAndLogEx(WARNING, "Transfer of APDU #%d Part %d failed!", i, j); - return 0; - } - } - } + clearCommandBuffer(); + SendCommand(&usb_cmd); + WaitForResponse(CMD_ACK, &resp); + if (resp.arg[0] != 0) { + PrintAndLogEx(WARNING, "Transfer of APDU #%d Part %d failed!", i, j); + return 0; + } + } + } - // now perform the replay - usb_cmd.arg[0] = 0; - clearCommandBuffer(); - SendCommand(&usb_cmd); - WaitForResponse(CMD_ACK, &resp); - if (resp.arg[0] != 0) { - PrintAndLogEx(NORMAL, "\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]); - PrintAndLogEx(NORMAL, "Measured times:"); - PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); - PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); - PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); - PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); - PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); - } else { - PrintAndLogEx(NORMAL, "PACE replay successfull!"); - PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); - PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); - PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); - PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); - PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); - } - return 1; + // now perform the replay + usb_cmd.arg[0] = 0; + clearCommandBuffer(); + SendCommand(&usb_cmd); + WaitForResponse(CMD_ACK, &resp); + if (resp.arg[0] != 0) { + PrintAndLogEx(NORMAL, "\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]); + PrintAndLogEx(NORMAL, "Measured times:"); + PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); + PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); + PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); + PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); + PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); + } else { + PrintAndLogEx(NORMAL, "PACE replay successfull!"); + PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); + PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); + PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); + PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); + PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); + } + return 1; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"cnonces", CmdHFEPACollectPACENonces, 0, " Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, - {"preplay", CmdHFEPAPACEReplay, 0, " Perform PACE protocol by replaying given APDUs"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"cnonces", CmdHFEPACollectPACENonces, 0, " Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, + {"preplay", CmdHFEPAPACEReplay, 0, " Perform PACE protocol by replaying given APDUs"}, + {NULL, NULL, 0, NULL} }; int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } int CmdHFEPA(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } \ No newline at end of file diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 7a00c2490..615f51049 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -12,406 +12,406 @@ static int CmdHelp(const char *Cmd); int usage_hf_felica_sim(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " t : 1 = FeliCa"); - PrintAndLogEx(NORMAL, " : 2 = FeliCaLiteS"); - PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica sim t 1 "); - return 0; + PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); + PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t [v]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " t : 1 = FeliCa"); + PrintAndLogEx(NORMAL, " : 2 = FeliCaLiteS"); + PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica sim t 1 "); + return 0; } int usage_hf_felica_sniff(void){ - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'"); - PrintAndLogEx(NORMAL, "Usage: hf felica sniff "); - PrintAndLogEx(NORMAL, " s samples to skip (decimal)"); - PrintAndLogEx(NORMAL, " t triggers to skip (decimal)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica sniff s 1000"); - return 0; + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); + PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'"); + PrintAndLogEx(NORMAL, "Usage: hf felica sniff "); + PrintAndLogEx(NORMAL, " s samples to skip (decimal)"); + PrintAndLogEx(NORMAL, " t triggers to skip (decimal)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica sniff s 1000"); + return 0; } int usage_hf_felica_simlite(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " uid : UID in hexsymbol"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677"); - return 0; + PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n"); + PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " uid : UID in hexsymbol"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677"); + return 0; } int usage_hf_felica_dumplite(void) { - PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec."); - PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litedump"); - return 0; + PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n"); + PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec."); + PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica litedump"); + return 0; } int usage_hf_felica_raw(void){ - PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); - PrintAndLogEx(NORMAL, " -a active signal field ON without select"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -r do not read response"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); + PrintAndLogEx(NORMAL, " -a active signal field ON without select"); + PrintAndLogEx(NORMAL, " -s active signal field ON with select"); + return 0; } int CmdHFFelicaList(const char *Cmd) { - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead"); - CmdTraceList("felica"); - return 0; + //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead"); + CmdTraceList("felica"); + return 0; } int CmdHFFelicaReader(const char *Cmd) { - bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); - //UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}}; - UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "FeliCa card select failed"); - //SendCommand(&cDisconnect); - return 0; - } + bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); + //UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}}; + UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "FeliCa card select failed"); + //SendCommand(&cDisconnect); + return 0; + } - felica_card_select_t card; - memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t)); - uint64_t status = resp.arg[0]; + felica_card_select_t card; + memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t)); + uint64_t status = resp.arg[0]; - switch(status) { - case 1: { - if (!silent) - PrintAndLogEx(WARNING, "card timeout"); - break; - } - case 2: { - if (!silent) - PrintAndLogEx(WARNING, "card answered wrong"); - break; - } - case 3: { - if (!silent) - PrintAndLogEx(WARNING, "CRC check failed"); - break; - } - case 0: { - PrintAndLogEx(SUCCESS, "FeliCa tag info"); + switch(status) { + case 1: { + if (!silent) + PrintAndLogEx(WARNING, "card timeout"); + break; + } + case 2: { + if (!silent) + PrintAndLogEx(WARNING, "card answered wrong"); + break; + } + case 3: { + if (!silent) + PrintAndLogEx(WARNING, "CRC check failed"); + break; + } + case 0: { + PrintAndLogEx(SUCCESS, "FeliCa tag info"); - PrintAndLogEx(NORMAL, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); - PrintAndLogEx(NORMAL, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); - PrintAndLogEx(NORMAL, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); + PrintAndLogEx(NORMAL, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); + PrintAndLogEx(NORMAL, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); + PrintAndLogEx(NORMAL, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); - PrintAndLogEx(NORMAL, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); - PrintAndLogEx(NORMAL, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); - PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); + PrintAndLogEx(NORMAL, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); + PrintAndLogEx(NORMAL, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); + PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); - PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); - break; - } - } - return status; + PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); + break; + } + } + return status; } // simulate iso18092 / FeliCa tag int CmdHFFelicaSim(const char *Cmd) { - bool errors = false; - uint8_t flags = 0; - uint8_t tagtype = 1; - uint8_t cmdp = 0; - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - int uidlen = 0; - bool verbose = false; + bool errors = false; + uint8_t flags = 0; + uint8_t tagtype = 1; + uint8_t cmdp = 0; + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + int uidlen = 0; + bool verbose = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_felica_sim(); - case 't': - case 'T': - // Retrieve the tag type - tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); - if (tagtype == 0) - errors = true; - cmdp += 2; - break; - case 'u': - case 'U': - // Retrieve the full 4,7,10 byte long uid - param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); - if (!errors) { - PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); - } - cmdp += 2; - break; - case 'v': - case 'V': - verbose = true; - cmdp++; - break; - case 'e': - case 'E': - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_felica_sim(); + case 't': + case 'T': + // Retrieve the tag type + tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); + if (tagtype == 0) + errors = true; + cmdp += 2; + break; + case 'u': + case 'U': + // Retrieve the full 4,7,10 byte long uid + param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); + if (!errors) { + PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); + } + cmdp += 2; + break; + case 'v': + case 'V': + verbose = true; + cmdp++; + break; + case 'e': + case 'E': + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0) return usage_hf_felica_sim(); + //Validations + if (errors || cmdp == 0) return usage_hf_felica_sim(); - UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }}; - memcpy(c.d.asBytes, uid, uidlen>>1); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }}; + memcpy(c.d.asBytes, uid, uidlen>>1); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if ( verbose ) - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); + if ( verbose ) + PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); - while( !ukbhit() ){ - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - } - return 0; + while( !ukbhit() ){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; + } + return 0; } int CmdHFFelicaSniff(const char *Cmd) { - uint8_t cmdp = 0; - uint64_t samples2skip = 0; - uint64_t triggers2skip = 0; - bool errors = false; + uint8_t cmdp = 0; + uint64_t samples2skip = 0; + uint64_t triggers2skip = 0; + bool errors = false; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_felica_sniff(); - case 's': - case 'S': - samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 't': - case 'T': - triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0) return usage_hf_felica_sniff(); + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_felica_sniff(); + case 's': + case 'S': + samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 't': + case 'T': + triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0) return usage_hf_felica_sniff(); - UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } // uid hex int CmdHFFelicaSimLite(const char *Cmd) { - uint64_t uid = param_get64ex(Cmd, 0, 0, 16); + uint64_t uid = param_get64ex(Cmd, 0, 0, 16); if (!uid) - return usage_hf_felica_simlite(); + return usage_hf_felica_simlite(); - UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} }; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} }; + clearCommandBuffer(); + SendCommand(&c); + return 0; } static void printSep() { - PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); + PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); } uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { - if (tracepos+19 >= tracelen) - return tracelen; + if (tracepos+19 >= tracelen) + return tracelen; - trace += tracepos; - uint8_t blocknum = trace[0]; - uint8_t status1 = trace[1]; - uint8_t status2 = trace[2]; + trace += tracepos; + uint8_t blocknum = trace[0]; + uint8_t status1 = trace[1]; + uint8_t status2 = trace[2]; - char line[110] = {0}; - for (int j = 0; j < 16; j++) { - snprintf(line + (j * 4), sizeof(line) - 1 - (j*4) , "%02x ", trace[j+3]); - } + char line[110] = {0}; + for (int j = 0; j < 16; j++) { + snprintf(line + (j * 4), sizeof(line) - 1 - (j*4) , "%02x ", trace[j+3]); + } - PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x",blocknum,status1, status2); - switch (blocknum) { - case 0x00: PrintAndLogEx(NORMAL, "S_PAD0: %s",line);break; - case 0x01: PrintAndLogEx(NORMAL, "S_PAD1: %s",line);break; - case 0x02: PrintAndLogEx(NORMAL, "S_PAD2: %s",line);break; - case 0x03: PrintAndLogEx(NORMAL, "S_PAD3: %s",line);break; - case 0x04: PrintAndLogEx(NORMAL, "S_PAD4: %s",line);break; - case 0x05: PrintAndLogEx(NORMAL, "S_PAD5: %s",line);break; - case 0x06: PrintAndLogEx(NORMAL, "S_PAD6: %s",line);break; - case 0x07: PrintAndLogEx(NORMAL, "S_PAD7: %s",line);break; - case 0x08: PrintAndLogEx(NORMAL, "S_PAD8: %s",line);break; - case 0x09: PrintAndLogEx(NORMAL, "S_PAD9: %s",line);break; - case 0x0a: PrintAndLogEx(NORMAL, "S_PAD10: %s",line);break; - case 0x0b: PrintAndLogEx(NORMAL, "S_PAD11: %s",line);break; - case 0x0c: PrintAndLogEx(NORMAL, "S_PAD12: %s",line);break; - case 0x0d: PrintAndLogEx(NORMAL, "S_PAD13: %s",line);break; - case 0x0E: { - uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; - uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; - line[0] = 0; - for (int j = 0; j < 8; j++) - snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); + PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x",blocknum,status1, status2); + switch (blocknum) { + case 0x00: PrintAndLogEx(NORMAL, "S_PAD0: %s",line);break; + case 0x01: PrintAndLogEx(NORMAL, "S_PAD1: %s",line);break; + case 0x02: PrintAndLogEx(NORMAL, "S_PAD2: %s",line);break; + case 0x03: PrintAndLogEx(NORMAL, "S_PAD3: %s",line);break; + case 0x04: PrintAndLogEx(NORMAL, "S_PAD4: %s",line);break; + case 0x05: PrintAndLogEx(NORMAL, "S_PAD5: %s",line);break; + case 0x06: PrintAndLogEx(NORMAL, "S_PAD6: %s",line);break; + case 0x07: PrintAndLogEx(NORMAL, "S_PAD7: %s",line);break; + case 0x08: PrintAndLogEx(NORMAL, "S_PAD8: %s",line);break; + case 0x09: PrintAndLogEx(NORMAL, "S_PAD9: %s",line);break; + case 0x0a: PrintAndLogEx(NORMAL, "S_PAD10: %s",line);break; + case 0x0b: PrintAndLogEx(NORMAL, "S_PAD11: %s",line);break; + case 0x0c: PrintAndLogEx(NORMAL, "S_PAD12: %s",line);break; + case 0x0d: PrintAndLogEx(NORMAL, "S_PAD13: %s",line);break; + case 0x0E: { + uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; + uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; + line[0] = 0; + for (int j = 0; j < 8; j++) + snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); - PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); - } - break; - case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break; - case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break; - case 0x82: { - char idd[20]; - char idm[20]; - for (int j = 0; j < 8; j++) - snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]); + PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); + } + break; + case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break; + case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break; + case 0x82: { + char idd[20]; + char idm[20]; + for (int j = 0; j < 8; j++) + snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]); - for (int j = 0; j < 6; j++) - snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]); + for (int j = 0; j < 6; j++) + snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]); - PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); - } - break; - case 0x83: { - char idm[20]; - char pmm[20]; - for (int j = 0; j < 8; j++) - snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]); + PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); + } + break; + case 0x83: { + char idm[20]; + char pmm[20]; + for (int j = 0; j < 8; j++) + snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]); - for (int j = 0; j < 8; j++) - snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]); + for (int j = 0; j < 8; j++) + snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]); - PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); - } - break; - case 0x84: PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]); break; - case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; - case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; - case 0x87: PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line); break; - case 0x88: { - PrintAndLogEx(NORMAL, "Memory Configuration (MC):"); - PrintAndLogEx(NORMAL, "MAC needed to write state: %s", trace[3+12]? "on" : "off"); - //order might be off here... - PrintAndLogEx(NORMAL, "Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) ); - PrintAndLogEx(NORMAL, "Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) ); - PrintAndLogEx(NORMAL, "Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) ); - PrintAndLogEx(NORMAL, "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off"); - PrintAndLogEx(NORMAL, "RF parameter: %02x", (trace[3+4] & 0x7) ); - PrintAndLogEx(NORMAL, "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no"); - PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no"); - PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace+3, 2) ); - } - break; - case 0x90: { + PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); + } + break; + case 0x84: PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]); break; + case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; + case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; + case 0x87: PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line); break; + case 0x88: { + PrintAndLogEx(NORMAL, "Memory Configuration (MC):"); + PrintAndLogEx(NORMAL, "MAC needed to write state: %s", trace[3+12]? "on" : "off"); + //order might be off here... + PrintAndLogEx(NORMAL, "Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) ); + PrintAndLogEx(NORMAL, "Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) ); + PrintAndLogEx(NORMAL, "Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) ); + PrintAndLogEx(NORMAL, "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off"); + PrintAndLogEx(NORMAL, "RF parameter: %02x", (trace[3+4] & 0x7) ); + PrintAndLogEx(NORMAL, "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no"); + PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no"); + PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace+3, 2) ); + } + break; + case 0x90: { PrintAndLogEx(NORMAL, "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]); - } - break; - case 0x91: { + } + break; + case 0x91: { PrintAndLogEx(NORMAL, "MAC_A, RW (auth): %s ", line); } - break; - case 0x92: + break; + case 0x92: PrintAndLogEx(NORMAL, "State:"); PrintAndLogEx(NORMAL, "Polling disabled: %s", trace[3+8] ? "yes" : "no"); PrintAndLogEx(NORMAL, "Authenticated: %s", trace[3] ? "yes" : "no"); - break; - case 0xa0: + break; + case 0xa0: PrintAndLogEx(NORMAL, "CRC of all bloacks match : %s", (trace[3+2]==0xff) ? "no" : "yes"); - break; - default: - PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line); - break; - } - return tracepos+19; + break; + default: + PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line); + break; + } + return tracepos+19; } int CmdHFFelicaDumpLite(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if ( ctmp == 'h') return usage_hf_felica_dumplite(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h') return usage_hf_felica_dumplite(); - PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); - UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); + PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); + UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - uint8_t timeout = 0; - while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - timeout++; - printf("."); fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); - DropField(); - return 1; - } - if (timeout > 100) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - DropField(); - return 1; - } - } - if (resp.arg[0] == 0) { - PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); - return 1; - } + uint8_t timeout = 0; + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + timeout++; + printf("."); fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); + DropField(); + return 1; + } + if (timeout > 100) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + DropField(); + return 1; + } + } + if (resp.arg[0] == 0) { + PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); + return 1; + } - uint64_t tracelen = resp.arg[1]; - uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); - if ( trace == NULL ) { - PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); - return 1; - } + uint64_t tracelen = resp.arg[1]; + uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); + if ( trace == NULL ) { + PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); + return 1; + } - // only download data if there is any. - if ( tracelen > 0 ) { + // only download data if there is any. + if ( tracelen > 0 ) { - if ( !GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false) ){ - PrintAndLogEx(WARNING, "command execution time out"); - free(trace); - return 0; - } + if ( !GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false) ){ + PrintAndLogEx(WARNING, "command execution time out"); + free(trace); + return 0; + } - PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen); + PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen); - print_hex_break(trace, tracelen, 32); + print_hex_break(trace, tracelen, 32); - printSep(); - uint16_t tracepos = 0; - while (tracepos < tracelen) - tracepos = PrintFliteBlock(tracepos, trace, tracelen); + printSep(); + uint16_t tracepos = 0; + while (tracepos < tracelen) + tracepos = PrintFliteBlock(tracepos, trace, tracelen); - printSep(); - } + printSep(); + } free(trace); - return 0; + return 0; } int CmdHFFelicaCmdRaw(const char *cmd) { @@ -425,8 +425,8 @@ int CmdHFFelicaCmdRaw(const char *cmd) { char buf[5]=""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE]; - uint16_t datalen = 0; - uint32_t temp; + uint16_t datalen = 0; + uint32_t temp; if (strlen(cmd) < 2) return usage_hf_felica_raw(); @@ -437,9 +437,9 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; } if (cmd[i]=='-') { switch (cmd[i+1]) { - case 'H': - case 'h': - return usage_hf_felica_raw(); + case 'H': + case 'h': + return usage_hf_felica_raw(); case 'r': reply = false; break; @@ -479,11 +479,11 @@ int CmdHFFelicaCmdRaw(const char *cmd) { sscanf(buf,"%x",&temp); data[datalen]=(uint8_t)(temp & 0xff); *buf=0; - if (++datalen >= sizeof(data)){ - if (crc) - PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); - break; - } + if (++datalen >= sizeof(data)){ + if (crc) + PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); + break; + } } continue; } @@ -493,7 +493,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (crc && datalen>0 && datalen < sizeof(data)-2) { uint8_t b1, b2; - compute_crc(CRC_FELICA, data, datalen, &b1, &b2); + compute_crc(CRC_FELICA, data, datalen, &b1, &b2); data[datalen++] = b1; data[datalen++] = b2; } @@ -506,19 +506,19 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (power) { c.arg[0] |= FELICA_NO_DISCONNECT; - } + } if (datalen > 0) { c.arg[0] |= FELICA_RAW; - } + } - // Max buffer is USB_CMD_DATA_SIZE - datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; + // Max buffer is USB_CMD_DATA_SIZE + datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; c.arg[1] = (datalen & 0xFFFF) | (uint32_t)(numbits << 16); memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); if (reply) { @@ -539,32 +539,32 @@ void waitCmdFelica(uint8_t iSelect) { PrintAndLogEx(NORMAL, "received %i octets", len); if(!len) return; - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"}, - {"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"}, - {"sim", CmdHFFelicaSim, 0, " -- Simulate ISO 18092/FeliCa tag"}, - {"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"}, - {"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"}, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"}, + {"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"}, + {"sim", CmdHFFelicaSim, 0, " -- Simulate ISO 18092/FeliCa tag"}, + {"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"}, + {"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"}, - {"litesim", CmdHFFelicaSimLite, 0, " - only reply to poll request"}, - {"litedump", CmdHFFelicaDumpLite, 0, "Wait for and try dumping FelicaLite"}, + {"litesim", CmdHFFelicaSimLite, 0, " - only reply to poll request"}, + {"litedump", CmdHFFelicaDumpLite, 0, "Wait for and try dumping FelicaLite"}, {NULL, NULL, 0, NULL} }; int CmdHFFelica(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } \ No newline at end of file diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index bcec38a0b..80a09f7d3 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -21,10 +21,10 @@ #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "comms.h" // getfromdevice +#include "comms.h" // getfromdevice #include "iso14443crc.h" -#include "cmdhf.h" // list cmd -#include "mifare.h" // felica_card_select_t struct +#include "cmdhf.h" // list cmd +#include "mifare.h" // felica_card_select_t struct extern int CmdHFFelica(const char *Cmd); extern int CmdHFFelicaList(const char *Cmd); diff --git a/client/cmdhffido.c b/client/cmdhffido.c index ea5d55c66..588c3b037 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -51,872 +51,872 @@ static int CmdHelp(const char *Cmd); int CmdHFFidoInfo(const char *cmd) { - if (cmd && strlen(cmd) > 0) - PrintAndLog("WARNING: command don't have any parameters.\n"); + if (cmd && strlen(cmd) > 0) + PrintAndLog("WARNING: command don't have any parameters.\n"); - // info about 14a part - CmdHF14AInfo(""); + // info about 14a part + CmdHF14AInfo(""); - // FIDO info - PrintAndLog("--------------------------------------------"); - SetAPDULogging(false); + // FIDO info + PrintAndLog("--------------------------------------------"); + SetAPDULogging(false); - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - DropField(); - return res; - } + if (res) { + DropField(); + return res; + } - if (sw != 0x9000) { - if (sw) - PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - else - PrintAndLog("APDU exchange error. Card returns 0x0000."); + if (sw != 0x9000) { + if (sw) + PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + else + PrintAndLog("APDU exchange error. Card returns 0x0000."); - DropField(); - return 0; - } + DropField(); + return 0; + } - if (!strncmp((char *)buf, "U2F_V2", 7)) { - if (!strncmp((char *)buf, "FIDO_2_0", 8)) { - PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); - } else { - PrintAndLog("FIDO authenricator detected (not standard U2F)."); - PrintAndLog("Non U2F authenticator version:"); - dump_buffer((const unsigned char *)buf, len, NULL, 0); - } - } else { - PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); - } + if (!strncmp((char *)buf, "U2F_V2", 7)) { + if (!strncmp((char *)buf, "FIDO_2_0", 8)) { + PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); + } else { + PrintAndLog("FIDO authenricator detected (not standard U2F)."); + PrintAndLog("Non U2F authenticator version:"); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + } + } else { + PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); + } - res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - return res; - } - if (sw != 0x9000) { - PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + return res; + } + if (sw != 0x9000) { + PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 0; - } + return 0; + } - if(buf[0]) { - PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); - return 0; - } + if(buf[0]) { + PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } - if (len > 1) { -// if (false) { -// PrintAndLog("FIDO2 version: (len=%d)", len); -// dump_buffer((const unsigned char *)buf, len, NULL, 0); -// } + if (len > 1) { +// if (false) { +// PrintAndLog("FIDO2 version: (len=%d)", len); +// dump_buffer((const unsigned char *)buf, len, NULL, 0); +// } - PrintAndLog("FIDO2 version CBOR decoded:"); - TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1); - } else { - PrintAndLog("FIDO2 version length error"); - } + PrintAndLog("FIDO2 version CBOR decoded:"); + TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1); + } else { + PrintAndLog("FIDO2 version length error"); + } - return 0; + return 0; } json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { - json_t *root = NULL; - json_error_t error; - *err = false; + json_t *root = NULL; + json_error_t error; + *err = false; - uint8_t jsonname[250] ={0}; - char *cjsonname = (char *)jsonname; - int jsonnamelen = 0; + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; - // CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); - if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { - CLIParserFree(); - return NULL; - } + // CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); + if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { + CLIParserFree(); + return NULL; + } - // current path + file name - if (!strstr(cjsonname, ".json")) - strcat(cjsonname, ".json"); + // current path + file name + if (!strstr(cjsonname, ".json")) + strcat(cjsonname, ".json"); - if (jsonnamelen) { - strcpy(fname, get_my_executable_directory()); - strcat(fname, cjsonname); - if (access(fname, F_OK) != -1) { - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - *err = true; - return NULL; - } + if (jsonnamelen) { + strcpy(fname, get_my_executable_directory()); + strcat(fname, cjsonname); + if (access(fname, F_OK) != -1) { + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + *err = true; + return NULL; + } - if (!json_is_object(root)) { - PrintAndLog("ERROR: Invalid json format. root must be an object."); - json_decref(root); - *err = true; - return NULL; - } + if (!json_is_object(root)) { + PrintAndLog("ERROR: Invalid json format. root must be an object."); + json_decref(root); + *err = true; + return NULL; + } - } else { - root = json_object(); - } - } - return root; + } else { + root = json_object(); + } + } + return root; } int CmdHFFidoRegister(const char *cmd) { - uint8_t data[64] = {0}; - int chlen = 0; - uint8_t cdata[250] = {0}; - int applen = 0; - uint8_t adata[250] = {0}; - json_t *root = NULL; + uint8_t data[64] = {0}; + int chlen = 0; + uint8_t cdata[250] = {0}; + int applen = 0; + uint8_t adata[250] = {0}; + json_t *root = NULL; - CLIParserInit("hf fido reg", - "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", - "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" - "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" - "\thf fido reg -p s0 s1 -> execute command with plain parameters"); + CLIParserInit("hf fido reg", + "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", + "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" + "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" + "\thf fido reg -p s0 s1 -> execute command with plain parameters"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), - arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), - arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool verbose2 = arg_get_lit(2) > 1; - bool paramsPlain = arg_get_lit(3); - bool showDERTLV = arg_get_lit(4); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool paramsPlain = arg_get_lit(3); + bool showDERTLV = arg_get_lit(4); - char fname[250] = {0}; - bool err; - root = OpenJson(5, fname, argtable, &err); - if(err) - return 1; - if (root) { - size_t jlen; - JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); - JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); - } + char fname[250] = {0}; + bool err; + root = OpenJson(5, fname, argtable, &err); + if(err) + return 1; + if (root) { + size_t jlen; + JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); + JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); + } - if (paramsPlain) { - memset(cdata, 0x00, 32); - CLIGetStrWithReturn(6, cdata, &chlen); - if (chlen && chlen > 16) { - PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); - return 1; - } - } else { - CLIGetHexWithReturn(6, cdata, &chlen); - if (chlen && chlen != 32) { - PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); - return 1; - } - } - if (chlen) - memmove(data, cdata, 32); + if (paramsPlain) { + memset(cdata, 0x00, 32); + CLIGetStrWithReturn(6, cdata, &chlen); + if (chlen && chlen > 16) { + PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); + return 1; + } + } else { + CLIGetHexWithReturn(6, cdata, &chlen); + if (chlen && chlen != 32) { + PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); + return 1; + } + } + if (chlen) + memmove(data, cdata, 32); - if (paramsPlain) { - memset(adata, 0x00, 32); - CLIGetStrWithReturn(7, adata, &applen); - if (applen && applen > 16) { - PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); - return 1; - } - } else { - CLIGetHexWithReturn(7, adata, &applen); - if (applen && applen != 32) { - PrintAndLog("ERROR: application parameter length must be 32 bytes only."); - return 1; - } - } - if (applen) - memmove(&data[32], adata, 32); + if (paramsPlain) { + memset(adata, 0x00, 32); + CLIGetStrWithReturn(7, adata, &applen); + if (applen && applen > 16) { + PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); + return 1; + } + } else { + CLIGetHexWithReturn(7, adata, &applen); + if (applen && applen != 32) { + PrintAndLog("ERROR: application parameter length must be 32 bytes only."); + return 1; + } + } + if (applen) + memmove(&data[32], adata, 32); - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - // challenge parameter [32 bytes] - The challenge parameter is the SHA-256 hash of the Client Data, a stringified JSON data structure that the FIDO Client prepares - // application parameter [32 bytes] - The application parameter is the SHA-256 hash of the UTF-8 encoding of the application identity + // challenge parameter [32 bytes] - The challenge parameter is the SHA-256 hash of the Client Data, a stringified JSON data structure that the FIDO Client prepares + // application parameter [32 bytes] - The application parameter is the SHA-256 hash of the UTF-8 encoding of the application identity - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDORegister(data, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute register command. res=%x. Exit...", res); - return res; - } + res = FIDORegister(data, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute register command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - PrintAndLog(""); - if (APDULogging) - PrintAndLog("---------------------------------------------------------------"); - PrintAndLog("data len: %d", len); - if (verbose2) { - PrintAndLog("--------------data----------------------"); - dump_buffer((const unsigned char *)buf, len, NULL, 0); - PrintAndLog("--------------data----------------------"); - } + PrintAndLog(""); + if (APDULogging) + PrintAndLog("---------------------------------------------------------------"); + PrintAndLog("data len: %d", len); + if (verbose2) { + PrintAndLog("--------------data----------------------"); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + PrintAndLog("--------------data----------------------"); + } - if (buf[0] != 0x05) { - PrintAndLog("ERROR: First byte must be 0x05, but it %2x", buf[0]); - return 5; - } - PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65)); + if (buf[0] != 0x05) { + PrintAndLog("ERROR: First byte must be 0x05, but it %2x", buf[0]); + return 5; + } + PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65)); - uint8_t keyHandleLen = buf[66]; - PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen)); + uint8_t keyHandleLen = buf[66]; + PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen)); - int derp = 67 + keyHandleLen; - int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; - if (verbose2) { - PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); - dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL); - PrintAndLog("\n----------------DER---------------------"); - } else { - if (verbose) - PrintAndLog("------------------DER-------------------"); - PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); - } + int derp = 67 + keyHandleLen; + int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; + if (verbose2) { + PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); + dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL); + PrintAndLog("\n----------------DER---------------------"); + } else { + if (verbose) + PrintAndLog("------------------DER-------------------"); + PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); + } - // check and print DER certificate - uint8_t public_key[65] = {0}; + // check and print DER certificate + uint8_t public_key[65] = {0}; - // print DER certificate in TLV view - if (showDERTLV) { - PrintAndLog("----------------DER TLV-----------------"); - asn1_print(&buf[derp], derLen, " "); - PrintAndLog("----------------DER TLV-----------------"); - } + // print DER certificate in TLV view + if (showDERTLV) { + PrintAndLog("----------------DER TLV-----------------"); + asn1_print(&buf[derp], derLen, " "); + PrintAndLog("----------------DER TLV-----------------"); + } FIDOCheckDERAndGetKey(&buf[derp], derLen, verbose, public_key, sizeof(public_key)); - // get hash - int hashp = 1 + 65 + 1 + keyHandleLen + derLen; - PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); + // get hash + int hashp = 1 + 65 + 1 + keyHandleLen + derLen; + PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); - // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - "\x00", 1, - &data[32], 32, // application parameter - &data[0], 32, // challenge parameter - &buf[67], keyHandleLen, // keyHandle - &buf[1], 65, // user public key - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + "\x00", 1, + &data[32], 32, // application parameter + &data[0], 32, // challenge parameter + &buf[67], keyHandleLen, // keyHandle + &buf[1], 65, // user public key + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } - PrintAndLog("\nauth command: "); - printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); - if(chlen || applen) - printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32)); - if(applen) - printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); - printf("\n"); + PrintAndLog("\nauth command: "); + printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); + if(chlen || applen) + printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32)); + if(applen) + printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); + printf("\n"); - if (root) { - JsonSaveBufAsHex(root, "ChallengeParam", data, 32); - JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); - JsonSaveBufAsHexCompact(root, "PublicKey", &buf[1], 65); - JsonSaveInt(root, "KeyHandleLen", keyHandleLen); - JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); - JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveBufAsHexCompact(root, "PublicKey", &buf[1], 65); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); + JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); - // free json object - json_decref(root); - } + // free json object + json_decref(root); + } - return 0; + return 0; }; int CmdHFFidoAuthenticate(const char *cmd) { - uint8_t data[512] = {0}; - uint8_t hdata[250] = {0}; - bool public_key_loaded = false; - uint8_t public_key[65] = {0}; - int hdatalen = 0; - uint8_t keyHandleLen = 0; - json_t *root = NULL; + uint8_t data[512] = {0}; + uint8_t hdata[250] = {0}; + bool public_key_loaded = false; + uint8_t public_key[65] = {0}; + int hdatalen = 0; + uint8_t keyHandleLen = 0; + json_t *root = NULL; - CLIParserInit("hf fido auth", - "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", - "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" - "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " - "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); + CLIParserInit("hf fido auth", + "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", + "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" + "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " + "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_lit0("vV", "verbose", "show technical data"), - arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), - arg_rem("default mode:", "dont-enforce-user-presence-and-sign"), - arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"), - arg_lit0("cC", "check", "mode: check-only"), - arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), - arg_str0("kK", "key", "public key to verify signature", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("vV", "verbose", "show technical data"), + arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_rem("default mode:", "dont-enforce-user-presence-and-sign"), + arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"), + arg_lit0("cC", "check", "mode: check-only"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0("kK", "key", "public key to verify signature", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool paramsPlain = arg_get_lit(3); - uint8_t controlByte = 0x08; - if (arg_get_lit(5)) - controlByte = 0x03; - if (arg_get_lit(6)) - controlByte = 0x07; + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool paramsPlain = arg_get_lit(3); + uint8_t controlByte = 0x08; + if (arg_get_lit(5)) + controlByte = 0x03; + if (arg_get_lit(6)) + controlByte = 0x07; - char fname[250] = {0}; - bool err; - root = OpenJson(7, fname, argtable, &err); - if(err) - return 1; - if (root) { - size_t jlen; - JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); - JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); - JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); - keyHandleLen = jlen & 0xff; - data[64] = keyHandleLen; - JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); - public_key_loaded = (jlen > 0); - } + char fname[250] = {0}; + bool err; + root = OpenJson(7, fname, argtable, &err); + if(err) + return 1; + if (root) { + size_t jlen; + JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); + JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); + JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); + keyHandleLen = jlen & 0xff; + data[64] = keyHandleLen; + JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); + public_key_loaded = (jlen > 0); + } - // public key - CLIGetHexWithReturn(8, hdata, &hdatalen); - if (hdatalen && hdatalen != 65) { - PrintAndLog("ERROR: public key length must be 65 bytes only."); - return 1; - } - if (hdatalen) { - memmove(public_key, hdata, hdatalen); - public_key_loaded = true; - } + // public key + CLIGetHexWithReturn(8, hdata, &hdatalen); + if (hdatalen && hdatalen != 65) { + PrintAndLog("ERROR: public key length must be 65 bytes only."); + return 1; + } + if (hdatalen) { + memmove(public_key, hdata, hdatalen); + public_key_loaded = true; + } - CLIGetHexWithReturn(9, hdata, &hdatalen); - if (hdatalen > 255) { - PrintAndLog("ERROR: application parameter length must be less than 255."); - return 1; - } - if (hdatalen) { - keyHandleLen = hdatalen; - data[64] = keyHandleLen; - memmove(&data[65], hdata, keyHandleLen); - } + CLIGetHexWithReturn(9, hdata, &hdatalen); + if (hdatalen > 255) { + PrintAndLog("ERROR: application parameter length must be less than 255."); + return 1; + } + if (hdatalen) { + keyHandleLen = hdatalen; + data[64] = keyHandleLen; + memmove(&data[65], hdata, keyHandleLen); + } - if (paramsPlain) { - memset(hdata, 0x00, 32); - CLIGetStrWithReturn(9, hdata, &hdatalen); - if (hdatalen && hdatalen > 16) { - PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); - return 1; - } - } else { - CLIGetHexWithReturn(10, hdata, &hdatalen); - if (hdatalen && hdatalen != 32) { - PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); - return 1; - } - } - if (hdatalen) - memmove(data, hdata, 32); + if (paramsPlain) { + memset(hdata, 0x00, 32); + CLIGetStrWithReturn(9, hdata, &hdatalen); + if (hdatalen && hdatalen > 16) { + PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); + return 1; + } + } else { + CLIGetHexWithReturn(10, hdata, &hdatalen); + if (hdatalen && hdatalen != 32) { + PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); + return 1; + } + } + if (hdatalen) + memmove(data, hdata, 32); - if (paramsPlain) { - memset(hdata, 0x00, 32); - CLIGetStrWithReturn(11, hdata, &hdatalen); - if (hdatalen && hdatalen > 16) { - PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); - return 1; - } - } else { - CLIGetHexWithReturn(10, hdata, &hdatalen); - if (hdatalen && hdatalen != 32) { - PrintAndLog("ERROR: application parameter length must be 32 bytes only."); - return 1; - } - } - if (hdatalen) - memmove(&data[32], hdata, 32); + if (paramsPlain) { + memset(hdata, 0x00, 32); + CLIGetStrWithReturn(11, hdata, &hdatalen); + if (hdatalen && hdatalen > 16) { + PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); + return 1; + } + } else { + CLIGetHexWithReturn(10, hdata, &hdatalen); + if (hdatalen && hdatalen != 32) { + PrintAndLog("ERROR: application parameter length must be 32 bytes only."); + return 1; + } + } + if (hdatalen) + memmove(&data[32], hdata, 32); - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - // (in parameter) conrtol byte 0x07 - check only, 0x03 - user presense + cign. 0x08 - sign only - // challenge parameter [32 bytes] - // application parameter [32 bytes] - // key handle length [1b] = N - // key handle [N] + // (in parameter) conrtol byte 0x07 - check only, 0x03 - user presense + cign. 0x08 - sign only + // challenge parameter [32 bytes] + // application parameter [32 bytes] + // key handle length [1b] = N + // key handle [N] - uint8_t datalen = 32 + 32 + 1 + keyHandleLen; + uint8_t datalen = 32 + 32 + 1 + keyHandleLen; - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute authentication command. res=%x. Exit...", res); - return res; - } + res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute authentication command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - PrintAndLog("---------------------------------------------------------------"); - PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified")); - uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); - PrintAndLog("Counter: %d", cntr); - PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); + PrintAndLog("---------------------------------------------------------------"); + PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified")); + uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); + PrintAndLog("Counter: %d", cntr); + PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); - // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } - if (public_key_loaded) { - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - &data[32], 32, // application parameter - &buf[0], 1, // user presence - &buf[1], 4, // counter - data, 32, // challenge parameter - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } - } else { - PrintAndLog("No public key provided. can't check signature."); - } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + if (public_key_loaded) { + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + &data[32], 32, // application parameter + &buf[0], 1, // user presence + &buf[1], 4, // counter + data, 32, // challenge parameter + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("No public key provided. can't check signature."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } - if (root) { - JsonSaveBufAsHex(root, "ChallengeParam", data, 32); - JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); - JsonSaveInt(root, "KeyHandleLen", keyHandleLen); - JsonSaveBufAsHexCompact(root, "KeyHandle", &data[65], keyHandleLen); - JsonSaveInt(root, "Counter", cntr); + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &data[65], keyHandleLen); + JsonSaveInt(root, "Counter", cntr); - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); - // free json object - json_decref(root); - } - return 0; + // free json object + json_decref(root); + } + return 0; }; void CheckSlash(char *fileName) { - if ((fileName[strlen(fileName) - 1] != '/') && - (fileName[strlen(fileName) - 1] != '\\')) - strcat(fileName, "/"); + if ((fileName[strlen(fileName) - 1] != '/') && + (fileName[strlen(fileName) - 1] != '\\')) + strcat(fileName, "/"); } int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName) { - fileName[0] = 0x00; - strcpy(fileName, get_my_executable_directory()); - CheckSlash(fileName); + fileName[0] = 0x00; + strcpy(fileName, get_my_executable_directory()); + CheckSlash(fileName); - strcat(fileName, prefixDir); - CheckSlash(fileName); + strcat(fileName, prefixDir); + CheckSlash(fileName); - strcat(fileName, reqestedFileName); - if (!strstr(fileName, ".json")) - strcat(fileName, ".json"); + strcat(fileName, reqestedFileName); + if (!strstr(fileName, ".json")) + strcat(fileName, ".json"); - if (access(fileName, F_OK) < 0) { - strcpy(fileName, get_my_executable_directory()); - CheckSlash(fileName); + if (access(fileName, F_OK) < 0) { + strcpy(fileName, get_my_executable_directory()); + CheckSlash(fileName); - strcat(fileName, reqestedFileName); - if (!strstr(fileName, ".json")) - strcat(fileName, ".json"); + strcat(fileName, reqestedFileName); + if (!strstr(fileName, ".json")) + strcat(fileName, ".json"); - if (access(fileName, F_OK) < 0) { - return 1; // file not found - } - } - return 0; + if (access(fileName, F_OK) < 0) { + return 1; // file not found + } + } + return 0; } int CmdHFFido2MakeCredential(const char *cmd) { - json_error_t error; - json_t *root = NULL; - char fname[300] = {0}; + json_error_t error; + json_t *root = NULL; + char fname[300] = {0}; - CLIParserInit("hf fido make", - "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", - "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" - "\thf fido make test.json -> execute command with parameters file `text.json`"); + CLIParserInit("hf fido make", + "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" + "\thf fido make test.json -> execute command with parameters file `text.json`"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), - arg_lit0("cC", "cbor", "show CBOR decoded data"), - arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), + arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool verbose2 = arg_get_lit(2) > 1; - bool showDERTLV = arg_get_lit(3); - bool showCBOR = arg_get_lit(4); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool showDERTLV = arg_get_lit(3); + bool showCBOR = arg_get_lit(4); - uint8_t jsonname[250] ={0}; - char *cjsonname = (char *)jsonname; - int jsonnamelen = 0; - CLIGetStrWithReturn(5, jsonname, &jsonnamelen); + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(5, jsonname, &jsonnamelen); - if (!jsonnamelen) { - strcat(cjsonname, "fido2"); - jsonnamelen = strlen(cjsonname); - } + if (!jsonnamelen) { + strcat(cjsonname, "fido2"); + jsonnamelen = strlen(cjsonname); + } - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - int res = GetExistsFileNameJson("fido", cjsonname, fname); - if(res) { - PrintAndLog("ERROR: Can't found the json file."); - return res; - } - PrintAndLog("fname: %s\n", fname); - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - return 1; - } + int res = GetExistsFileNameJson("fido", cjsonname, fname); + if(res) { + PrintAndLog("ERROR: Can't found the json file."); + return res; + } + PrintAndLog("fname: %s\n", fname); + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } - uint8_t data[2048] = {0}; - size_t datalen = 0; - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t data[2048] = {0}; + size_t datalen = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); - if (res) - return res; + res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); + if (res) + return res; - if (showCBOR) { - PrintAndLog("CBOR make credentional request:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); - PrintAndLog("---------------- CBOR ------------------"); - } + if (showCBOR) { + PrintAndLog("CBOR make credentional request:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + PrintAndLog("---------------- CBOR ------------------"); + } - res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute make credential command. res=%x. Exit...", res); - return res; - } + res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute make credential command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - if(buf[0]) { - PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); - return 0; - } + if(buf[0]) { + PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } - PrintAndLog("MakeCredential result (%d b) OK.", len); - if (showCBOR) { - PrintAndLog("CBOR make credentional response:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); - PrintAndLog("---------------- CBOR ------------------"); - } + PrintAndLog("MakeCredential result (%d b) OK.", len); + if (showCBOR) { + PrintAndLog("CBOR make credentional response:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + PrintAndLog("---------------- CBOR ------------------"); + } - // parse returned cbor - FIDO2MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); + // parse returned cbor + FIDO2MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); - if (root) { - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); - } + if (root) { + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + } - json_decref(root); + json_decref(root); - return 0; + return 0; }; int CmdHFFido2GetAssertion(const char *cmd) { - json_error_t error; - json_t *root = NULL; - char fname[300] = {0}; + json_error_t error; + json_t *root = NULL; + char fname[300] = {0}; - CLIParserInit("hf fido assert", - "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", - "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" - "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); + CLIParserInit("hf fido assert", + "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" + "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("cC", "cbor", "show CBOR decoded data"), - arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator don't store credential to its memory)"), - arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator don't store credential to its memory)"), + arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool verbose2 = arg_get_lit(2) > 1; - bool showCBOR = arg_get_lit(3); - bool createAllowList = arg_get_lit(4); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool showCBOR = arg_get_lit(3); + bool createAllowList = arg_get_lit(4); - uint8_t jsonname[250] ={0}; - char *cjsonname = (char *)jsonname; - int jsonnamelen = 0; - CLIGetStrWithReturn(5, jsonname, &jsonnamelen); + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(5, jsonname, &jsonnamelen); - if (!jsonnamelen) { - strcat(cjsonname, "fido2"); - jsonnamelen = strlen(cjsonname); - } + if (!jsonnamelen) { + strcat(cjsonname, "fido2"); + jsonnamelen = strlen(cjsonname); + } - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - int res = GetExistsFileNameJson("fido", "fido2", fname); - if(res) { - PrintAndLog("ERROR: Can't found the json file."); - return res; - } - PrintAndLog("fname: %s\n", fname); - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - return 1; - } + int res = GetExistsFileNameJson("fido", "fido2", fname); + if(res) { + PrintAndLog("ERROR: Can't found the json file."); + return res; + } + PrintAndLog("fname: %s\n", fname); + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } - uint8_t data[2048] = {0}; - size_t datalen = 0; - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t data[2048] = {0}; + size_t datalen = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList); - if (res) - return res; + res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList); + if (res) + return res; - if (showCBOR) { - PrintAndLog("CBOR get assertion request:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); - PrintAndLog("---------------- CBOR ------------------"); - } + if (showCBOR) { + PrintAndLog("CBOR get assertion request:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); + PrintAndLog("---------------- CBOR ------------------"); + } - res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res); - return res; - } + res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - if(buf[0]) { - PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); - return 0; - } + if(buf[0]) { + PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } - PrintAndLog("GetAssertion result (%d b) OK.", len); - if (showCBOR) { - PrintAndLog("CBOR get assertion response:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1); - PrintAndLog("---------------- CBOR ------------------"); - } + PrintAndLog("GetAssertion result (%d b) OK.", len); + if (showCBOR) { + PrintAndLog("CBOR get assertion response:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1); + PrintAndLog("---------------- CBOR ------------------"); + } - // parse returned cbor - FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); + // parse returned cbor + FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); - if (root) { - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); - } + if (root) { + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + } - json_decref(root); + json_decref(root); - return 0; + return 0; }; static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help."}, - {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, - {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, - {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, - {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, - {"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help."}, + {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, + {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, + {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, + {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, + {"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, + {NULL, NULL, 0, NULL} }; int CmdHFFido(const char *Cmd) { - (void)WaitForResponseTimeout(CMD_ACK, NULL, 100); - CmdsParse(CommandTable, Cmd); - return 0; + (void)WaitForResponseTimeout(CMD_ACK, NULL, 100); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index bf8976e8a..20bcfdf33 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -19,346 +19,346 @@ static int CmdHelp(const char *Cmd); static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }; int usage_hf_iclass_sim(void) { - PrintAndLogEx(NORMAL, "Usage: hf iclass sim