mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-09-12 11:17:15 +00:00
in appmain.c and cmd added. in cmd.c and add some code for test CEP in em4x50.c(Do not timeout--) in em4x70.c in emvsim.c in epa.c in felica.c in felicasim.c in felicasim.c in hfops.c in hfsnoop.c in hitag2.c in hitag_common.c(Cross-platform implementation is incomplete.) in hitagS.c in hitagu.c in i2c.c(Incomplete, continue to abstract.) in i2c_direct.c in iclass.c in iso14443a.c(Sniff no finish yet) in iso14443b.c and fixed bug for st25 in iso15693.c in legicrf.c in legicrfsim.c in lfadc.c(lf_count_edge_periods_ex() improved) in lfops.c(TI tag no finish yet) in lfsampling.c in lfzx.c in mifarecmd.c in mifaredesfire.c in mifaresim.c in mifaresniff_disabled.c in mifareutil.c in pcf7931.c in sam_xxx in secc & seos in start.c in thinfilm.c in utils
363 lines
9.2 KiB
C
363 lines
9.2 KiB
C
//-----------------------------------------------------------------------------
|
|
// Copyright (C) Jonathan Westhues, Sept 2005
|
|
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// See LICENSE.txt for the text of the license.
|
|
//-----------------------------------------------------------------------------
|
|
// Utility functions used in many places, not specific to any piece of code.
|
|
//-----------------------------------------------------------------------------
|
|
#include "util.h"
|
|
|
|
#include "proxmark3_arm.h"
|
|
#include "ticks_apis.h"
|
|
#include "commonutil.h"
|
|
#include "dbprint.h"
|
|
#include "string.h"
|
|
#include "usb_cdc_apis.h"
|
|
#include "usart.h"
|
|
|
|
size_t nbytes(size_t nbits) {
|
|
return (nbits >> 3) + ((nbits % 8) > 0);
|
|
}
|
|
|
|
//convert hex digit to integer
|
|
uint8_t hex2int(char x) {
|
|
switch (x) {
|
|
case '0':
|
|
return 0;
|
|
case '1':
|
|
return 1;
|
|
case '2':
|
|
return 2;
|
|
case '3':
|
|
return 3;
|
|
case '4':
|
|
return 4;
|
|
case '5':
|
|
return 5;
|
|
case '6':
|
|
return 6;
|
|
case '7':
|
|
return 7;
|
|
case '8':
|
|
return 8;
|
|
case '9':
|
|
return 9;
|
|
case 'a':
|
|
case 'A':
|
|
return 10;
|
|
case 'b':
|
|
case 'B':
|
|
return 11;
|
|
case 'c':
|
|
case 'C':
|
|
return 12;
|
|
case 'd':
|
|
case 'D':
|
|
return 13;
|
|
case 'e':
|
|
case 'E':
|
|
return 14;
|
|
case 'f':
|
|
case 'F':
|
|
return 15;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
The following methods comes from Rfidler sourcecode.
|
|
https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
|
|
*/
|
|
// convert hex to sequence of 0/1 bit values
|
|
// returns number of bits converted
|
|
int hex2binarray(char *target, const char *source) {
|
|
return hex2binarray_n(target, source, strlen(source));
|
|
}
|
|
|
|
int hex2binarray_n(char *target, const char *source, int sourcelen) {
|
|
int count = 0;
|
|
|
|
// process 4 bits (1 hex digit) at a time
|
|
while (sourcelen--) {
|
|
|
|
char x = *(source++);
|
|
|
|
*(target++) = (x >> 7) & 1;
|
|
*(target++) = (x >> 6) & 1;
|
|
*(target++) = (x >> 5) & 1;
|
|
*(target++) = (x >> 4) & 1;
|
|
*(target++) = (x >> 3) & 1;
|
|
*(target++) = (x >> 2) & 1;
|
|
*(target++) = (x >> 1) & 1;
|
|
*(target++) = (x & 1);
|
|
|
|
count += 8;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex) {
|
|
|
|
int count = 0;
|
|
int byte_index = 0;
|
|
|
|
// Clear output buffer
|
|
memset(hex, 0, bs_len >> 3);
|
|
|
|
for (int i = 0; i < bs_len; i++) {
|
|
|
|
// Set the appropriate bit in hex
|
|
if (bs[i] == 1) {
|
|
hex[byte_index] |= (1 << (7 - (count % 8)));
|
|
}
|
|
|
|
count++;
|
|
|
|
// Move to the next byte if 8 bits have been filled
|
|
if (count % 8 == 0) {
|
|
byte_index++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
|
|
void LEDsoff(void) {
|
|
LED_A_OFF();
|
|
LED_B_OFF();
|
|
LED_C_OFF();
|
|
LED_D_OFF();
|
|
}
|
|
|
|
//ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8
|
|
void LED(int led, int ms) {
|
|
if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
|
|
LED_A_ON();
|
|
if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
|
|
LED_B_ON();
|
|
if (led & LED_C) // Proxmark3 historical mapping: LED_RED
|
|
LED_C_ON();
|
|
if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
|
|
LED_D_ON();
|
|
|
|
if (!ms)
|
|
return;
|
|
|
|
SpinDelay(ms);
|
|
|
|
if (led & LED_A)
|
|
LED_A_OFF();
|
|
if (led & LED_B)
|
|
LED_B_OFF();
|
|
if (led & LED_C)
|
|
LED_C_OFF();
|
|
if (led & LED_D)
|
|
LED_D_OFF();
|
|
}
|
|
|
|
void SpinOff(uint32_t pause) {
|
|
LED_A_OFF();
|
|
LED_B_OFF();
|
|
LED_C_OFF();
|
|
LED_D_OFF();
|
|
SpinDelay(pause);
|
|
}
|
|
|
|
// Blinks..
|
|
// A = 1, B = 2, C = 4, D = 8
|
|
void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
|
|
SpinOff(speed);
|
|
NTIME(times) {
|
|
|
|
if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
|
|
LED_A_INV();
|
|
if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
|
|
LED_B_INV();
|
|
if (led & LED_C) // Proxmark3 historical mapping: LED_RED
|
|
LED_C_INV();
|
|
if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
|
|
LED_D_INV();
|
|
|
|
SpinDelay(speed);
|
|
}
|
|
LED_A_OFF();
|
|
LED_B_OFF();
|
|
LED_C_OFF();
|
|
LED_D_OFF();
|
|
}
|
|
|
|
void SpinDown(uint32_t speed) {
|
|
SpinOff(speed);
|
|
LED_D_ON();
|
|
SpinDelay(speed);
|
|
LED_D_OFF();
|
|
LED_C_ON();
|
|
SpinDelay(speed);
|
|
LED_C_OFF();
|
|
LED_B_ON();
|
|
SpinDelay(speed);
|
|
LED_B_OFF();
|
|
LED_A_ON();
|
|
SpinDelay(speed);
|
|
LED_A_OFF();
|
|
}
|
|
|
|
void SpinUp(uint32_t speed) {
|
|
SpinOff(speed);
|
|
LED_A_ON();
|
|
SpinDelay(speed);
|
|
LED_A_OFF();
|
|
LED_B_ON();
|
|
SpinDelay(speed);
|
|
LED_B_OFF();
|
|
LED_C_ON();
|
|
SpinDelay(speed);
|
|
LED_C_OFF();
|
|
LED_D_ON();
|
|
SpinDelay(speed);
|
|
LED_D_OFF();
|
|
}
|
|
|
|
// Determine if a button is double clicked, single clicked,
|
|
// not clicked, or held down (for ms || 1sec)
|
|
// In general, don't use this function unless you expect a
|
|
// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
|
|
// Note: StartTickCount required.
|
|
int BUTTON_CLICKED(int ms) {
|
|
// If we're not even pressed, forget about it!
|
|
if (BUTTON_PRESS() == false)
|
|
return BUTTON_NO_CLICK;
|
|
|
|
ms = ms ? ms : 1000; // use ms param if valid.
|
|
|
|
int letoff = 0;
|
|
for (;;) {
|
|
|
|
// Using a very short delay period to count how long has passed is much safer than using other methods,
|
|
// as other timers may be stopped/reset
|
|
SpinDelay(1);
|
|
--ms;
|
|
|
|
// We haven't let off the button yet
|
|
if (!letoff) {
|
|
// We just let it off!
|
|
if (BUTTON_PRESS() == false) {
|
|
letoff = 1;
|
|
|
|
// reset our timer for 500ms next press waiting
|
|
ms = 500;
|
|
}
|
|
|
|
// Still haven't let it off
|
|
else
|
|
// Have we held down a full second?
|
|
if (ms <= 0)
|
|
return BUTTON_HOLD;
|
|
}
|
|
|
|
// We already let off, did we click again?
|
|
else
|
|
// Sweet, double click!
|
|
if (BUTTON_PRESS())
|
|
return BUTTON_DOUBLE_CLICK;
|
|
|
|
// Have we ran out of time to double click?
|
|
else if (ms <= 0)
|
|
// At least we did a single click
|
|
return BUTTON_SINGLE_CLICK;
|
|
|
|
WDT_HIT();
|
|
}
|
|
|
|
// We should never get here
|
|
return BUTTON_ERROR;
|
|
}
|
|
|
|
// Determine if a button is held down
|
|
// Note: StartTickCount required.
|
|
int BUTTON_HELD(int ms) {
|
|
// If we're not even pressed, forget about it!
|
|
if (BUTTON_PRESS() == false) {
|
|
return BUTTON_NO_CLICK;
|
|
}
|
|
|
|
ms = ms ? ms : 1000; // use ms param if valid.
|
|
|
|
for (;;) {
|
|
|
|
// As soon as our button let go, we didn't hold long enough
|
|
if (BUTTON_PRESS() == false) {
|
|
return BUTTON_SINGLE_CLICK;
|
|
}
|
|
|
|
// Using a very short delay period to count how long has passed is much safer than using other methods,
|
|
// as other timers may be stopped/reset
|
|
SpinDelay(1);
|
|
--ms;
|
|
|
|
// Have we waited the full second?
|
|
if (ms <= 0) {
|
|
return BUTTON_HOLD;
|
|
}
|
|
|
|
WDT_HIT();
|
|
}
|
|
|
|
// We should never get here
|
|
return BUTTON_ERROR;
|
|
}
|
|
|
|
// This function returns false if no data is available or
|
|
// the USB connection is invalid.
|
|
bool data_available(void) {
|
|
#ifdef WITH_FPC_USART_HOST
|
|
return usb_poll_validate_length() || (usart_rxdata_available() > 0);
|
|
#else
|
|
return usb_poll_validate_length();
|
|
#endif
|
|
}
|
|
|
|
// This function doesn't check if the USB connection is valid.
|
|
// In most of the cases, you should use data_available() unless
|
|
// the timing is critical.
|
|
bool data_available_fast(void) {
|
|
#ifdef WITH_FPC_USART_HOST
|
|
return usb_available_length() || (usart_rxdata_available() > 0);
|
|
#else
|
|
return usb_available_length();
|
|
#endif
|
|
}
|
|
|
|
// Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1
|
|
void convertToHexArray(uint32_t num, uint8_t *partialkey) {
|
|
char binaryStr[25]; // 24 bits for binary representation + 1 for null terminator
|
|
binaryStr[24] = '\0'; // Null-terminate the string
|
|
|
|
// Convert the number to binary string
|
|
for (int i = 23; i >= 0; i--) {
|
|
binaryStr[i] = (num % 2) ? '1' : '0';
|
|
num /= 2;
|
|
}
|
|
|
|
// Split the binary string into groups of 3 and convert to hex
|
|
for (int i = 0; i < 8 ; i++) {
|
|
char group[4] = {'0', '0', '0', '\0'}; // Ensure group is initialized correctly
|
|
memcpy(group, binaryStr + i * 3, 3); // Use memcpy to copy exactly 3 characters
|
|
group[3] = '\0'; // Null-terminate the group string
|
|
partialkey[i] = (uint8_t)strtoul(group, NULL, 2);
|
|
}
|
|
}
|