1 //-----------------------------------------------------------------------------
2 // Copyright (C) Jonathan Westhues, Sept 2005
3 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // See LICENSE.txt for the text of the license.
16 //-----------------------------------------------------------------------------
17 // Utility functions used in many places, not specific to any piece of code.
18 //-----------------------------------------------------------------------------
21 #include "proxmark3_arm.h"
23 #include "commonutil.h"
29 size_t nbytes(size_t nbits
) {
30 return (nbits
>> 3) + ((nbits
% 8) > 0);
33 //convert hex digit to integer
34 uint8_t hex2int(char x
) {
80 The following methods comes from Rfidler sourcecode.
81 https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
83 // convert hex to sequence of 0/1 bit values
84 // returns number of bits converted
85 int hex2binarray(char *target
, const char *source
) {
86 return hex2binarray_n(target
, source
, strlen(source
));
89 int hex2binarray_n(char *target
, const char *source
, int sourcelen
) {
92 // process 4 bits (1 hex digit) at a time
97 *(target
++) = (x
>> 7) & 1;
98 *(target
++) = (x
>> 6) & 1;
99 *(target
++) = (x
>> 5) & 1;
100 *(target
++) = (x
>> 4) & 1;
101 *(target
++) = (x
>> 3) & 1;
102 *(target
++) = (x
>> 2) & 1;
103 *(target
++) = (x
>> 1) & 1;
104 *(target
++) = (x
& 1);
111 int binarray2hex(const uint8_t *bs
, int bs_len
, uint8_t *hex
) {
116 // Clear output buffer
117 memset(hex
, 0, bs_len
>> 3);
119 for (int i
= 0; i
< bs_len
; i
++) {
121 // Set the appropriate bit in hex
123 hex
[byte_index
] |= (1 << (7 - (count
% 8)));
128 // Move to the next byte if 8 bits have been filled
129 if (count
% 8 == 0) {
145 //ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8
146 void LED(int led
, int ms
) {
147 if (led
& LED_A
) // Proxmark3 historical mapping: LED_ORANGE
149 if (led
& LED_B
) // Proxmark3 historical mapping: LED_GREEN
151 if (led
& LED_C
) // Proxmark3 historical mapping: LED_RED
153 if (led
& LED_D
) // Proxmark3 historical mapping: LED_RED2
171 void SpinOff(uint32_t pause
) {
180 // A = 1, B = 2, C = 4, D = 8
181 void SpinErr(uint8_t led
, uint32_t speed
, uint8_t times
) {
185 if (led
& LED_A
) // Proxmark3 historical mapping: LED_ORANGE
187 if (led
& LED_B
) // Proxmark3 historical mapping: LED_GREEN
189 if (led
& LED_C
) // Proxmark3 historical mapping: LED_RED
191 if (led
& LED_D
) // Proxmark3 historical mapping: LED_RED2
202 void SpinDown(uint32_t speed
) {
218 void SpinUp(uint32_t speed
) {
235 // Determine if a button is double clicked, single clicked,
236 // not clicked, or held down (for ms || 1sec)
237 // In general, don't use this function unless you expect a
238 // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
239 int BUTTON_CLICKED(int ms
) {
240 // Up to 500ms in between clicks to mean a double click
241 // timer counts in 21.3us increments (1024/48MHz)
242 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
244 if (g_dbglevel
>= DBG_ERROR
) Dbprintf(_RED_("Error, BUTTON_CLICKED called with %i > 1390"), ms
);
247 int ticks
= ((MCK
/ 1000) * (ms
? ms
: 1000)) >> 10;
249 // If we're not even pressed, forget about it!
250 if (BUTTON_PRESS() == false)
251 return BUTTON_NO_CLICK
;
253 // Borrow a PWM unit for my real-time clock
254 AT91C_BASE_PWMC
->PWMC_ENA
= PWM_CHANNEL(0);
255 // 48 MHz / 1024 gives 46.875 kHz
256 AT91C_BASE_PWMC_CH0
->PWMC_CMR
= PWM_CH_MODE_PRESCALER(10);
257 AT91C_BASE_PWMC_CH0
->PWMC_CDTYR
= 0;
258 AT91C_BASE_PWMC_CH0
->PWMC_CPRDR
= 0xffff;
260 uint16_t start
= AT91C_BASE_PWMC_CH0
->PWMC_CCNTR
;
264 uint16_t now
= AT91C_BASE_PWMC_CH0
->PWMC_CCNTR
;
266 // We haven't let off the button yet
268 // We just let it off!
269 if (BUTTON_PRESS() == false) {
272 // reset our timer for 500ms
273 start
= AT91C_BASE_PWMC_CH0
->PWMC_CCNTR
;
274 ticks
= ((MCK
/ 1000) * (500)) >> 10;
277 // Still haven't let it off
279 // Have we held down a full second?
280 if (now
== (uint16_t)(start
+ ticks
))
284 // We already let off, did we click again?
286 // Sweet, double click!
288 return BUTTON_DOUBLE_CLICK
;
290 // Have we ran out of time to double click?
291 else if (now
== (uint16_t)(start
+ ticks
))
292 // At least we did a single click
293 return BUTTON_SINGLE_CLICK
;
298 // We should never get here
302 // Determine if a button is held down
303 int BUTTON_HELD(int ms
) {
304 // timer counts in 21.3us increments (1024/48MHz)
305 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
307 if (g_dbglevel
>= DBG_ERROR
) Dbprintf(_RED_("Error, BUTTON_HELD called with %i > 1390"), ms
);
310 // If button is held for one second
311 int ticks
= (48000 * (ms
? ms
: 1000)) >> 10;
313 // If we're not even pressed, forget about it!
314 if (BUTTON_PRESS() == false) {
315 return BUTTON_NO_CLICK
;
318 // Borrow a PWM unit for my real-time clock
319 AT91C_BASE_PWMC
->PWMC_ENA
= PWM_CHANNEL(0);
320 // 48 MHz / 1024 gives 46.875 kHz
321 AT91C_BASE_PWMC_CH0
->PWMC_CMR
= PWM_CH_MODE_PRESCALER(10);
322 AT91C_BASE_PWMC_CH0
->PWMC_CDTYR
= 0;
323 AT91C_BASE_PWMC_CH0
->PWMC_CPRDR
= 0xffff;
325 uint16_t start
= AT91C_BASE_PWMC_CH0
->PWMC_CCNTR
;
328 uint16_t now
= AT91C_BASE_PWMC_CH0
->PWMC_CCNTR
;
330 // As soon as our button let go, we didn't hold long enough
331 if (BUTTON_PRESS() == false) {
332 return BUTTON_SINGLE_CLICK
;
335 // Have we waited the full second?
336 else if (now
== (uint16_t)(start
+ ticks
)) {
343 // We should never get here
347 // This function returns false if no data is available or
348 // the USB connection is invalid.
349 bool data_available(void) {
350 #ifdef WITH_FPC_USART_HOST
351 return usb_poll_validate_length() || (usart_rxdata_available() > 0);
353 return usb_poll_validate_length();
357 // This function doesn't check if the USB connection is valid.
358 // In most of the cases, you should use data_available() unless
359 // the timing is critical.
360 bool data_available_fast(void) {
361 #ifdef WITH_FPC_USART_HOST
362 return usb_available_length() || (usart_rxdata_available() > 0);
364 return usb_available_length();
368 uint32_t flash_size_from_cidr(uint32_t cidr
) {
369 uint8_t nvpsiz
= (cidr
& 0xF00) >> 8;
390 default: // for 'reserved' values, guess 2MB
395 uint32_t get_flash_size(void) {
396 return flash_size_from_cidr(*AT91C_DBGU_CIDR
);
399 // Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1
400 void convertToHexArray(uint32_t num
, uint8_t *partialkey
) {
401 char binaryStr
[25]; // 24 bits for binary representation + 1 for null terminator
402 binaryStr
[24] = '\0'; // Null-terminate the string
404 // Convert the number to binary string
405 for (int i
= 23; i
>= 0; i
--) {
406 binaryStr
[i
] = (num
% 2) ? '1' : '0';
410 // Split the binary string into groups of 3 and convert to hex
411 for (int i
= 0; i
< 8 ; i
++) {
412 char group
[4] = {'0', '0', '0', '\0'}; // Ensure group is initialized correctly
413 memcpy(group
, binaryStr
+ i
* 3, 3); // Use memcpy to copy exactly 3 characters
414 group
[3] = '\0'; // Null-terminate the group string
415 partialkey
[i
] = (uint8_t)strtoul(group
, NULL
, 2);