From d42eb52a2ef3769be7e515d946d474303b60aa4c Mon Sep 17 00:00:00 2001 From: Pin Lin Date: Sun, 16 Apr 2023 04:27:32 +0800 Subject: [PATCH] Remove unused files --- 0xcafec0de.bin | Bin 45006 -> 0 bytes Makefile | 41 +- bintotxt.py | 16 - libnfc_crypto1_crack.c | 738 ----------------------------- pwpiwi_proxmark3_hard_nested.patch | 632 ------------------------ solve_bs.c | 145 ------ solve_piwi.c | 101 ---- solve_piwi_bs.c | 147 ------ txttobin.py | 29 -- 9 files changed, 1 insertion(+), 1848 deletions(-) delete mode 100644 0xcafec0de.bin delete mode 100644 bintotxt.py delete mode 100755 libnfc_crypto1_crack.c delete mode 100644 pwpiwi_proxmark3_hard_nested.patch delete mode 100644 solve_bs.c delete mode 100644 solve_piwi.c delete mode 100644 solve_piwi_bs.c delete mode 100644 txttobin.py diff --git a/0xcafec0de.bin b/0xcafec0de.bin deleted file mode 100644 index 8139d18000dd43fb74b20dc5de878161d61c4a5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45006 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�@Zxky1#)~0!k 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 diff --git a/Makefile b/Makefile index 08bf9b9..12943ef 100755 --- a/Makefile +++ b/Makefile @@ -22,44 +22,5 @@ holycard_collect: holycard_solve: $(CC) $(CFLAGS) $@.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -o $@ -lpthread -lm $(LDFLAGS) -solve_bs: - $(CC) $(CFLAGS) $@.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -o $@ -lpthread -lm $(LDFLAGS) - -solve_piwi_bs: - $(CC) $(CFLAGS) $@.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -o $@ -lpthread -lm $(LDFLAGS) - -solve_piwi: - $(CC) $(CFLAGS) $@.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -o $@ -lpthread $(LDFLAGS) - -libnfc_crypto1_crack: - $(CC) $(CFLAGS) $@.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -o $@ -lpthread -lnfc -lm $(LDFLAGS) - clean: - rm -f solve.so solve_bs solve_piwi_bs solve_piwi libnfc_crypto1_crack holycard_collect holycard_solve - -# Windows cross compilation -MINGW32 = i686-w64-mingw32-gcc -MINGW64 = x86_64-w64-mingw32-gcc -# solve.c code cannot be compiled on windows without patching the includes - -WIN32EXES = solve_piwi_bs32.exe solve_piwi32.exe libnfc_crypto1_crack32.exe -win32: $(WIN32EXES) -win32_clean: - rm -f $(WIN32EXES) - -WIN64EXES = solve_piwi_bs64.exe solve_piwi64.exe libnfc_crypto1_crack64.exe -win64: $(WIN64EXES) -win64_clean: - rm -f $(WIN64EXES) - -solve_piwi_bs32.exe: - $(MINGW32) $(CFLAGS) solve_piwi_bs.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -static -m32 -o $@ -lpthread - -solve_piwi_bs64.exe: - $(MINGW64) $(CFLAGS) solve_piwi_bs.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -static -o $@ -lpthread - -solve_piwi32.exe: - $(MINGW32) $(CFLAGS) solve_piwi.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -static -m32 -o $@ -lpthread - -solve_piwi64.exe: - $(MINGW64) $(CFLAGS) solve_piwi.c $(CRYPTO1_BS) $(CRAPTO1) ${CRAPTEV1} -static -o $@ -lpthread + rm -f solve.so holycard_collect holycard_solve diff --git a/bintotxt.py b/bintotxt.py deleted file mode 100644 index 7631e07..0000000 --- a/bintotxt.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys -data = file(sys.argv[1], 'rb').read() -uid = data[0:4] - -def parity(x): - return ("{0:08b}".format(x).count('1') & 1) - -for idx in range(6, len(data), 9): - n = data[idx:idx+8] - p = data[idx+8] - nonce_string = [ "%02x" % ord(n[i]) - + (' ' if int(x)^parity(ord(n[i])) else '! ') - for i, x in enumerate(("{0:08b}".format(ord(p)))) - ] - print ''.join(nonce_string[:4]) - print ''.join(nonce_string[4:]) diff --git a/libnfc_crypto1_crack.c b/libnfc_crypto1_crack.c deleted file mode 100755 index 2015dcb..0000000 --- a/libnfc_crypto1_crack.c +++ /dev/null @@ -1,738 +0,0 @@ -// Copyright (C) 2016 Aram Verstegen -/* - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "crypto1_bs_crack.h" -#define llu PRIu64 - -extern uint64_t * crypto1_create(uint64_t key); -extern uint32_t crypto1_word(uint64_t *, uint32_t, int); -extern uint8_t crypto1_byte(uint64_t*, uint8_t, int); -extern uint32_t prng_successor(uint32_t x, uint32_t n); -extern void crypto1_destroy(uint64_t*); - -#define MC_AUTH_A 0x60 -#define MC_AUTH_B 0x61 - -nfc_device* pnd; -nfc_target target; -typedef uint8_t byte_t; - -uint8_t oddparity(const uint8_t bt) -{ - // cf http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel - return (0x9669 >> ((bt ^(bt >> 4)) & 0xF)) & 1; -} - - -long long unsigned int bytes_to_num(uint8_t *src, uint32_t len) -{ - uint64_t num = 0; - while (len--) { - num = (num << 8) | (*src); - src++; - } - return num; -} - -// Sectors 0 to 31 have 4 blocks per sector. -// Sectors 32 to 39 have 16 blocks per sector. -uint8_t block_to_sector(uint8_t block) -{ - uint8_t sector; - if(block < 128) { - return block >> 2; - } - block -= 128; - return 32 + (block >> 4); -} - -static nfc_context *context; - -#define MAX_FRAME_LEN 264 - -uint64_t *nonces = NULL; -size_t nonces_collected; - -enum { - OK, - ERROR, - KEY_WRONG, -}; - -#define VT100_cleareol "\r\33[2K" - -// Almost entirely based on code from Mifare Offline Cracker (MFOC) by Nethemba, cheers guys! :) -int nested_auth(uint32_t uid, uint64_t known_key, uint8_t ab_key, uint8_t for_block, uint8_t target_block, uint8_t target_key, FILE* fp) -{ - uint64_t *pcs; - - // Possible key counter, just continue with a previous "session" - uint8_t Nr[4] = { 0x00, 0x00, 0x00, 0x00 }; // Reader nonce - uint8_t Cmd[4] = { 0x00, 0x00, 0x00, 0x00 }; - - uint8_t ArEnc[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t ArEncPar[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - uint8_t Rx[MAX_FRAME_LEN]; // Tag response - uint8_t RxPar[MAX_FRAME_LEN]; // Tag response - - uint32_t Nt; - - int i; - - // Prepare AUTH command - Cmd[0] = ab_key; - Cmd[1] = for_block; - iso14443a_crc_append(Cmd, 2); - - // We need full control over the CRC - if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) { - nfc_perror(pnd, "nfc_device_set_property_bool crc"); - return ERROR; - } - - // Request plain tag-nonce - // TODO: Set NP_EASY_FRAMING option only once if possible - if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) { - nfc_perror(pnd, "nfc_device_set_property_bool framing"); - return ERROR; - } - - if (nfc_initiator_transceive_bytes(pnd, Cmd, 4, Rx, sizeof(Rx), 0) < 0) { - fprintf(stdout, "Error while requesting plain tag-nonce "); - return ERROR; - } - - if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) { - nfc_perror(pnd, "nfc_device_set_property_bool"); - return ERROR; - } - - // Save the tag nonce (Nt) - Nt = bytes_to_num(Rx, 4); - - // Init the cipher with key {0..47} bits - pcs = crypto1_create(known_key); - - // Load (plain) uid^nt into the cipher {48..79} bits - crypto1_word(pcs, bytes_to_num(Rx, 4) ^ uid, 0); - - // Generate (encrypted) nr+parity by loading it into the cipher - for (i = 0; i < 4; i++) { - // Load in, and encrypt the reader nonce (Nr) - ArEnc[i] = crypto1_byte(pcs, Nr[i], 0) ^ Nr[i]; - ArEncPar[i] = filter(*pcs) ^ oddparity(Nr[i]); - } - - // Skip 32 bits in the pseudo random generator - Nt = prng_successor(Nt, 32); - - // Generate reader-answer from tag-nonce - for (i = 4; i < 8; i++) { - // Get the next random byte - Nt = prng_successor(Nt, 8); - // Encrypt the reader-answer (Nt' = suc2(Nt)) - ArEnc[i] = crypto1_byte(pcs, 0x00, 0) ^(Nt & 0xff); - ArEncPar[i] = filter(*pcs) ^ oddparity(Nt); - } - - // Finally we want to send arbitrary parity bits - if (nfc_device_set_property_bool(pnd, NP_HANDLE_PARITY, false) < 0) { - nfc_perror(pnd, "nfc_device_set_property_bool parity "); - return 1; - } - - // Transmit reader-answer - int res; - if (((res = nfc_initiator_transceive_bits(pnd, ArEnc, 64, ArEncPar, Rx, sizeof(Rx), RxPar)) < 0) || (res != 32)) { - fprintf(stderr, "Reader-answer transfer error, exiting.. "); - return KEY_WRONG; - } - - // Decrypt the tag answer and verify that suc3(Nt) is At - Nt = prng_successor(Nt, 32); - - if (!((crypto1_word(pcs, 0x00, 0) ^ bytes_to_num(Rx, 4)) == (Nt & 0xFFFFFFFF))) { - fprintf(stderr, "[At] is not Suc3(Nt), something is wrong, exiting.. "); - return ERROR; - } - - Cmd[0] = target_key; - Cmd[1] = target_block; - iso14443a_crc_append(Cmd, 2); - - for (i = 0; i < 4; i++) { - ArEnc[i] = crypto1_byte(pcs, 0, 0) ^ Cmd[i]; - ArEncPar[i] = filter(*pcs) ^ oddparity(Cmd[i]); - } - if (((res = nfc_initiator_transceive_bits(pnd, ArEnc, 32, ArEncPar, Rx, sizeof(Rx), RxPar)) < 0) || (res != 32)) { - fprintf(stderr, "Reader-answer transfer error, exiting.. "); - return ERROR; - } - - if(fp){ - for(i = 0; i < 4; i++){ - fprintf(fp,"%02x", Rx[i]); - if(RxPar[i] != oddparity(Rx[i])){ - fprintf(fp,"! "); - } else { - fprintf(fp," "); - } - } - fprintf(fp, "\n"); - } - if(nonces){ - nonces[nonces_collected] = 0; - for(i = 0; i < 4; i++){ - nonces[nonces_collected] |= ((uint64_t) Rx[i]) << (8*i); - nonces[nonces_collected] |= ((uint64_t) !RxPar[i]) << (32 + (8*i)); - } - nonces_collected++; - } - - crypto1_destroy(pcs); - return OK; -} - -uint32_t uid; -uint32_t **space; -uint64_t found_key; -size_t thread_count; -void* crack_states_thread(void* x){ - const size_t thread_id = (size_t)x; - int j; - for(j = thread_id; space[j * 5]; j += thread_count) { - const uint64_t key = crack_states_bitsliced(space + j * 5); - if(key != -1){ - found_key = key; - break; - } - } - return NULL; -} - -bool stop_collection = false; -#define CUTOFF ((uint64_t) 1<<39) - -void * update_predictions_thread(void* p){ - while(!stop_collection){ - if(nonces && uid){ - if(space){ - craptev1_destroy_space(space); - space = NULL; - } - space = craptev1_get_space(nonces, 95, uid); - } - if(space){ - total_states = craptev1_sizeof_space(space); - } - sleep(1); // We don't need to check this more often than once per second - } - return NULL; -} - -void notify_status_offline(int sig){ - printf(VT100_cleareol "Cracking... %6.02f%%", (100.0*total_states_tested/(total_states))); - alarm(1); - fflush(stdout); - signal(SIGALRM, notify_status_offline); -} - -void notify_status_online(int sig){ - if(!total_states){ - printf(VT100_cleareol "Collected %zu nonces... ", nonces_collected); - } else { - printf(VT100_cleareol "Collected %zu nonces... leftover complexity %"llu" (~2^%0.2f)", nonces_collected, total_states, log(total_states) / log(2)); - char c; - if(scanf("%c", &c) == 1 || total_states < CUTOFF){ - printf(" - initializing brute-force phase...\n"); - alarm(0); - stop_collection = true; - return; - } else { - printf(" - press enter to start brute-force phase"); - } - } - alarm(1); - fflush(stdout); - signal(SIGALRM, notify_status_online); -} - -uint64_t known_key; -uint8_t for_block; -uint8_t ab_key; -uint8_t target_block; -uint8_t target_key; -FILE* fp; - -const nfc_modulation nmMifare = { - .nmt = NMT_ISO14443A, - .nbr = NBR_106, -}; - -void * update_nonces_thread(void* v){ - while(!stop_collection){ - // Configure the CRC and Parity settings - nfc_device_set_property_bool(pnd,NP_HANDLE_CRC,true); - nfc_device_set_property_bool(pnd,NP_HANDLE_PARITY,true); - // Poll for a ISO14443A (MIFARE) tag - if (nfc_initiator_select_passive_target(pnd,nmMifare,NULL,0,&target)) { - nested_auth(uid, known_key, ab_key, for_block, target_block, target_key, fp); - } else { - printf(VT100_cleareol "Don't move the tag!"); - fflush(stdout); - } - } - return NULL; -} - -int main (int argc, const char * argv[]) { - nfc_init(&context); - pnd = nfc_open(context, NULL); - - if (pnd == NULL) { - fprintf(stderr, "No NFC device connection\n"); - return 1; - } - - nfc_initiator_init(pnd); - - nfc_device_set_property_bool(pnd,NP_ACTIVATE_FIELD,false); - // Let the reader only try once to find a tag - nfc_device_set_property_bool(pnd,NP_INFINITE_SELECT,false); - nfc_device_set_property_bool(pnd,NP_HANDLE_CRC,true); - nfc_device_set_property_bool(pnd,NP_HANDLE_PARITY,true); - nfc_device_set_property_bool(pnd,NP_AUTO_ISO14443_4, false); - - uid = 0; - - // Enable field so more power consuming cards can power themselves up - nfc_device_set_property_bool(pnd,NP_ACTIVATE_FIELD,true); - if (nfc_initiator_select_passive_target(pnd,nmMifare,NULL,0,&target)) { - uid = bytes_to_num(target.nti.nai.abtUid,target.nti.nai.szUidLen); - } - - if(!uid){ - fprintf(stderr, "No tag detected!\n"); - // Disconnect from NFC device - nfc_close(pnd); - return 1; - } - - if(argc < 6){ - printf("%s \n", argv[0]); - nfc_close(pnd); - return 1; - } - - known_key = strtoull(argv[1], 0, 16); - for_block = atoi(argv[2]); - ab_key = MC_AUTH_A; - if(argv[3][0] == 'b' || argv[3][0] == 'B'){ - ab_key = MC_AUTH_B; - } - target_block = atoi(argv[4]); - target_key = MC_AUTH_A; - if(argv[5][0] == 'b' || argv[5][0] == 'B'){ - target_key = MC_AUTH_B; - } - switch(nested_auth(uid, known_key, ab_key, for_block, target_block, target_key, NULL)){ - case KEY_WRONG: - printf("%012"PRIx64" doesn't look like the right key %s for block %u (sector %u)\n", known_key, ab_key == MC_AUTH_A ? "A" : "B", for_block, block_to_sector(for_block)); - return 1; - case OK: - break; - case ERROR: - default: - printf("Some other error occurred.\n"); - break; - } - - char filename[21]; - sprintf(filename, "0x%08x_%03u%s.txt", uid, target_block, target_key == MC_AUTH_A ? "A" : "B"); - fp = fopen(filename, "wb"); - - printf("Found tag with uid %04x, collecting nonces for key %s of block %u (sector %u) using known key %s %012"PRIx64" for block %u (sector %u)\n", - uid, target_key == MC_AUTH_A ? "A" : "B", target_block, block_to_sector(target_block), ab_key == MC_AUTH_A ? "A" : "B", known_key, for_block, block_to_sector(for_block)); - nonces_collected = 0; - nonces = malloc(sizeof (uint64_t) << 24); - memset(nonces, 0xff, sizeof (uint64_t) << 24); - - fcntl(0, F_SETFL, O_NONBLOCK); - signal(SIGALRM, notify_status_online); - alarm(1); - pthread_t prediction_thread, nonce_gathering_thread; - pthread_create(&nonce_gathering_thread, NULL, update_nonces_thread, NULL); - pthread_create(&prediction_thread, NULL, update_predictions_thread, NULL); - pthread_join(nonce_gathering_thread, 0); - pthread_join(prediction_thread, 0); - alarm(0); - - if(fp){ - fclose(fp); - } - nfc_close(pnd); - - if(!space){ - space = craptev1_get_space(nonces, 95, uid); - } - if(space){ - total_states = craptev1_sizeof_space(space); - } else { - total_states = 0; - } - if(!total_states){ - fprintf(stderr, "No solution found :(\n"); - return 1; - } - -#ifndef __WIN32 - thread_count = sysconf(_SC_NPROCESSORS_CONF); -#else - thread_count = 1; -#endif - // append some zeroes to the end of the space to make sure threads don't go off into the wild - size_t j = 0; - for(j = 0; space[j]; j+=5){ - } - size_t fill = j + (5*thread_count); - for(; j < fill; j++) { - space[j] = 0; - } - pthread_t threads[thread_count]; - - crypto1_bs_init(); - - uint8_t rollback_byte = **space; - // convert to 32 bit little-endian - crypto1_bs_bitslice_value32(rev32((rollback_byte)), bitsliced_rollback_byte, 8); - - for(size_t tests = 0; tests < NONCE_TESTS; tests++){ - // pre-xor the uid into the decrypted nonces, and also pre-xor the uid parity into the encrypted parity bits - otherwise an exta xor is required in the decryption routine - uint32_t test_nonce = uid^rev32(nonces[tests]); - uint32_t test_parity = (nonces[tests]>>32)^rev32(uid); - test_parity = ((parity(test_parity >> 24 & 0xff) & 1) | (parity(test_parity>>16 & 0xff) & 1)<<1 | (parity(test_parity>>8 & 0xff) & 1)<<2 | (parity(test_parity & 0xff) & 1) << 3); - crypto1_bs_bitslice_value32(test_nonce, bitsliced_encrypted_nonces[tests], 32); - // convert to 32 bit little-endian - crypto1_bs_bitslice_value32(~(test_parity)<<24, bitsliced_encrypted_parity_bits[tests], 4); - } - - printf("Starting %zu threads to test %"llu" states using %u-way bitslicing\n", thread_count, total_states, MAX_BITSLICES); - total_states_tested = 0; - keys_found = 0; - signal(SIGALRM, notify_status_offline); - - notify_status_offline(0); - alarm(1); - - size_t i; - for(i = 0; i < thread_count; i++){ - pthread_create(&threads[i], NULL, crack_states_thread, (void*) i); - } - for(i = 0; i < thread_count; i++){ - pthread_join(threads[i], 0); - } - alarm(0); - printf("\n"); - if(!keys_found){ - fprintf(stderr, "No solution found :(\n"); - return 1; - } else { - printf("Found key: %012"PRIx64"\n", found_key); - } - printf("Tested %"llu" states\n", total_states_tested); - - craptev1_destroy_space(space); - return 0; -} diff --git a/pwpiwi_proxmark3_hard_nested.patch b/pwpiwi_proxmark3_hard_nested.patch deleted file mode 100644 index f4e29c8..0000000 --- a/pwpiwi_proxmark3_hard_nested.patch +++ /dev/null @@ -1,632 +0,0 @@ -Just thought I'd make it clear that this code is GPLv2 licensed here - -- Aram Verstegen - - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS -diff --git a/client/Makefile b/client/Makefile -index 91e595d..dc3557f 100644 ---- a/client/Makefile -+++ b/client/Makefile -@@ -107,6 +107,7 @@ CMDSRCS = nonce2key/crapto1.c\ - aes.c\ - protocols.c\ - sha1.c\ -+ crypto1_bs.c \ - - ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c - ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED -diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c -index b3893ea..bf71a08 100644 ---- a/client/cmdhfmfhard.c -+++ b/client/cmdhfmfhard.c -@@ -20,12 +20,15 @@ - #include - #include - #include -+#include -+#include - #include "proxmark3.h" - #include "cmdmain.h" - #include "ui.h" - #include "util.h" - #include "nonce2key/crapto1.h" - #include "parity.h" -+#include "crypto1_bs.h" - - // uint32_t test_state_odd = 0; - // uint32_t test_state_even = 0; -@@ -88,6 +91,8 @@ typedef struct noncelist { - } noncelist_t; - - -+static size_t nonces_to_bruteforce = 0; -+static noncelistentry_t *brute_force_nonces[256]; - static uint32_t cuid; - static noncelist_t nonces[256]; - static uint8_t best_first_bytes[256]; -@@ -169,6 +174,11 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) - p2->nonce_enc = nonce_enc; - p2->par_enc = par_enc; - -+ if(nonces_to_bruteforce < 256){ -+ brute_force_nonces[nonces_to_bruteforce] = p2; -+ nonces_to_bruteforce++; -+ } -+ - nonces[first_byte].num++; - nonces[first_byte].Sum += evenparity32((nonce_enc & 0x00ff0000) | (par_enc & 0x04)); - nonces[first_byte].updated = true; // indicates that we need to recalculate the Sum(a8) probability for this first byte -@@ -1376,6 +1386,236 @@ static void free_statelist_cache(void) - } - } - -+size_t keys_found = 0; -+size_t bucket_count = 0; -+statelist_t* buckets[128]; -+size_t total_states_tested = 0; -+size_t thread_count = 4; -+ -+// these bitsliced states will hold identical states in all slices -+bitslice_t bitsliced_rollback_byte[ROLLBACK_SIZE]; -+ -+// arrays of bitsliced states with identical values in all slices -+bitslice_t bitsliced_encrypted_nonces[NONCE_TESTS][STATE_SIZE]; -+bitslice_t bitsliced_encrypted_parity_bits[NONCE_TESTS][ROLLBACK_SIZE]; -+ -+#define EXACT_COUNT -+ -+static const uint64_t crack_states_bitsliced(statelist_t *p){ -+ // the idea to roll back the half-states before combining them was suggested/explained to me by bla -+ // first we pre-bitslice all the even state bits and roll them back, then bitslice the odd bits and combine the two in the inner loop -+ uint64_t key = -1; -+#ifdef EXACT_COUNT -+ size_t bucket_states_tested = 0; -+ size_t bucket_size[p->len[EVEN_STATE]/MAX_BITSLICES]; -+#else -+ const size_t bucket_states_tested = (p->len[EVEN_STATE])*(p->len[ODD_STATE]); -+#endif -+ bitslice_t *bitsliced_even_states[p->len[EVEN_STATE]/MAX_BITSLICES]; -+ size_t bitsliced_blocks = 0; -+ uint32_t const * restrict even_end = p->states[EVEN_STATE]+p->len[EVEN_STATE]; -+ // bitslice all the even states -+ for(uint32_t * restrict p_even = p->states[EVEN_STATE]; p_even < even_end; p_even+=MAX_BITSLICES){ -+ bitslice_t * restrict lstate_p = memalign(sizeof(bitslice_t), (STATE_SIZE+ROLLBACK_SIZE)*sizeof(bitslice_t)); -+ memset(lstate_p+1, 0x0, (STATE_SIZE-1)*sizeof(bitslice_t)); // zero even bits -+ // bitslice even half-states -+ const size_t max_slices = (even_end-p_even) < MAX_BITSLICES ? even_end-p_even : MAX_BITSLICES; -+#ifdef EXACT_COUNT -+ bucket_size[bitsliced_blocks] = max_slices; -+#endif -+ for(size_t slice_idx = 0; slice_idx < max_slices; ++slice_idx){ -+ uint32_t e = *(p_even+slice_idx); -+ for(size_t bit_idx = 1; bit_idx < STATE_SIZE; bit_idx+=2, e >>= 1){ -+ // set even bits -+ if(e&1){ -+ lstate_p[bit_idx].bytes64[slice_idx>>6] |= 1ull << (slice_idx&63); -+ } -+ } -+ } -+ // compute the rollback bits -+ for(size_t rollback = 0; rollback < ROLLBACK_SIZE; ++rollback){ -+ // inlined crypto1_bs_lfsr_rollback -+ const bitslice_value_t feedout = lstate_p[0].value; -+ ++lstate_p; -+ const bitslice_value_t ks_bits = crypto1_bs_f20(lstate_p); -+ const bitslice_value_t feedback = (feedout ^ ks_bits ^ lstate_p[47- 5].value ^ lstate_p[47- 9].value ^ -+ lstate_p[47-10].value ^ lstate_p[47-12].value ^ lstate_p[47-14].value ^ -+ lstate_p[47-15].value ^ lstate_p[47-17].value ^ lstate_p[47-19].value ^ -+ lstate_p[47-24].value ^ lstate_p[47-25].value ^ lstate_p[47-27].value ^ -+ lstate_p[47-29].value ^ lstate_p[47-35].value ^ lstate_p[47-39].value ^ -+ lstate_p[47-41].value ^ lstate_p[47-42].value ^ lstate_p[47-43].value); -+ lstate_p[47].value = feedback ^ bitsliced_rollback_byte[rollback].value; -+ } -+ bitsliced_even_states[bitsliced_blocks++] = lstate_p; -+ } -+ // bitslice every odd state to every block of even half-states with half-finished rollback -+ for(uint32_t const * restrict p_odd = p->states[ODD_STATE]; p_odd < p->states[ODD_STATE]+p->len[ODD_STATE]; ++p_odd){ -+ // early abort -+ if(keys_found){ -+ goto out; -+ } -+ -+ // set the odd bits and compute rollback -+ uint64_t o = (uint64_t) *p_odd; -+ lfsr_rollback_byte((struct Crypto1State*) &o, 0, 1); -+ // pre-compute part of the odd feedback bits (minus rollback) -+ bool odd_feedback_bit = parity(o&0x9ce5c); -+ -+ crypto1_bs_rewind_a0(); -+ // set odd bits -+ for(size_t state_idx = 0; state_idx < STATE_SIZE-ROLLBACK_SIZE; o >>= 1, state_idx+=2){ -+ if(o & 1){ -+ state_p[state_idx] = bs_ones; -+ } else { -+ state_p[state_idx] = bs_zeroes; -+ } -+ } -+ const bitslice_value_t odd_feedback = odd_feedback_bit ? bs_ones.value : bs_zeroes.value; -+ -+ for(size_t block_idx = 0; block_idx < bitsliced_blocks; ++block_idx){ -+ const bitslice_t const * restrict bitsliced_even_state = bitsliced_even_states[block_idx]; -+ size_t state_idx; -+ // set even bits -+ for(state_idx = 0; state_idx < STATE_SIZE-ROLLBACK_SIZE; state_idx+=2){ -+ state_p[1+state_idx] = bitsliced_even_state[1+state_idx]; -+ } -+ // set rollback bits -+ uint64_t lo = o; -+ for(; state_idx < STATE_SIZE; lo >>= 1, state_idx+=2){ -+ // set the odd bits and take in the odd rollback bits from the even states -+ if(lo & 1){ -+ state_p[state_idx].value = ~bitsliced_even_state[state_idx].value; -+ } else { -+ state_p[state_idx] = bitsliced_even_state[state_idx]; -+ } -+ -+ // set the even bits and take in the even rollback bits from the odd states -+ if((lo >> 32) & 1){ -+ state_p[1+state_idx].value = ~bitsliced_even_state[1+state_idx].value; -+ } else { -+ state_p[1+state_idx] = bitsliced_even_state[1+state_idx]; -+ } -+ } -+ -+#ifdef EXACT_COUNT -+ bucket_states_tested += bucket_size[block_idx]; -+#endif -+ // pre-compute first keystream and feedback bit vectors -+ const bitslice_value_t ksb = crypto1_bs_f20(state_p); -+ const bitslice_value_t fbb = (odd_feedback ^ state_p[47- 0].value ^ state_p[47- 5].value ^ // take in the even and rollback bits -+ state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^ -+ state_p[47-24].value ^ state_p[47-42].value); -+ -+ // vector to contain test results (1 = passed, 0 = failed) -+ bitslice_t results = bs_ones; -+ -+ for(size_t tests = 0; tests < NONCE_TESTS; ++tests){ -+ size_t parity_bit_idx = 0; -+ bitslice_value_t fb_bits = fbb; -+ bitslice_value_t ks_bits = ksb; -+ state_p = &states[KEYSTREAM_SIZE-1]; -+ bitslice_value_t parity_bit_vector = bs_zeroes.value; -+ -+ // highest bit is transmitted/received first -+ for(int32_t ks_idx = KEYSTREAM_SIZE-1; ks_idx >= 0; --ks_idx, --state_p){ -+ // decrypt nonce bits -+ const bitslice_value_t encrypted_nonce_bit_vector = bitsliced_encrypted_nonces[tests][ks_idx].value; -+ const bitslice_value_t decrypted_nonce_bit_vector = (encrypted_nonce_bit_vector ^ ks_bits); -+ -+ // compute real parity bits on the fly -+ parity_bit_vector ^= decrypted_nonce_bit_vector; -+ -+ // update state -+ state_p[0].value = (fb_bits ^ decrypted_nonce_bit_vector); -+ -+ // compute next keystream bit -+ ks_bits = crypto1_bs_f20(state_p); -+ -+ // for each byte: -+ if((ks_idx&7) == 0){ -+ // get encrypted parity bits -+ const bitslice_value_t encrypted_parity_bit_vector = bitsliced_encrypted_parity_bits[tests][parity_bit_idx++].value; -+ -+ // decrypt parity bits -+ const bitslice_value_t decrypted_parity_bit_vector = (encrypted_parity_bit_vector ^ ks_bits); -+ -+ // compare actual parity bits with decrypted parity bits and take count in results vector -+ results.value &= (parity_bit_vector ^ decrypted_parity_bit_vector); -+ -+ // make sure we still have a match in our set -+ // if(memcmp(&results, &bs_zeroes, sizeof(bitslice_t)) == 0){ -+ -+ // this is much faster on my gcc, because somehow a memcmp needlessly spills/fills all the xmm registers to/from the stack - ??? -+ // the short-circuiting also helps -+ if(results.bytes64[0] == 0 -+#if MAX_BITSLICES > 64 -+ && results.bytes64[1] == 0 -+#endif -+#if MAX_BITSLICES > 128 -+ && results.bytes64[2] == 0 -+ && results.bytes64[3] == 0 -+#endif -+ ){ -+ goto stop_tests; -+ } -+ // this is about as fast but less portable (requires -std=gnu99) -+ // asm goto ("ptest %1, %0\n\t" -+ // "jz %l2" :: "xm" (results.value), "xm" (bs_ones.value) : "cc" : stop_tests); -+ parity_bit_vector = bs_zeroes.value; -+ } -+ // compute next feedback bit vector -+ fb_bits = (state_p[47- 0].value ^ state_p[47- 5].value ^ state_p[47- 9].value ^ -+ state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^ -+ state_p[47-15].value ^ state_p[47-17].value ^ state_p[47-19].value ^ -+ state_p[47-24].value ^ state_p[47-25].value ^ state_p[47-27].value ^ -+ state_p[47-29].value ^ state_p[47-35].value ^ state_p[47-39].value ^ -+ state_p[47-41].value ^ state_p[47-42].value ^ state_p[47-43].value); -+ } -+ } -+ // all nonce tests were successful: we've found the key in this block! -+ state_t keys[MAX_BITSLICES]; -+ crypto1_bs_convert_states(&states[KEYSTREAM_SIZE], keys); -+ for(size_t results_idx = 0; results_idx < MAX_BITSLICES; ++results_idx){ -+ if(get_vector_bit(results_idx, results)){ -+ key = keys[results_idx].value; -+ goto out; -+ } -+ } -+stop_tests: -+ // prepare to set new states -+ crypto1_bs_rewind_a0(); -+ continue; -+ } -+ } -+out: -+ for(size_t block_idx = 0; block_idx < bitsliced_blocks; ++block_idx){ -+ free(bitsliced_even_states[block_idx]-ROLLBACK_SIZE); -+ } -+ __sync_fetch_and_add(&total_states_tested, bucket_states_tested); -+ return key; -+} -+ -+static void* crack_states_thread(void* x){ -+ const size_t thread_id = (size_t)x; -+ size_t current_bucket = thread_id; -+ while(current_bucket < bucket_count){ -+ statelist_t * bucket = buckets[current_bucket]; -+ if(bucket){ -+ const uint64_t key = crack_states_bitsliced(bucket); -+ if(key != -1){ -+ printf("Found key: %012lx\n", key); -+ __sync_fetch_and_add(&keys_found, 1); -+ break; -+ } else if(keys_found){ -+ break; -+ } else { -+ printf("Cracking... %6.02f%%\n", (100.0*total_states_tested/(maximum_states))); -+ } -+ } -+ current_bucket += thread_count; -+ } -+ return NULL; -+} - - static void brute_force(void) - { -@@ -1383,7 +1623,56 @@ static void brute_force(void) - PrintAndLog("Looking for known target key in remaining key space..."); - TestIfKeyExists(known_target_key); - } else { -- PrintAndLog("Brute Force phase is not implemented."); -+ PrintAndLog("Brute force phase starting."); -+ time_t start, end; -+ time(&start); -+ keys_found = 0; -+ -+ crypto1_bs_init(); -+ -+ PrintAndLog("Using %u-bit bitslices", MAX_BITSLICES); -+ PrintAndLog("Bitslicing best_first_byte^uid[3] (rollback byte): %02x...", best_first_bytes[0]^(cuid>>24)); -+ // convert to 32 bit little-endian -+ crypto1_bs_bitslice_value32((best_first_bytes[0]<<24)^cuid, bitsliced_rollback_byte, 8); -+ -+ PrintAndLog("Bitslicing nonces..."); -+ for(size_t tests = 0; tests < NONCE_TESTS; tests++){ -+ uint32_t test_nonce = brute_force_nonces[tests]->nonce_enc; -+ uint8_t test_parity = brute_force_nonces[tests]->par_enc; -+ // pre-xor the uid into the decrypted nonces, and also pre-xor the cuid parity into the encrypted parity bits - otherwise an exta xor is required in the decryption routine -+ crypto1_bs_bitslice_value32(cuid^test_nonce, bitsliced_encrypted_nonces[tests], 32); -+ // convert to 32 bit little-endian -+ crypto1_bs_bitslice_value32(rev32( ~(test_parity ^ ~(parity(cuid>>24 & 0xff)<<3 | parity(cuid>>16 & 0xff)<<2 | parity(cuid>>8 & 0xff)<<1 | parity(cuid&0xff)))), bitsliced_encrypted_parity_bits[tests], 4); -+ } -+ total_states_tested = 0; -+ -+ // count number of states to go -+ bucket_count = 0; -+ for (statelist_t *p = candidates; p != NULL; p = p->next) { -+ buckets[bucket_count] = p; -+ bucket_count++; -+ } -+ -+ // enumerate states using all hardware threads, each thread handles one bucket -+ thread_count = sysconf(_SC_NPROCESSORS_CONF); -+ PrintAndLog("Starting %u cracking threads to search %u buckets containing a total of %lu states...", thread_count, bucket_count, maximum_states); -+ pthread_t threads[thread_count]; -+ for(size_t i = 0; i < thread_count; i++){ -+ pthread_create(&threads[i], NULL, crack_states_thread, (void*) i); -+ } -+ for(size_t i = 0; i < thread_count; i++){ -+ pthread_join(threads[i], 0); -+ } -+ -+ time(&end); -+ unsigned long elapsed_time = difftime(end, start); -+ PrintAndLog("Tested %lu states, found %u keys after %u seconds", total_states_tested, keys_found, elapsed_time); -+ if(!keys_found){ -+ assert(total_states_tested == maximum_states); -+ } -+ // reset this counter for the next call -+ -+ nonces_to_bruteforce = 0; - } - - } diff --git a/solve_bs.c b/solve_bs.c deleted file mode 100644 index bf14d9a..0000000 --- a/solve_bs.c +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "craptev1.h" -#include "crypto1_bs.h" -#include "crypto1_bs_crack.h" -#include -#include -#define __STDC_FORMAT_MACROS -#define llx PRIx64 -#define lli PRIi64 -#define llu PRIu64 -#define lu PRIu32 -#define VT100_cleareol "\r\33[2K" - -uint32_t **space; -uint8_t thread_count = 1; - -uint64_t *readnonces(char* fname) { - int i, j; - FILE *f = fopen(fname, "r"); - if (f == NULL) { - fprintf(stderr, "Cannot open file.\n"); - exit(EXIT_FAILURE); - } - uint64_t *nonces = malloc(sizeof (uint64_t) << 24); - uint32_t nt; - char par; - - i = 0; - while(!feof(f)){ - nonces[i] = 0; - for(j = 0; j < 32; j += 8) { - if(2 != fscanf(f, "%02x%c ", &nt, &par)) { - fprintf(stderr, "Input format error at line:%d\n", i); - fflush(stderr); - exit(EXIT_FAILURE); - } - nonces[i] |= nt << j | (uint64_t)((par == '!') ^ parity(nt)) << (32 + j); - } - i++; - } - nonces[i] = -1; - fclose(f); - return nonces; -} - -void* crack_states_thread(void* x){ - const size_t thread_id = (size_t)x; - int j; - for(j = thread_id; space[j * 5]; j += thread_count) { - const uint64_t key = crack_states_bitsliced(space + j * 5); - if(key != -1){ - printf("Found key: %012"llx"\n", key); - break; - } else if(keys_found){ - break; - } - } - return NULL; -} - -void notify_status_offline(int sig){ - printf(VT100_cleareol "Cracking... %6.02f%%", (100.0*total_states_tested/(total_states))); - alarm(1); - fflush(stdout); - signal(SIGALRM, notify_status_offline); -} - -int main(int argc, char* argv[]){ - if(argc != 3){ - printf("Usage: %s \n", argv[0]); - return -1; - } - printf("Reading nonces...\n"); - uint64_t *nonces = readnonces(argv[1]); - uint32_t uid = strtoul(argv[2], NULL, 16); - printf("Deriving search space...\n"); - space = craptev1_get_space(nonces, 95, uid); - total_states = craptev1_sizeof_space(space); - -#ifndef __WIN32 - thread_count = sysconf(_SC_NPROCESSORS_CONF); -#else - thread_count = 1; -#endif - // append some zeroes to the end of the space to make sure threads don't go off into the wild - size_t j = 0; - for(j = 0; space[j]; j+=5){ - } - size_t fill = j + (5*thread_count); - for(; j < fill; j++) { - space[j] = 0; - } - pthread_t threads[thread_count]; - size_t i; - - printf("Initializing BS crypto-1\n"); - crypto1_bs_init(); - printf("Using %u-bit bitslices\n", MAX_BITSLICES); - - uint8_t rollback_byte = **space; - printf("Bitslicing rollback byte: %02x...\n", rollback_byte); - // convert to 32 bit little-endian - crypto1_bs_bitslice_value32(rev32((rollback_byte)), bitsliced_rollback_byte, 8); - - printf("Bitslicing nonces...\n"); - for(size_t tests = 0; tests < NONCE_TESTS; tests++){ - // pre-xor the uid into the decrypted nonces, and also pre-xor the uid parity into the encrypted parity bits - otherwise an exta xor is required in the decryption routine - uint32_t test_nonce = uid^rev32(nonces[tests]); - uint32_t test_parity = (nonces[tests]>>32)^rev32(uid); - test_parity = ((parity(test_parity >> 24 & 0xff) & 1) | (parity(test_parity>>16 & 0xff) & 1)<<1 | (parity(test_parity>>8 & 0xff) & 1)<<2 | (parity(test_parity & 0xff) & 1) << 3); - crypto1_bs_bitslice_value32(test_nonce, bitsliced_encrypted_nonces[tests], 32); - // convert to 32 bit little-endian - crypto1_bs_bitslice_value32(~(test_parity)<<24, bitsliced_encrypted_parity_bits[tests], 4); - } - - total_states_tested = 0; - keys_found = 0; - - printf("Starting %u threads to test %"llu" (~2^%0.2f) states\n", thread_count, total_states, log(total_states) / log(2)); - - signal(SIGALRM, notify_status_offline); - alarm(1); - - for(i = 0; i < thread_count; i++){ - pthread_create(&threads[i], NULL, crack_states_thread, (void*) i); - } - for(i = 0; i < thread_count; i++){ - pthread_join(threads[i], 0); - } - - alarm(0); - - printf("\nTested %"llu" states\n", total_states_tested); - - if(!keys_found) fprintf(stderr, "No solution found :(\n"); - - craptev1_destroy_space(space); - return 0; -} - diff --git a/solve_piwi.c b/solve_piwi.c deleted file mode 100644 index acc1bc5..0000000 --- a/solve_piwi.c +++ /dev/null @@ -1,101 +0,0 @@ -#include -#include -#include -#include -#include -#include "craptev1.h" -#include -#define __STDC_FORMAT_MACROS -#define llx PRIx64 -#define lli PRIi64 -#define llu PRIu64 -#define lu PRIu32 - -#define rev32(word) (((word & 0xff) << 24) | (((word >> 8) & 0xff) << 16) | (((word >> 16) & 0xff) << 8) | (((word >> 24) & 0xff))) - -uint64_t split(uint8_t p){ - return (((p & 0x8) >>3 )| ((p & 0x4) >> 2) << 8 | ((p & 0x2) >> 1) << 16 | (p & 0x1) << 24 ); -} - -uint32_t uid; -uint64_t *readnonces(char* fname){ - int i; - FILE *f = fopen(fname, "rb"); - uint64_t *nonces = malloc(sizeof (uint64_t) << 24); - if(fread(&uid, 1, 4, f)){ - uid = rev32(uid); - } - fseek(f, 6, SEEK_SET); - i = 0; - uint32_t nt_enc1, nt_enc2; - uint8_t par_enc; - while(!feof(f)){ - if(fread(&nt_enc1, 1, 4, f) && fread(&nt_enc2, 1, 4, f) && fread(&par_enc, 1, 1, f)){ - nonces[i ] = split(~(par_enc >> 4)) << 32 | nt_enc1; - nonces[i+1] = split(~(par_enc & 0xff)) << 32 | nt_enc2; - i += 2; - } - } - nonces[i] = -1; - fclose(f); - return nonces; -} - -uint32_t **space; -uint8_t thread_count = 1; -uint64_t states_tested = 0; -uint64_t total_states; - -void* crack_states_thread(void* x){ - const size_t thread_id = (size_t)x; - int j; - for(j = thread_id; space[j * 5]; j += thread_count) { - uint64_t key = craptev1_search_partition(space + j * 5); - states_tested = total_states - craptev1_sizeof_space(space+j*5); - printf("Cracking... %6.02f%%\n", (100.0*states_tested/(total_states))); - if(key != -1){ - printf("Found key: %012"llx"\n", key); - exit(0); - } - } - return NULL; -} - -int main(int argc, char* argv[]){ - if(argc != 2){ - printf("Usage: %s \n", argv[0]); - return -1; - } - uint64_t *nonces = readnonces(argv[1]); - space = craptev1_get_space(nonces, 95, uid); - total_states = craptev1_sizeof_space(space); - -#ifndef __WIN32 - thread_count = sysconf(_SC_NPROCESSORS_CONF); -#else - thread_count = 1; -#endif - // append some zeroes to the end of the space to make sure threads don't go off into the wild - size_t j = 0; - for(j = 0; space[j]; j+=5){ - } - size_t fill = j + (5*thread_count); - for(; j < fill; j++) { - space[j] = 0; - } - pthread_t threads[thread_count]; - printf("Starting %u threads to test %"llu" states\n", thread_count, total_states); - size_t i; - states_tested = 0; - for(i = 0; i < thread_count; i++){ - pthread_create(&threads[i], NULL, crack_states_thread, (void*) i); - } - for(i = 0; i < thread_count; i++){ - pthread_join(threads[i], 0); - } - printf("Tested %"llu" states\n", states_tested); - - craptev1_destroy_space(space); - return 0; -} - diff --git a/solve_piwi_bs.c b/solve_piwi_bs.c deleted file mode 100644 index 1d149e7..0000000 --- a/solve_piwi_bs.c +++ /dev/null @@ -1,147 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "craptev1.h" -#include "crypto1_bs.h" -#include "crypto1_bs_crack.h" -#include -#include -#define __STDC_FORMAT_MACROS -#define llx PRIx64 -#define lli PRIi64 -#define llu PRIu64 -#define lu PRIu32 -#define VT100_cleareol "\r\33[2K" - -uint64_t split(uint8_t p){ - return (((p & 0x8) >>3 )| ((p & 0x4) >> 2) << 8 | ((p & 0x2) >> 1) << 16 | (p & 0x1) << 24 ); -} - -uint32_t uid; -uint64_t *readnonces(char* fname){ - int i; - FILE *f = fopen(fname, "rb"); - if (f == NULL) { - fprintf(stderr, "Cannot open file.\n"); - exit(EXIT_FAILURE); - } - uint64_t *nonces = malloc(sizeof (uint64_t) << 24); - if(fread(&uid, 1, 4, f)){ - uid = rev32(uid); - } - fseek(f, 6, SEEK_SET); - i = 0; - while(!feof(f)){ - uint32_t nt_enc1, nt_enc2; - uint8_t par_enc; - if(fread(&nt_enc1, 1, 4, f) && fread(&nt_enc2, 1, 4, f) && fread(&par_enc, 1, 1, f)){ - nonces[i ] = split(~(par_enc >> 4)) << 32 | nt_enc1; - nonces[i+1] = split(~(par_enc & 0xff)) << 32 | nt_enc2; - i += 2; - } - } - nonces[i] = -1; - fclose(f); - return nonces; -} - -uint32_t **space; -uint8_t thread_count = 1; - -void* crack_states_thread(void* x){ - const size_t thread_id = (size_t)x; - int j; - for(j = thread_id; space[j * 5]; j += thread_count) { - const uint64_t key = crack_states_bitsliced(space + j * 5); - if(key != -1){ - printf("Found key: %012"llx"\n", key); - break; - } else if(keys_found){ - break; - } - } - return NULL; -} - -void notify_status_offline(int sig){ - printf(VT100_cleareol "Cracking... %6.02f%%", (100.0*total_states_tested/(total_states))); - alarm(1); - fflush(stdout); - signal(SIGALRM, notify_status_offline); -} - -int main(int argc, char* argv[]){ - if(argc != 2){ - printf("Usage: %s \n", argv[0]); - return -1; - } - printf("Reading nonces...\n"); - uint64_t *nonces = readnonces(argv[1]); - printf("Deriving search space...\n"); - space = craptev1_get_space(nonces, 95, uid); - total_states = craptev1_sizeof_space(space); - -#ifndef __WIN32 - thread_count = sysconf(_SC_NPROCESSORS_CONF); -#else - thread_count = 1; -#endif - - // append some zeroes to the end of the space to make sure threads don't go off into the wild - size_t j = 0; - for(j = 0; space[j]; j+=5){ - } - size_t fill = j + (5*thread_count); - for(; j < fill; j++) { - space[j] = 0; - } - pthread_t threads[thread_count]; - size_t i; - - printf("Initializing BS crypto-1\n"); - crypto1_bs_init(); - printf("Using %u-bit bitslices\n", MAX_BITSLICES); - - uint8_t rollback_byte = **space; - printf("Bitslicing rollback byte: %02x...\n", rollback_byte); - // convert to 32 bit little-endian - crypto1_bs_bitslice_value32(rev32((rollback_byte)), bitsliced_rollback_byte, 8); - - printf("Bitslicing nonces...\n"); - for(size_t tests = 0; tests < NONCE_TESTS; tests++){ - // pre-xor the uid into the decrypted nonces, and also pre-xor the uid parity into the encrypted parity bits - otherwise an exta xor is required in the decryption routine - uint32_t test_nonce = uid^rev32(nonces[tests]); - uint32_t test_parity = (nonces[tests]>>32)^rev32(uid); - test_parity = ((parity(test_parity >> 24 & 0xff) & 1) | (parity(test_parity>>16 & 0xff) & 1)<<1 | (parity(test_parity>>8 & 0xff) & 1)<<2 | (parity(test_parity &0xff) & 1) << 3); - crypto1_bs_bitslice_value32(test_nonce, bitsliced_encrypted_nonces[tests], 32); - // convert to 32 bit little-endian - crypto1_bs_bitslice_value32(~(test_parity)<<24, bitsliced_encrypted_parity_bits[tests], 4); - } - - total_states_tested = 0; - keys_found = 0; - - printf("Starting %u threads to test %"llu" (~2^%0.2f) states\n", thread_count, total_states, log(total_states) / log(2)); - - signal(SIGALRM, notify_status_offline); - alarm(1); - - for(i = 0; i < thread_count; i++){ - pthread_create(&threads[i], NULL, crack_states_thread, (void*) i); - } - for(i = 0; i < thread_count; i++){ - pthread_join(threads[i], 0); - } - - alarm(0); - - printf("Tested %"llu" states\n", total_states_tested); - - craptev1_destroy_space(space); - return 0; -} - - diff --git a/txttobin.py b/txttobin.py deleted file mode 100644 index ac53400..0000000 --- a/txttobin.py +++ /dev/null @@ -1,29 +0,0 @@ -import sys -data = file(sys.argv[1], 'rb').readlines() -if sys.argv[1].endswith('.txt'): - uid = sys.argv[1][:-4] - -def parity(x): - return ("{0:08b}".format(x).count('1') & 1) - -uid=raw_input("uid> ") -fp = file(uid+'_generated.bin','wb') -fp.write(uid.decode('hex')+"\x00"*2) -bits = 0 -pbits = 0 -for l in data: - if bits == 8: - fp.write(chr(pbits)) - bits = 0 - pbits = 0 - hexbytes = filter(None, l.strip().split(' ')) - bits += 4 - for x in hexbytes: - b = int(x.replace('!', ''), 16) - p = parity(b) - if '!' not in x: - p^=1 - pbits <<= 1 - pbits |= p - fp.write(chr(b)) -