1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
11 // ensure gmtime_r is available even with -std=c99; must be included before
12 #if !defined(_WIN32) && !defined(__APPLE__)
13 #define _POSIX_C_SOURCE 200112L
24 #include <time.h> // Mingw
26 #include "ui.h" // PrintAndLog
28 #define UTIL_BUFFER_SIZE_SPRINT 4097
29 // global client debug variable
30 uint8_t g_debugMode
= 0;
31 // global client disable logging variable
32 uint8_t g_printAndLog
= PRINTANDLOG_PRINT
| PRINTANDLOG_LOG
;
33 // global client tell if a pending prompt is present
34 bool g_pendingPrompt
= false;
40 #define MAX_BIN_BREAK_LENGTH (3072+384+1)
46 int kbd_enter_pressed(void) {
48 if ((flags
= fcntl(STDIN_FILENO
, F_GETFL
, 0)) < 0) {
49 PrintAndLogEx(ERR
, "fcntl failed in kbd_enter_pressed");
54 if (fcntl(STDIN_FILENO
, F_SETFL
, flags
) < 0) {
55 PrintAndLogEx(ERR
, "fcntl failed in kbd_enter_pressed");
60 do { //get all available chars
66 if (fcntl(STDIN_FILENO
, F_SETFL
, flags
) < 0) {
67 PrintAndLogEx(ERR
, "fcntl failed in kbd_enter_pressed");
76 int kbd_enter_pressed(void) {
79 ret
|= getch() == '\r';
85 // create filename on hex uid.
86 // param *fn - pointer to filename char array
87 // param *uid - pointer to uid byte array
88 // param *ext - ".log"
89 // param uidlen - length of uid array.
90 void FillFileNameByUID(char *filenamePrefix
, const uint8_t *uid
, const char *ext
, const int uidlen
) {
91 if (filenamePrefix
== NULL
|| uid
== NULL
|| ext
== NULL
) {
95 int len
= strlen(filenamePrefix
);
97 for (int j
= 0; j
< uidlen
; j
++)
98 sprintf(filenamePrefix
+ len
+ j
* 2, "%02X", uid
[j
]);
100 strcat(filenamePrefix
, ext
);
103 // fill buffer from structure [{uint8_t data, size_t length},...]
104 int FillBuffer(uint8_t *data
, size_t maxDataLength
, size_t *dataLength
, ...) {
107 va_start(valist
, dataLength
);
109 uint8_t *vdata
= NULL
;
112 vdata
= va_arg(valist
, uint8_t *);
116 size_t vlength
= va_arg(valist
, size_t);
117 if (*dataLength
+ vlength
> maxDataLength
) {
122 memcpy(&data
[*dataLength
], vdata
, vlength
);
123 *dataLength
+= vlength
;
132 bool CheckStringIsHEXValue(const char *value
) {
133 for (size_t i
= 0; i
< strlen(value
); i
++)
134 if (!isxdigit(value
[i
]))
137 if (strlen(value
) % 2)
143 void hex_to_buffer(const uint8_t *buf
, const uint8_t *hex_data
, const size_t hex_len
, const size_t hex_max_len
,
144 const size_t min_str_len
, const size_t spaces_between
, bool uppercase
) {
146 if (buf
== NULL
) return;
148 char *tmp
= (char *)buf
;
150 memset(tmp
, 0x00, hex_max_len
);
152 size_t max_len
= (hex_len
> hex_max_len
) ? hex_max_len
: hex_len
;
154 for (i
= 0; i
< max_len
; ++i
, tmp
+= 2 + spaces_between
) {
155 sprintf(tmp
, (uppercase
) ? "%02X" : "%02x", (unsigned int) hex_data
[i
]);
157 for (size_t j
= 0; j
< spaces_between
; j
++)
158 sprintf(tmp
+ 2 + j
, " ");
161 i
*= (2 + spaces_between
);
163 size_t mlen
= min_str_len
> i
? min_str_len
: 0;
164 if (mlen
> hex_max_len
)
167 for (; i
< mlen
; i
++, tmp
+= 1)
175 // printing and converting functions
176 void print_hex(const uint8_t *data
, const size_t len
) {
177 if (data
== NULL
|| len
== 0) return;
179 for (size_t i
= 0; i
< len
; i
++)
180 PrintAndLogEx(NORMAL
, "%02x " NOLF
, data
[i
]);
182 PrintAndLogEx(NORMAL
, "");
185 void print_hex_break(const uint8_t *data
, const size_t len
, uint8_t breaks
) {
186 if (data
== NULL
|| len
== 0 || breaks
== 0) return;
190 for (i
= 0; i
< len
; i
+= breaks
, rownum
++) {
191 if (len
- i
< breaks
) { // incomplete block, will be treated out of the loop
194 PrintAndLogEx(INFO
, "%02u | %s", rownum
, sprint_hex_ascii(data
+ i
, breaks
));
197 // the last odd bytes
198 uint8_t mod
= len
% breaks
;
201 char buf
[UTIL_BUFFER_SIZE_SPRINT
+ 3];
202 memset(buf
, 0, sizeof(buf
));
203 hex_to_buffer((uint8_t *)buf
, data
+ i
, mod
, (sizeof(buf
) - 1), 0, 1, true);
206 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), "%*s", ((breaks
- mod
) * 3), " ");
207 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), "| %s", sprint_ascii(data
+ i
, mod
));
208 PrintAndLogEx(INFO
, "%02u | %s", rownum
, buf
);
212 static void print_buffer_ex(const uint8_t *data
, const size_t len
, int level
, uint8_t breaks
) {
217 char buf
[UTIL_BUFFER_SIZE_SPRINT
+ 3];
219 for (i
= 0; i
< len
; i
+= breaks
) {
220 if (len
- i
< breaks
) { // incomplete block, will be treated out of the loop
223 // (16 * 3) + (16) + + 1
224 memset(buf
, 0, sizeof(buf
));
225 sprintf(buf
, "%*s%02x: ", (level
* 4), " ", i
);
227 hex_to_buffer((uint8_t *)(buf
+ strlen(buf
)), data
+ i
, breaks
, (sizeof(buf
) - strlen(buf
) - 1), 0, 1, true);
228 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), "| %s", sprint_ascii(data
+ i
, breaks
));
229 PrintAndLogEx(INFO
, "%s", buf
);
232 // the last odd bytes
233 uint8_t mod
= len
% breaks
;
236 memset(buf
, 0, sizeof(buf
));
237 sprintf(buf
, "%*s%02x: ", (level
* 4), " ", i
);
238 hex_to_buffer((uint8_t *)(buf
+ strlen(buf
)), data
+ i
, mod
, (sizeof(buf
) - strlen(buf
) - 1), 0, 1, true);
241 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), "%*s", ((breaks
- mod
) * 3), " ");
243 snprintf(buf
+ strlen(buf
), sizeof(buf
) - strlen(buf
), "| %s", sprint_ascii(data
+ i
, mod
));
244 PrintAndLogEx(INFO
, "%s", buf
);
248 void print_buffer(const uint8_t *data
, const size_t len
, int level
) {
249 print_buffer_ex(data
, len
, level
, 16);
252 void print_blocks(uint32_t *data
, size_t len
) {
253 PrintAndLogEx(SUCCESS
, "Blk | Data ");
254 PrintAndLogEx(SUCCESS
, "----+------------");
257 PrintAndLogEx(ERR
, "..empty data");
259 for (uint8_t i
= 0; i
< len
; i
++)
260 PrintAndLogEx(SUCCESS
, " %02d | %08X", i
, data
[i
]);
264 char *sprint_hex(const uint8_t *data
, const size_t len
) {
265 static char buf
[UTIL_BUFFER_SIZE_SPRINT
- 3] = {0};
266 hex_to_buffer((uint8_t *)buf
, data
, len
, sizeof(buf
) - 1, 0, 1, true);
270 char *sprint_hex_inrow_ex(const uint8_t *data
, const size_t len
, const size_t min_str_len
) {
271 static char buf
[UTIL_BUFFER_SIZE_SPRINT
] = {0};
272 hex_to_buffer((uint8_t *)buf
, data
, len
, sizeof(buf
) - 1, min_str_len
, 0, true);
276 char *sprint_hex_inrow(const uint8_t *data
, const size_t len
) {
277 return sprint_hex_inrow_ex(data
, len
, 0);
279 char *sprint_hex_inrow_spaces(const uint8_t *data
, const size_t len
, size_t spaces_between
) {
280 static char buf
[UTIL_BUFFER_SIZE_SPRINT
] = {0};
281 hex_to_buffer((uint8_t *)buf
, data
, len
, sizeof(buf
) - 1, 0, spaces_between
, true);
285 char *sprint_bin_break(const uint8_t *data
, const size_t len
, const uint8_t breaks
) {
287 // make sure we don't go beyond our char array memory
288 size_t rowlen
= (len
> MAX_BIN_BREAK_LENGTH
) ? MAX_BIN_BREAK_LENGTH
: len
;
290 // 3072 + end of line characters if broken at 8 bits
291 static char buf
[MAX_BIN_BREAK_LENGTH
];
292 memset(buf
, 0x00, sizeof(buf
));
295 // loop through the out_index to make sure we don't go too far
296 for (int i
= 0; i
< rowlen
; i
++) {
299 // manchester wrong bit marker
307 // check if a line break is needed and we have room to print it in our array
309 if (((i
+ 1) % breaks
) == 0) {
318 void sprint_bin_break_ex(uint8_t *src, size_t srclen, char *dest , uint8_t breaks) {
319 if ( src == NULL ) return;
320 if ( srclen < 1 ) return;
322 // make sure we don't go beyond our char array memory
323 size_t in_index = 0, out_index = 0;
326 rowlen = ( len > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len;
328 rowlen = ( len+(len/breaks) > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len+(len/breaks);
330 PrintAndLogEx(NORMAL, "(sprint_bin_break) rowlen %d", rowlen);
332 // 3072 + end of line characters if broken at 8 bits
333 dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t));
334 if (dest == NULL) return;
337 memset(dest, 0x00, sizeof(dest));
339 // loop through the out_index to make sure we don't go too far
340 for (out_index=0; out_index < rowlen-1; out_index++) {
342 sprintf(dest++, "%u", src[in_index]);
343 // check if a line break is needed and we have room to print it in our array
344 if ( (breaks > 0) && !((in_index+1) % breaks) && (out_index+1 != rowlen) ) {
345 // increment and print line break
347 sprintf(dest++, "%s","\n");
352 sprintf(dest++, "%u", src[in_index]);
356 char *sprint_bin(const uint8_t *data
, const size_t len
) {
357 return sprint_bin_break(data
, len
, 0);
360 char *sprint_hex_ascii(const uint8_t *data
, const size_t len
) {
361 static char buf
[UTIL_BUFFER_SIZE_SPRINT
];
363 memset(buf
, 0x00, UTIL_BUFFER_SIZE_SPRINT
);
364 size_t max_len
= (len
> 1010) ? 1010 : len
;
366 snprintf(tmp
, UTIL_BUFFER_SIZE_SPRINT
, "%s| ", sprint_hex(data
, max_len
));
369 size_t pos
= (max_len
* 3) + 2;
371 while (i
< max_len
) {
374 if ((c
< 32) || (c
== 127))
377 sprintf(tmp
+ pos
+ i
, "%c", c
);
383 char *sprint_ascii_ex(const uint8_t *data
, const size_t len
, const size_t min_str_len
) {
384 static char buf
[UTIL_BUFFER_SIZE_SPRINT
];
386 memset(buf
, 0x00, UTIL_BUFFER_SIZE_SPRINT
);
387 size_t max_len
= (len
> 1010) ? 1010 : len
;
389 while (i
< max_len
) {
391 tmp
[i
] = ((c
< 32) || (c
== 127)) ? '.' : c
;
395 size_t m
= min_str_len
> i
? min_str_len
: 0;
401 char *sprint_ascii(const uint8_t *data
, const size_t len
) {
402 return sprint_ascii_ex(data
, len
, 0);
405 int hex_to_bytes(const char *hexValue
, uint8_t *bytesValue
, size_t maxBytesValueLen
) {
408 int bytesValueLen
= 0;
409 while (hexValue
[indx
]) {
410 if (hexValue
[indx
] == '\t' || hexValue
[indx
] == ' ') {
415 if (isxdigit(hexValue
[indx
])) {
416 buf
[strlen(buf
)] = hexValue
[indx
];
418 // if we have symbols other than spaces and hex
422 if (maxBytesValueLen
&& bytesValueLen
>= maxBytesValueLen
) {
423 // if we dont have space in buffer and have symbols to translate
427 if (strlen(buf
) >= 2) {
429 sscanf(buf
, "%x", &temp
);
430 bytesValue
[bytesValueLen
] = (uint8_t)(temp
& 0xff);
431 memset(buf
, 0, sizeof(buf
));
439 //error when not completed hex bytes
442 return bytesValueLen
;
445 // takes a number (uint64_t) and creates a binarray in dest.
446 void num_to_bytebits(uint64_t n
, size_t len
, uint8_t *dest
) {
453 //least significant bit first
454 void num_to_bytebitsLSBF(uint64_t n
, size_t len
, uint8_t *dest
) {
455 for (size_t i
= 0 ; i
< len
; ++i
) {
461 void bytes_to_bytebits(void *src
, size_t srclen
, void *dest
) {
463 uint8_t *s
= (uint8_t *)src
;
464 uint8_t *d
= (uint8_t *)dest
;
466 uint32_t i
= srclen
* 8;
468 uint8_t b
= s
[srclen
];
469 d
[--i
] = (b
>> 0) & 1;
470 d
[--i
] = (b
>> 1) & 1;
471 d
[--i
] = (b
>> 2) & 1;
472 d
[--i
] = (b
>> 3) & 1;
473 d
[--i
] = (b
>> 4) & 1;
474 d
[--i
] = (b
>> 5) & 1;
475 d
[--i
] = (b
>> 6) & 1;
476 d
[--i
] = (b
>> 7) & 1;
480 // aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
482 // hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
483 // up to 64 bytes or 512 bits
484 uint8_t *SwapEndian64(const uint8_t *src
, const size_t len
, const uint8_t blockSize
) {
485 static uint8_t buf
[64];
486 memset(buf
, 0x00, 64);
488 for (uint8_t block
= 0; block
< (uint8_t)(len
/ blockSize
); block
++) {
489 for (size_t i
= 0; i
< blockSize
; i
++) {
490 tmp
[i
+ (blockSize
* block
)] = src
[(blockSize
- 1 - i
) + (blockSize
* block
)];
496 // takes a uint8_t src array, for len items and reverses the byte order in blocksizes (8,16,32,64),
497 // returns: the dest array contains the reordered src array.
498 void SwapEndian64ex(const uint8_t *src
, const size_t len
, const uint8_t blockSize
, uint8_t *dest
) {
499 for (uint8_t block
= 0; block
< (uint8_t)(len
/ blockSize
); block
++) {
500 for (size_t i
= 0; i
< blockSize
; i
++) {
501 dest
[i
+ (blockSize
* block
)] = src
[(blockSize
- 1 - i
) + (blockSize
* block
)];
506 // -------------------------------------------------------------------------
507 // string parameters lib
508 // -------------------------------------------------------------------------
510 // -------------------------------------------------------------------------
512 // bg, en - symbol numbers in param line of beginning and ending parameter
513 // paramnum - param number (from 0)
514 // -------------------------------------------------------------------------
515 int param_getptr(const char *line
, int *bg
, int *en
, int paramnum
) {
517 int len
= strlen(line
);
523 while (line
[*bg
] == ' ' || line
[*bg
] == '\t')(*bg
)++;
528 for (i
= 0; i
< paramnum
; i
++) {
529 while (line
[*bg
] != ' ' && line
[*bg
] != '\t' && line
[*bg
] != '\0')(*bg
)++;
530 while (line
[*bg
] == ' ' || line
[*bg
] == '\t')(*bg
)++;
532 if (line
[*bg
] == '\0') return 1;
536 while (line
[*en
] != ' ' && line
[*en
] != '\t' && line
[*en
] != '\0')(*en
)++;
543 int param_getlength(const char *line
, int paramnum
) {
546 if (param_getptr(line
, &bg
, &en
, paramnum
)) return 0;
551 char param_getchar(const char *line
, int paramnum
) {
552 return param_getchar_indx(line
, 0, paramnum
);
555 char param_getchar_indx(const char *line
, int indx
, int paramnum
) {
558 if (param_getptr(line
, &bg
, &en
, paramnum
)) return 0x00;
563 return line
[bg
+ indx
];
566 uint8_t param_get8(const char *line
, int paramnum
) {
567 return param_get8ex(line
, paramnum
, 0, 10);
571 * @brief Reads a decimal integer (actually, 0-254, not 255)
574 * @return -1 if error
576 uint8_t param_getdec(const char *line
, int paramnum
, uint8_t *destination
) {
577 uint8_t val
= param_get8ex(line
, paramnum
, 255, 10);
578 if ((int8_t) val
== -1) return 1;
579 (*destination
) = val
;
583 * @brief Checks if param is decimal
588 uint8_t param_isdec(const char *line
, int paramnum
) {
590 //TODO, check more thorougly
591 if (!param_getptr(line
, &bg
, &en
, paramnum
)) return 1;
592 // return strtoul(&line[bg], NULL, 10) & 0xff;
597 uint8_t param_get8ex(const char *line
, int paramnum
, int deflt
, int base
) {
599 if (!param_getptr(line
, &bg
, &en
, paramnum
))
600 return strtoul(&line
[bg
], NULL
, base
) & 0xff;
605 uint32_t param_get32ex(const char *line
, int paramnum
, int deflt
, int base
) {
607 if (!param_getptr(line
, &bg
, &en
, paramnum
))
608 return strtoul(&line
[bg
], NULL
, base
);
613 uint64_t param_get64ex(const char *line
, int paramnum
, int deflt
, int base
) {
615 if (!param_getptr(line
, &bg
, &en
, paramnum
))
616 return strtoull(&line
[bg
], NULL
, base
);
621 float param_getfloat(const char *line
, int paramnum
, float deflt
) {
623 if (!param_getptr(line
, &bg
, &en
, paramnum
))
624 return strtof(&line
[bg
], NULL
);
629 int param_gethex(const char *line
, int paramnum
, uint8_t *data
, int hexcnt
) {
633 if (hexcnt
& 1) return 1;
635 if (param_getptr(line
, &bg
, &en
, paramnum
)) return 1;
637 if (en
- bg
+ 1 != hexcnt
) return 1;
639 for (i
= 0; i
< hexcnt
; i
+= 2) {
640 if (!(isxdigit(line
[bg
+ i
]) && isxdigit(line
[bg
+ i
+ 1]))) return 1;
642 sscanf((char[]) {line
[bg
+ i
], line
[bg
+ i
+ 1], 0}, "%X", &temp
);
643 data
[i
/ 2] = temp
& 0xff;
648 int param_gethex_ex(const char *line
, int paramnum
, uint8_t *data
, int *hexcnt
) {
652 if (param_getptr(line
, &bg
, &en
, paramnum
)) return 1;
654 *hexcnt
= en
- bg
+ 1;
655 if (*hexcnt
% 2) //error if not complete hex bytes
658 for (i
= 0; i
< *hexcnt
; i
+= 2) {
659 if (!(isxdigit(line
[bg
+ i
]) && isxdigit(line
[bg
+ i
+ 1]))) return 1;
661 sscanf((char[]) {line
[bg
+ i
], line
[bg
+ i
+ 1], 0}, "%X", &temp
);
662 data
[i
/ 2] = temp
& 0xff;
668 int param_gethex_to_eol(const char *line
, int paramnum
, uint8_t *data
, int maxdatalen
, int *datalen
) {
673 if (param_getptr(line
, &bg
, &en
, paramnum
)) return 1;
679 if (line
[indx
] == '\t' || line
[indx
] == ' ') {
684 if (isxdigit(line
[indx
])) {
685 buf
[strlen(buf
) + 1] = 0x00;
686 buf
[strlen(buf
)] = line
[indx
];
688 // if we have symbols other than spaces and hex
692 if (*datalen
>= maxdatalen
) {
693 // if we dont have space in buffer and have symbols to translate
697 if (strlen(buf
) >= 2) {
698 sscanf(buf
, "%x", &temp
);
699 data
[*datalen
] = (uint8_t)(temp
& 0xff);
708 //error when not completed hex bytes
714 int param_getbin_to_eol(const char *line
, int paramnum
, uint8_t *data
, int maxdatalen
, int *datalen
) {
716 if (param_getptr(line
, &bg
, &en
, paramnum
)) {
724 if (line
[indx
] == '\t' || line
[indx
] == ' ') {
729 if (line
[indx
] == '0' || line
[indx
] == '1') {
730 buf
[strlen(buf
) + 1] = 0x00;
731 buf
[strlen(buf
)] = line
[indx
];
733 // if we have symbols other than spaces and 0/1
737 if (*datalen
>= maxdatalen
) {
738 // if we dont have space in buffer and have symbols to translate
742 if (strlen(buf
) > 0) {
744 sscanf(buf
, "%d", &temp
);
745 data
[*datalen
] = (uint8_t)(temp
& 0xff);
755 int param_getstr(const char *line
, int paramnum
, char *str
, size_t buffersize
) {
758 if (param_getptr(line
, &bg
, &en
, paramnum
)) {
762 // Prevent out of bounds errors
763 if (en
- bg
+ 1 >= buffersize
) {
764 PrintAndLogEx(ERR
, "out of bounds error: want %d bytes have %zu bytes\n", en
- bg
+ 1 + 1, buffersize
);
768 memcpy(str
, line
+ bg
, en
- bg
+ 1);
769 str
[en
- bg
+ 1] = 0;
775 The following methods comes from Rfidler sourcecode.
776 https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/
778 // convert hex to sequence of 0/1 bit values
779 // returns number of bits converted
780 int hextobinarray(char *target
, char *source
) {
781 int length
, i
, count
= 0;
782 char *start
= source
;
783 length
= strlen(source
);
784 // process 4 bits (1 hex digit) at a time
786 char x
= *(source
++);
788 if (x
>= 'a' && x
<= 'f')
790 // convert to numeric value
791 if (x
>= '0' && x
<= '9')
793 else if (x
>= 'A' && x
<= 'F')
796 PrintAndLogEx(INFO
, "(hextobinarray) discovered unknown character %c %d at idx %d of %s", x
, x
, (int16_t)(source
- start
), start
);
800 for (i
= 0 ; i
< 4 ; ++i
, ++count
)
801 *(target
++) = (x
>> (3 - i
)) & 1;
807 // convert hex to human readable binary string
808 int hextobinstring(char *target
, char *source
) {
809 int length
= hextobinarray(target
, source
);
812 binarraytobinstring(target
, target
, length
);
816 // convert binary array of 0x00/0x01 values to hex
817 // return number of bits converted
818 int binarraytohex(char *target
, const size_t targetlen
, char *source
, size_t srclen
) {
819 uint8_t i
= 0, x
= 0;
820 uint32_t t
= 0; // written target chars
821 uint32_t r
= 0; // consumed bits
822 uint8_t w
= 0; // wrong bits separator printed
823 for (size_t s
= 0 ; s
< srclen
; s
++) {
824 if ((source
[s
] == 0) || (source
[s
] == 1)) {
826 x
+= (source
[s
] << (3 - i
));
829 if (t
>= targetlen
- 2) {
832 sprintf(target
+ t
, "%X", x
);
840 if (t
>= targetlen
- 5) {
843 sprintf(target
+ t
, "%X[%i]", x
, i
);
851 if (t
>= targetlen
- 2) {
854 sprintf(target
+ t
, " ");
863 // convert binary array to human readable binary
864 void binarraytobinstring(char *target
, char *source
, int length
) {
865 for (int i
= 0 ; i
< length
; ++i
)
866 *(target
++) = *(source
++) + '0';
870 int binstring2binarray(uint8_t *target
, char *source
, int length
) {
872 char *start
= source
;
874 char x
= *(source
++);
875 // convert from binary value
876 if (x
>= '0' && x
<= '1')
879 PrintAndLogEx(WARNING
, "(binstring2binarray) discovered unknown character %c %d at idx %d of %s", x
, x
, (int16_t)(source
- start
), start
);
888 // return parity bit required to match type
889 uint8_t GetParity(uint8_t *bits
, uint8_t type
, int length
) {
891 for (x
= 0 ; length
> 0 ; --length
)
892 x
+= bits
[length
- 1];
897 // add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
898 void wiegand_add_parity(uint8_t *target
, uint8_t *source
, uint8_t length
) {
899 *(target
++) = GetParity(source
, EVEN
, length
/ 2);
900 memcpy(target
, source
, length
);
902 *(target
) = GetParity(source
+ length
/ 2, ODD
, length
/ 2);
905 // add HID parity to binary array: ODD prefix for 1st half of ID, EVEN suffix for 2nd half
906 void wiegand_add_parity_swapped(uint8_t *target
, uint8_t *source
, uint8_t length
) {
907 *(target
++) = GetParity(source
, ODD
, length
/ 2);
908 memcpy(target
, source
, length
);
910 *(target
) = GetParity(source
+ length
/ 2, EVEN
, length
/ 2);
913 // Pack a bitarray into a uint32_t.
914 uint32_t PackBits(uint8_t start
, uint8_t len
, uint8_t *bits
) {
916 if (len
> 32) return 0;
922 for (; j
>= 0; --j
, ++i
)
928 uint64_t HornerScheme(uint64_t num
, uint64_t divider
, uint64_t factor
) {
929 uint64_t remaind
= 0, quotient
= 0, result
= 0;
930 remaind
= num
% divider
;
931 quotient
= num
/ divider
;
932 if (!(quotient
== 0 && remaind
== 0))
933 result
+= HornerScheme(quotient
, divider
, factor
) * factor
+ remaind
;
937 // determine number of logical CPU cores (use for multithreaded functions)
940 #include <sysinfoapi.h>
942 GetSystemInfo(&sysinfo
);
943 return sysinfo
.dwNumberOfProcessors
;
946 int count
= sysconf(_SC_NPROCESSORS_ONLN
);
953 void str_lower(char *s
) {
954 for (size_t i
= 0; i
< strlen(s
); i
++)
955 s
[i
] = tolower(s
[i
]);
958 // check for prefix in string
959 bool str_startswith(const char *s
, const char *pre
) {
960 return strncmp(pre
, s
, strlen(pre
)) == 0;
963 // check for suffix in string
964 bool str_endswith(const char *s
, const char *suffix
) {
965 size_t ls
= strlen(s
);
966 size_t lsuffix
= strlen(suffix
);
968 return strncmp(suffix
, s
+ (ls
- lsuffix
), lsuffix
) == 0;
973 // Replace unprintable characters with a dot in char buffer
974 void clean_ascii(unsigned char *buf
, size_t len
) {
975 for (size_t i
= 0; i
< len
; i
++) {
976 if (!isprint(buf
[i
]))
981 // replace \r \n to \0
982 void strcleanrn(char *buf
, size_t len
) {
983 strcreplace(buf
, len
, '\n', '\0');
984 strcreplace(buf
, len
, '\r', '\0');
987 // replace char in buffer
988 void strcreplace(char *buf
, size_t len
, char from
, char to
) {
989 for (size_t i
= 0; i
< len
; i
++) {
996 char *str_dup(const char *src
) {
997 return str_ndup(src
, strlen(src
));
999 char *str_ndup(const char *src
, size_t len
) {
1001 char *dest
= (char *) calloc(len
+ 1, sizeof(uint8_t));
1003 memcpy(dest
, src
, len
);
1010 * Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers
1011 * one nibble at a time.
1013 * Returns the number of nibbles (4 bits) entered.
1015 int hexstring_to_u96(uint32_t *hi2
, uint32_t *hi
, uint32_t *lo
, const char *str
) {
1016 uint32_t n
= 0, i
= 0;
1018 while (sscanf(&str
[i
++], "%1x", &n
) == 1) {
1019 *hi2
= (*hi2
<< 4) | (*hi
>> 28);
1020 *hi
= (*hi
<< 4) | (*lo
>> 28);
1021 *lo
= (*lo
<< 4) | (n
& 0xf);
1027 * Converts a binary string to component "hi2", "hi" and "lo" 32-bit integers,
1028 * one bit at a time.
1030 * Returns the number of bits entered.
1032 int binstring_to_u96(uint32_t *hi2
, uint32_t *hi
, uint32_t *lo
, const char *str
) {
1033 uint32_t n
= 0, i
= 0;
1037 int res
= sscanf(&str
[i
], "%1u", &n
);
1038 if ((res
!= 1) || (n
> 1))
1041 *hi2
= (*hi2
<< 1) | (*hi
>> 31);
1042 *hi
= (*hi
<< 1) | (*lo
>> 31);
1043 *lo
= (*lo
<< 1) | (n
& 0x1);
1052 * Converts a binary array to component "hi2", "hi" and "lo" 32-bit integers,
1053 * one bit at a time.
1055 * Returns the number of bits entered.
1057 int binarray_to_u96(uint32_t *hi2
, uint32_t *hi
, uint32_t *lo
, uint8_t *arr
, int arrlen
) {
1059 for (; i
< arrlen
; i
++) {
1064 *hi2
= (*hi2
<< 1) | (*hi
>> 31);
1065 *hi
= (*hi
<< 1) | (*lo
>> 31);
1066 *lo
= (*lo
<< 1) | (n
& 0x1);
1071 inline uint32_t bitcount32(uint32_t a
) {
1072 #if defined __GNUC__
1073 return __builtin_popcountl(a
);
1075 a
= a
- ((a
>> 1) & 0x55555555);
1076 a
= (a
& 0x33333333) + ((a
>> 2) & 0x33333333);
1077 return (((a
+ (a
>> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
1081 inline uint64_t bitcount64(uint64_t a
) {
1082 #if defined __GNUC__
1083 return __builtin_popcountll(a
);
1085 PrintAndLogEx(FAILED
, "Was not compiled with fct bitcount64");
1090 inline uint32_t leadingzeros32(uint32_t a
) {
1091 #if defined __GNUC__
1092 return __builtin_clzl(a
);
1094 PrintAndLogEx(FAILED
, "Was not compiled with fct bitcount64");
1099 inline uint64_t leadingzeros64(uint64_t a
) {
1100 #if defined __GNUC__
1101 return __builtin_clzll(a
);
1103 PrintAndLogEx(FAILED
, "Was not compiled with fct bitcount64");