diff options
author | cvs2svn <cvs2svn@FreeBSD.org> | 2005-10-20 16:31:55 +0000 |
---|---|---|
committer | cvs2svn <cvs2svn@FreeBSD.org> | 2005-10-20 16:31:55 +0000 |
commit | 666ee37fdf267ebea8318e58f7585029f0457800 (patch) | |
tree | 7438cacaba0d6c122ff1d16a5b44e55b3db4c9ea | |
parent | e00d94fa7cb16ece7a61c444a75fef8ff3926446 (diff) |
This commit was manufactured by cvs2svn to create tagvendor/wpa_supplicant/0.3-latest
'wpa_supplicant-vendor-v0_3_latest'.
Notes
Notes:
svn path=/vendor/wpa_supplicant/dist/; revision=151513
svn path=/vendor/wpa_supplicant/0.3-latest/; revision=151515; tag=vendor/wpa_supplicant/0.3-latest
88 files changed, 0 insertions, 37046 deletions
diff --git a/contrib/wpa_supplicant/COPYING b/contrib/wpa_supplicant/COPYING deleted file mode 100644 index 60549be514af..000000000000 --- a/contrib/wpa_supplicant/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - 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. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - 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) 19yy 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. - - <signature of Ty Coon>, 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. diff --git a/contrib/wpa_supplicant/ChangeLog b/contrib/wpa_supplicant/ChangeLog deleted file mode 100644 index 09d5b6121551..000000000000 --- a/contrib/wpa_supplicant/ChangeLog +++ /dev/null @@ -1,418 +0,0 @@ -ChangeLog for wpa_supplicant - -2005-06-10 - v0.3.9 - * modified the EAP workaround that accepts EAP-Success with incorrect - Identifier to be even less strict about verification in order to - interoperate with some authentication servers - * fixed RSN IE in 4-Way Handshake message 2/4 for the case where - Authenticator rejects PMKSA caching attempt and the driver is not - using assoc_info events - * fixed a possible double free in EAP-TTLS fast-reauthentication when - identity or password is entered through control interface - * added -P<pid file> argument for wpa_supplicant to write the current - process id into a file - * driver_madwifi: fixed association in plaintext mode - * driver_madwifi: added preliminary support for compiling against 'BSD' - branch of madwifi CVS tree - * added EAP workaround for PEAPv1 session resumption: allow outer, - i.e., not tunneled, EAP-Success to terminate session since; this can - be disabled with eap_workaround=0 - * driver_ipw: updated driver structures to match with ipw2200-1.0.4 - (note: ipw2100-1.1.0 is likely to require an update to work with - this) - * driver_broadcom: fixed couple of memory leaks in scan result - processing - -2005-02-13 - v0.3.8 - * fixed EAPOL-Key validation to drop packets with invalid Key Data - Length; such frames could have crashed wpa_supplicant due to buffer - overflow - -2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) - * added new phase1 option parameter, include_tls_length=1, to force - wpa_supplicant to add TLS Message Length field to all TLS messages - even if the packet is not fragmented; this may be needed with some - authentication servers - * fixed WPA/RSN IE verification in message 3 of 4-Way Handshake when - using drivers that take care of AP selection (e.g., when using - ap_scan=2) - * fixed reprocessing of pending request after ctrl_iface requests for - identity/password/otp - * fixed ctrl_iface requests for identity/password/otp in Phase 2 of - EAP-PEAP and EAP-TTLS - * all drivers using driver_wext: set interface up and select Managed - mode when starting wpa_supplicant; set interface down when exiting - * renamed driver_ipw2100.c to driver_ipw.c since it now supports both - ipw2100 and ipw2200; please note that this also changed the - configuration variable in .config to CONFIG_DRIVER_IPW - -2005-01-24 - v0.3.6 - * fixed a busy loop introduced in v0.3.5 for scan result processing - when no matching AP is found - -2005-01-23 - v0.3.5 - * added a workaround for an interoperability issue with a Cisco AP - when using WPA2-PSK - * fixed non-WPA IEEE 802.1X to use the same authentication timeout as - WPA with IEEE 802.1X (i.e., timeout 10 -> 70 sec to allow - retransmission of dropped frames) - * fixed issues with 64-bit CPUs and SHA1 cleanup in previous version - (e.g., segfault when processing EAPOL-Key frames) - * fixed EAP workaround and fast reauthentication configuration for - RSN pre-authentication; previously these were disabled and - pre-authentication would fail if the used authentication server - requires EAP workarounds - * added support for blacklisting APs that fail or timeout - authentication in ap_scan=1 mode so that all APs are tried in cases - where the ones with strongest signal level are failing authentication - * fixed CA certificate loading after a failed EAP-TLS/PEAP/TTLS - authentication attempt - * allow EAP-PEAP/TTLS fast reauthentication only if Phase 2 succeeded - in the previous authentication (previously, only Phase 1 success was - verified) - -2005-01-09 - v0.3.4 - * added preliminary support for IBSS (ad-hoc) mode configuration - (mode=1 in network block); this included a new key_mgmt mode - WPA-NONE, i.e., TKIP or CCMP with a fixed key (based on psk) and no - key management; see wpa_supplicant.conf for more details and an - example on how to configure this (note: this is currently implemented - only for driver_hostapd.c, but the changes should be trivial to add - in associate() handler for other drivers, too (assuming the driver - supports WPA-None) - * added preliminary port for native Windows (i.e., no cygwin) using - mingw - -2005-01-02 - v0.3.3 - * added optional support for GNU Readline and History Libraries for - wpa_cli (CONFIG_READLINE) - * cleaned up EAP state machine <-> method interface and number of - small problems with error case processing not terminating on - EAP-Failure but waiting for timeout - * added couple of workarounds for interoperability issues with a - Cisco AP when using WPA2 - * added support for EAP-FAST (draft-cam-winget-eap-fast-00.txt); - Note: This requires a patch for openssl to add support for TLS - extensions and number of workarounds for operations without - certificates. Proof of concept type of experimental patch is - included in openssl-tls-extensions.patch. - -2004-12-19 - v0.3.2 - * fixed private key loading for cases where passphrase is not set - * fixed Windows/cygwin L2 packet handler freeing; previous version - could cause a segfault when RSN pre-authentication was completed - * added support for PMKSA caching with drivers that generate RSN IEs - (e.g., NDIS); currently, this is only implemented in driver_ndis.c, - but similar code can be easily added to driver_ndiswrapper.c once - ndiswrapper gets full support for RSN PMKSA caching - * improved recovery from PMKID mismatches by requesting full EAP - authentication in case of failed PMKSA caching attempt - * driver_ndis: added support for NDIS NdisMIncidateStatus() events - (this requires that ndis_events is ran while wpa_supplicant is - running) - * driver_ndis: use ADD_WEP/REMOVE_WEP when configuring WEP keys - * added support for driver interfaces to replace the interface name - based on driver/OS specific mapping, e.g., in case of driver_ndis, - this allows the beginning of the adapter description to be used as - the interface name - * added support for CR+LF (Windows-style) line ends in configuration - file - * driver_ndis: enable radio before starting scanning, disable radio - when exiting - * modified association event handler to set portEnabled = FALSE before - clearing port Valid in order to reset EAP state machine and avoid - problems with new authentication getting ignored because of state - machines ending up in AUTHENTICATED/SUCCESS state based on old - information - * added support for driver events to add PMKID candidates in order to - allow drivers to give priority to most likely roaming candidates - * driver_hostap: moved PrivacyInvoked configuration to associate() - function so that this will not be set for plaintext connections - * added KEY_MGMT_802_1X_NO_WPA as a new key_mgmt type so that driver - interface can distinguish plaintext and IEEE 802.1X (no WPA) - authentication - * fixed static WEP key configuration to use broadcast/default type for - all keys (previously, the default TX key was configured as pairwise/ - unicast key) - * driver_ndis: added legacy WPA capability detection for non-WPA2 - drivers - * added support for setting static WEP keys for IEEE 802.1X without - dynamic WEP keying (eapol_flags=0) - -2004-12-12 - v0.3.1 - * added support for reading PKCS#12 (PFX) files (as a replacement for - PEM/DER) to get certificate and private key (CONFIG_PKCS12) - * fixed compilation with CONFIG_PCSC=y - * added new ap_scan mode, ap_scan=2, for drivers that take care of - association, but need to be configured with security policy and SSID, - e.g., ndiswrapper and NDIS driver; this mode should allow such - drivers to work with hidden SSIDs and optimized roaming; when - ap_scan=2 is used, only the first network block in the configuration - file is used and this configuration should have explicit security - policy (i.e., only one option in the lists) for key_mgmt, pairwise, - group, proto variables - * added experimental port of wpa_supplicant for Windows - - driver_ndis.c driver interface (NDIS OIDs) - - currently, this requires cygwin and WinPcap - - small utility, win_if_list, can be used to get interface name - * control interface can now be removed at build time; add - CONFIG_CTRL_IFACE=y to .config to maintain old functionality - * optional Xsupplicant interface can now be removed at build time; - (CONFIG_XSUPPLICANT_IFACE=y in .config to bring it back) - * added auth_alg to driver interface associate() parameters to make it - easier for drivers to configure authentication algorithm as part of - the association - -2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) - * driver_broadcom: added new driver interface for Broadcom wl.o driver - (a generic driver for Broadcom IEEE 802.11a/g cards) - * wpa_cli: fixed parsing of -p <path> command line argument - * PEAPv1: fixed tunneled EAP-Success reply handling to reply with TLS - ACK, not tunneled EAP-Success (of which only the first byte was - actually send due to a bug in previous code); this seems to - interoperate with most RADIUS servers that implements PEAPv1 - * PEAPv1: added support for terminating PEAP authentication on tunneled - EAP-Success message; this can be configured by adding - peap_outer_success=0 on phase1 parameters in wpa_supplicant.conf - (some RADIUS servers require this whereas others require a tunneled - reply - * PEAPv1: changed phase1 option peaplabel to use default to 0, i.e., to - the old label for key derivation; previously, the default was 1, - but it looks like most existing PEAPv1 implementations use the old - label which is thus more suitable default option - * added support for EAP-PSK (draft-bersani-eap-psk-03.txt) - * fixed parsing of wep_tx_keyidx - * added support for configuring list of allowed Phase 2 EAP types - (for both EAP-PEAP and EAP-TTLS) instead of only one type - * added support for configuring IEEE 802.11 authentication algorithm - (auth_alg; mainly for using Shared Key authentication with static - WEP keys) - * added support for EAP-AKA (with UMTS SIM) - * fixed couple of errors in PCSC handling that could have caused - random-looking errors for EAP-SIM - * added support for EAP-SIM pseudonyms and fast re-authentication - * added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS - session resumption) - * added support for EAP-SIM with two challanges - (phase1="sim_min_num_chal=3" can be used to require three challenges) - * added support for configuring DH/DSA parameters for an ephemeral DH - key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters - dh_file and dh_file2 (phase 2); this adds support for using DSA keys - and optional DH key exchange to achieve forward secracy with RSA keys - * added support for matching subject of the authentication server - certificate with a substring when using EAP-TLS/PEAP/TTLS; new - configuration variables subject_match and subject_match2 - * changed SSID configuration in driver_wext.c (used by many driver - interfaces) to use ssid_len+1 as the length for SSID since some Linux - drivers expect this - * fixed couple of unaligned reads in scan result parsing to fix WPA - connection on some platforms (e.g., ARM) - * added driver interface for Intel ipw2100 driver - * added support for LEAP with WPA - * added support for larger scan results report (old limit was 4 kB of - data, i.e., about 35 or so APs) when using Linux wireless extensions - v17 or newer - * fixed a bug in PMKSA cache processing: skip sending of EAPOL-Start - only if there is a PMKSA cache entry for the current AP - * fixed error handling for case where reading of scan results fails: - must schedule a new scan or wpa_supplicant will remain waiting - forever - * changed debug output to remove shared password/key material by - default; all key information can be included with -K command line - argument to match the previous behavior - * added support for timestamping debug log messages (disabled by - default, can be enabled with -t command line argument) - * set pairwise/group cipher suite for non-WPA IEEE 802.1X to WEP-104 - if keys are not configured to be used; this fixes IEEE 802.1X mode - with drivers that use this information to configure whether Privacy - bit can be in Beacon frames (e.g., ndiswrapper) - * avoid clearing driver keys if no keys have been configured since last - key clear request; this seems to improve reliability of group key - handshake for ndiswrapper & NDIS driver which seems to be suffering - of some kind of timing issue when the keys are cleared again after - association - * changed driver interface API: - - WPA_SUPPLICANT_DRIVER_VERSION define can be used to determine which - version is being used (now, this is set to 2; previously, it was - not defined) - - pass pointer to private data structure to all calls - - the new API is not backwards compatible; all in-tree driver - interfaces has been converted to the new API - * added support for controlling multiple interfaces (radios) per - wpa_supplicant process; each interface needs to be listed on the - command line (-c, -i, -D arguments) with -N as a separator - (-cwpa1.conf -iwlan0 -Dhostap -N -cwpa2.conf -iath0 -Dmadwifi) - * added a workaround for EAP servers that incorrectly use same Id for - sequential EAP packets - * changed libpcap/libdnet configuration to use .config variable, - CONFIG_DNET_PCAP, instead of requiring Makefile modification - * improved downgrade attack detection in IE verification of msg 3/4: - verify both WPA and RSN IEs, if present, not only the selected one; - reject the AP if an RSN IE is found in msg 3/4, but not in Beacon or - Probe Response frame, and RSN is enabled in wpa_supplicant - configuration - * fixed WPA msg 3/4 processing to allow Key Data field contain other - IEs than just one WPA IE - * added support for FreeBSD and driver interface for the BSD net80211 - layer (CONFIG_DRIVER_BSD=y in .config); please note that some of the - required kernel mods have not yet been committed - * made EAP workarounds configurable; enabled by default, can be - disabled with network block option eap_workaround=0 - -2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) - * resolved couple of interoperability issues with EAP-PEAPv1 and - Phase 2 (inner EAP) fragment reassembly - * driver_madwifi: fixed WEP key configuration for IEEE 802.1X when the - AP is using non-zero key index for the unicast key and key index zero - for the broadcast key - * driver_hostap: fixed IEEE 802.1X WEP key updates and - re-authentication by allowing unencrypted EAPOL frames when not using - WPA - * added a new driver interface, 'wext', which uses only standard, - driver independent functionality in Linux wireless extensions; - currently, this can be used only for non-WPA IEEE 802.1X mode, but - eventually, this is to be extended to support full WPA/WPA2 once - Linux wireless extensions get support for this - * added support for mode in which the driver is responsible for AP - scanning and selection; this is disabled by default and can be - enabled with global ap_scan=0 variable in wpa_supplicant.conf; - this mode can be used, e.g., with generic 'wext' driver interface to - use wpa_supplicant as IEEE 802.1X Supplicant with any Linux driver - supporting wireless extensions. - * driver_madwifi: fixed WPA2 configuration and scan_ssid=1 (e.g., - operation with an AP that does not include SSID in the Beacon frames) - * added support for new EAP authentication methods: - EAP-TTLS/EAP-OTP, EAP-PEAPv0/OTP, EAP-PEAPv1/OTP, EAP-OTP - * added support for asking one-time-passwords from frontends (e.g., - wpa_cli); this 'otp' command works otherwise like 'password' command, - but the password is used only once and the frontend will be asked for - a new password whenever a request from authenticator requires a - password; this can be used with both EAP-OTP and EAP-GTC - * changed wpa_cli to automatically re-establish connection so that it - does not need to be re-started when wpa_supplicant is terminated and - started again - * improved user data (identity/password/otp) requests through - frontends: process pending EAPOL packets after getting new - information so that full authentication does not need to be - restarted; in addition, send pending requests again whenever a new - frontend is attached - * changed control frontends to use a new directory for socket files to - make it easier for wpa_cli to automatically select between interfaces - and to provide access control for the control interface; - wpa_supplicant.conf: ctrl_interface is now a path - (/var/run/wpa_supplicant is the recommended path) and - ctrl_interface_group can be used to select which group gets access to - the control interface; - wpa_cli: by default, try to connect to the first interface available - in /var/run/wpa_supplicant; this path can be overriden with -p option - and an interface can be selected with -i option (i.e., in most common - cases, wpa_cli does not need to get any arguments) - * added support for LEAP - * added driver interface for Linux ndiswrapper - * added priority option for network blocks in the configuration file; - this allows networks to be grouped based on priority (the scan - results are searched for matches with network blocks in this order) - -2004-06-20 - v0.2.3 - * sort scan results to improve AP selection - * fixed control interface socket removal for some error cases - * improved scan requesting and authentication timeout - * small improvements/bug fixes for EAP-MSCHAPv2, EAP-PEAP, and - TLS processing - * PEAP version can now be forced with phase1="peapver=<ver>" - (mostly for testing; by default, the highest version supported by - both the Supplicant and Authentication Server is selected - automatically) - * added support for madwifi driver (Atheros ar521x) - * added a workaround for cases where AP sets Install Tx/Rx bit for - WPA Group Key messages when pairwise keys are used (without this, - the Group Key would be used for Tx and the AP would drop frames - from the station) - * added GSM SIM/USIM interface for GSM authentication algorithm for - EAP-SIM; this requires pcsc-lite - * added support for ATMEL AT76C5XXx driver - * fixed IEEE 802.1X WEP key derivation in the case where Authenticator - does not include key data in the EAPOL-Key frame (i.e., part of - EAP keying material is used as data encryption key) - * added support for using plaintext and static WEP networks - (key_mgmt=NONE) - -2004-05-31 - v0.2.2 - * added support for new EAP authentication methods: - EAP-TTLS/EAP-MD5-Challenge - EAP-TTLS/EAP-GTC - EAP-TTLS/EAP-MSCHAPv2 - EAP-TTLS/EAP-TLS - EAP-TTLS/MSCHAPv2 - EAP-TTLS/MSCHAP - EAP-TTLS/PAP - EAP-TTLS/CHAP - EAP-PEAP/TLS - EAP-PEAP/GTC - EAP-PEAP/MD5-Challenge - EAP-GTC - EAP-SIM (not yet complete; needs GSM/SIM authentication interface) - * added support for anonymous identity (to be used when identity is - sent in plaintext; real identity will be used within TLS protected - tunnel (e.g., with EAP-TTLS) - * added event messages from wpa_supplicant to frontends, e.g., wpa_cli - * added support for requesting identity and password information using - control interface; in other words, the password for EAP-PEAP or - EAP-TTLS does not need to be included in the configuration file since - a frontand (e.g., wpa_cli) can ask it from the user - * improved RSN pre-authentication to use a candidate list and process - all candidates from each scan; not only one per scan - * fixed RSN IE and WPA IE capabilities field parsing - * ignore Tx bit in GTK IE when Pairwise keys are used - * avoid making new scan requests during IEEE 802.1X negotiation - * use openssl/libcrypto for MD5 and SHA-1 when compiling wpa_supplicant - with TLS support (this replaces the included implementation with - library code to save about 8 kB since the library code is needed - anyway for TLS) - * fixed WPA-PSK only mode when compiled without IEEE 802.1X support - (i.e., without CONFIG_IEEE8021X_EAPOL=y in .config) - -2004-05-06 - v0.2.1 - * added support for internal IEEE 802.1X (actually, IEEE 802.1aa/D6.1) - Supplicant - - EAPOL state machines for Supplicant [IEEE 802.1aa/D6.1] - - EAP peer state machine [draft-ietf-eap-statemachine-02.pdf] - - EAP-MD5 (cannot be used with WPA-RADIUS) - [draft-ietf-eap-rfc2284bis-09.txt] - - EAP-TLS [RFC 2716] - - EAP-MSCHAPv2 (currently used only with EAP-PEAP) - - EAP-PEAP/MSCHAPv2 [draft-josefsson-pppext-eap-tls-eap-07.txt] - [draft-kamath-pppext-eap-mschapv2-00.txt] - (PEAP version 0, 1, and parts of 2; only 0 and 1 are enabled by - default; tested with FreeRADIUS, Microsoft IAS, and Funk Odyssey) - - new configuration file options: eap, identity, password, ca_cert, - client_cert, privatekey, private_key_passwd - - Xsupplicant is not required anymore, but it can be used by - disabling the internal IEEE 802.1X Supplicant with -e command line - option - - this code is not included in the default build; Makefile need to - be edited for this (uncomment lines for selected functionality) - - EAP-TLS and EAP-PEAP require openssl libraries - * use module prefix in debug messages (WPA, EAP, EAP-TLS, ..) - * added support for non-WPA IEEE 802.1X mode with dynamic WEP keys - (i.e., complete IEEE 802.1X/EAP authentication and use IEEE 802.1X - EAPOL-Key frames instead of WPA key handshakes) - * added support for IEEE 802.11i/RSN (WPA2) - - improved PTK Key Handshake - - PMKSA caching, pre-authentication - * fixed wpa_supplicant to ignore possible extra data after WPA - EAPOL-Key packets (this fixes 'Invalid EAPOL-Key MIC when using - TPTK' error from message 3 of 4-Way Handshake in case the AP - includes extra data after the EAPOL-Key) - * added interface for external programs (frontends) to control - wpa_supplicant - - CLI example (wpa_cli) with interactive mode and command line - mode - - replaced SIGUSR1 status/statistics with the new control interface - * made some feature compile time configurable - - .config file for make - - driver interfaces (hostap, hermes, ..) - - EAPOL/EAP functions - -2004-02-15 - v0.2.0 - * Initial version of wpa_supplicant diff --git a/contrib/wpa_supplicant/FREEBSD-Xlist b/contrib/wpa_supplicant/FREEBSD-Xlist deleted file mode 100644 index d2f169790480..000000000000 --- a/contrib/wpa_supplicant/FREEBSD-Xlist +++ /dev/null @@ -1,22 +0,0 @@ -$FreeBSD$ -.cvsignore -README-Windows.txt -driver_atmel.c -driver_broadcom.c -driver_bsd.c -driver_hostap.c -driver_ipw.c -driver_madwifi.c -driver_ndis.c -driver_ndis.h -driver_ndis_.c -driver_ndiswrapper.c -driver_prism54.c -driver_test.c -driver_wext.c -driver_wext.h -l2_packet.c -ndis_events.cpp -priv_netlink.h -win_if_list.c -wireless_copy.h diff --git a/contrib/wpa_supplicant/FREEBSD-upgrade b/contrib/wpa_supplicant/FREEBSD-upgrade deleted file mode 100644 index f8ef0f001379..000000000000 --- a/contrib/wpa_supplicant/FREEBSD-upgrade +++ /dev/null @@ -1,24 +0,0 @@ -$FreeBSD$ - -WPA Supplicant - originals can be found at: http://hostap.epitest.fi/releases/ - - -For the import files and directories were pruned by: - - tar -X FREEBSD-Xlist -zxf wpa_supplicant-0.3.8.tar.gz - -then imported by: - - cvs import -m 'Import of WPA supplicant 0.3.8' \ - src/contrib/wpa_supplicant MALINEN v0_3_8 - -To make local changes to wpa_supplcaint, simply patch and commit -to the main branch (aka HEAD). Never make local changes on the -vendor (MALINEN) branch. - -All local changes should be submitted to Jouni Malinen for inclusion in -the next vendor release. - -sam@FreeBSD.org -4-June-2005 diff --git a/contrib/wpa_supplicant/Makefile b/contrib/wpa_supplicant/Makefile deleted file mode 100644 index fa912436c86e..000000000000 --- a/contrib/wpa_supplicant/Makefile +++ /dev/null @@ -1,385 +0,0 @@ -ifndef CC -CC=gcc -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -# Include directories for CVS version -CFLAGS += -I../driver/modules -I../utils -I../hostapd - -ALL=wpa_supplicant wpa_passphrase wpa_cli - -all: verify_config $(ALL) - -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building wpa_supplicant requires a configuration file'; \ - echo '(.config). See README for more instructions. You can'; \ - echo 'run "cp defconfig .config" to create an example'; \ - echo 'configuration.'; \ - exit 1; \ - fi - -mkconfig: - @if [ -e .config ]; then \ - echo '.config exists - did not replace it'; \ - exit 1; \ - fi - echo CONFIG_DRIVER_HOSTAP=y >> .config - echo CONFIG_DRIVER_WEXT=y >> .config - echo CONFIG_WIRELESS_EXTENSION=y >> .config - -install: all - mkdir -p $(DESTDIR)/usr/local/sbin/ - for i in $(ALL); do cp $$i $(DESTDIR)/usr/local/sbin/$$i; done - -OBJS = config.o \ - eloop.o common.o md5.o \ - rc4.o sha1.o aes_wrap.o -OBJS_p = wpa_passphrase.o sha1.o md5.o -OBJS_c = wpa_cli.o wpa_ctrl.o - --include .config - -ifdef CONFIG_EAPOL_TEST -CFLAGS += -Werror -DEAPOL_TEST -endif - -ifdef CONFIG_DRIVER_HOSTAP -CFLAGS += -DCONFIG_DRIVER_HOSTAP -OBJS += driver_hostap.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_WEXT -CFLAGS += -DCONFIG_DRIVER_WEXT -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_PRISM54 -CFLAGS += -DCONFIG_DRIVER_PRISM54 -OBJS += driver_prism54.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_HERMES -CFLAGS += -DCONFIG_DRIVER_HERMES -OBJS += driver_hermes.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_MADWIFI -CFLAGS += -DCONFIG_DRIVER_MADWIFI -OBJS += driver_madwifi.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_ATMEL -CFLAGS += -DCONFIG_DRIVER_ATMEL -OBJS += driver_atmel.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_NDISWRAPPER -CFLAGS += -DCONFIG_DRIVER_NDISWRAPPER -OBJS += driver_ndiswrapper.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_BROADCOM -CFLAGS += -DCONFIG_DRIVER_BROADCOM -OBJS += driver_broadcom.o -endif - -ifdef CONFIG_DRIVER_IPW -CFLAGS += -DCONFIG_DRIVER_IPW -OBJS += driver_ipw.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_BSD -CFLAGS += -DCONFIG_DRIVER_BSD -OBJS += driver_bsd.o -CONFIG_DNET_PCAP=y -endif - -ifdef CONFIG_DRIVER_NDIS -CFLAGS += -DCONFIG_DRIVER_NDIS -OBJS += driver_ndis.o driver_ndis_.o -CONFIG_DNET_PCAP=y -CONFIG_WINPCAP=y -endif - -ifdef CONFIG_DRIVER_TEST -CFLAGS += -DCONFIG_DRIVER_TEST -OBJS += driver_test.o -endif - -ifdef CONFIG_DNET_PCAP -CFLAGS += -DUSE_DNET_PCAP -ifdef CONFIG_WINPCAP -CFLAGS += -DCONFIG_WINPCAP -LIBS += -lwpcap -lpacket -LIBS_w += -lwpcap -else -LIBS += -ldnet -lpcap -endif -endif - -ifdef CONFIG_EAP_TLS -# EAP-TLS -CFLAGS += -DEAP_TLS -OBJS += eap_tls.o -TLS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_PEAP -# EAP-PEAP -CFLAGS += -DEAP_PEAP -OBJS += eap_peap.o -TLS_FUNCS=y -CONFIG_EAP_MSCHAPV2=y -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_TLV=y -endif - -ifdef CONFIG_EAP_TTLS -# EAP-TTLS -CFLAGS += -DEAP_TTLS -OBJS += eap_ttls.o -MS_FUNCS=y -TLS_FUNCS=y -CONFIG_EAP_MD5=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_MD5 -# EAP-MD5 (also used by EAP-TTLS) -CFLAGS += -DEAP_MD5 -OBJS += eap_md5.o -CONFIG_IEEE8021X_EAPOL=y -endif - -# backwards compatibility for old spelling -ifdef CONFIG_MSCHAPV2 -CONFIG_EAP_MSCHAPV2=y -endif - -ifdef CONFIG_EAP_MSCHAPV2 -# EAP-MSCHAPv2 (also used by EAP-PEAP) -CFLAGS += -DEAP_MSCHAPv2 -OBJS += eap_mschapv2.o -MS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_GTC -# EAP-GTC (also used by EAP-PEAP) -CFLAGS += -DEAP_GTC -OBJS += eap_gtc.o -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_OTP -# EAP-OTP -CFLAGS += -DEAP_OTP -OBJS += eap_otp.o -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_SIM -# EAP-SIM -CFLAGS += -DEAP_SIM -OBJS += eap_sim.o -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_SIM_COMMON=y -endif - -ifdef CONFIG_EAP_LEAP -# EAP-LEAP -CFLAGS += -DEAP_LEAP -OBJS += eap_leap.o -MS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_PSK -# EAP-PSK -CFLAGS += -DEAP_PSK -OBJS += eap_psk.o -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_AKA -# EAP-AKA -CFLAGS += -DEAP_AKA -OBJS += eap_aka.o -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_SIM_COMMON=y -endif - -ifdef CONFIG_EAP_SIM_COMMON -OBJS += eap_sim_common.o -endif - -ifdef CONFIG_EAP_TLV -# EAP-TLV -CFLAGS += -DEAP_TLV -OBJS += eap_tlv.o -endif - -ifdef CONFIG_EAP_FAST -# EAP-FAST -CFLAGS += -DEAP_FAST -OBJS += eap_fast.o -TLS_FUNCS=y -endif - -ifdef CONFIG_IEEE8021X_EAPOL -# IEEE 802.1X/EAPOL state machines (e.g., for RADIUS authentication) -CFLAGS += -DIEEE8021X_EAPOL -OBJS += eapol_sm.o eap.o -endif - -ifdef CONFIG_PCSC -# PC/SC interface for smartcards (USIM, GSM SIM) -CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC -OBJS += pcsc_funcs.o -# -lpthread may not be needed depending on how pcsc-lite was configured -LIBS += -lpcsclite -lpthread -endif - -ifdef TLS_FUNCS -# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS) -CFLAGS += -DEAP_TLS_FUNCS -OBJS += eap_tls_common.o tls_openssl.o -LIBS += -lssl -lcrypto -LIBS_p += -lcrypto -else -OBJS += tls_none.o -endif - -ifdef CONFIG_PKCS12 -CFLAGS += -DPKCS12_FUNCS -endif - -ifdef MS_FUNCS -ifndef TLS_FUNCS -LIBS += -lcrypto -endif -OBJS += ms_funcs.o crypto.o -endif - -ifdef CONFIG_WIRELESS_EXTENSION -CFLAGS += -DCONFIG_WIRELESS_EXTENSION -OBJS += driver_wext.o -endif - -ifdef CONFIG_CTRL_IFACE -CFLAGS += -DCONFIG_CTRL_IFACE -OBJS += ctrl_iface.o -endif - -ifdef CONFIG_XSUPPLICANT_IFACE -CFLAGS += -DCONFIG_XSUPPLICANT_IFACE -endif - -ifdef CONFIG_READLINE -CFLAGS += -DCONFIG_READLINE -LIBS_c += -lncurses -lreadline -endif - -ifdef CONFIG_NATIVE_WINDOWS -CFLAGS += -DCONFIG_NATIVE_WINDOWS -DCONFIG_CTRL_IFACE_UDP -LIBS += -lws2_32 -lgdi32 -LIBS_c += -lws2_32 -endif - -OBJS_t := $(OBJS) eapol_test.o radius.o radius_client.o -OBJS_t2 := $(OBJS) preauth_test.o l2_packet.o -OBJS += wpa_supplicant.o wpa.o l2_packet.o drivers.o - -wpa_supplicant: .config $(OBJS) - $(CC) -o wpa_supplicant $(OBJS) $(LIBS) - -eapol_test: .config $(OBJS_t) - $(CC) -o eapol_test $(OBJS_t) $(LIBS) - -preauth_test: .config $(OBJS_t2) - $(CC) -o preauth_test $(OBJS_t2) $(LIBS) - -wpa_passphrase: $(OBJS_p) - $(CC) -o wpa_passphrase $(OBJS_p) $(LIBS_p) - -wpa_cli: $(OBJS_c) - $(CC) -o wpa_cli $(OBJS_c) $(LIBS_c) - -win_if_list: win_if_list.c - $(CC) -o $@ win_if_list.c $(CFLAGS) $(LIBS_w) - -# parameters for Microsoft Visual C++ Toolkit 2003 compiler -CL=cl -CLDIR=C:\Program Files\Microsoft Visual C++ Toolkit 2003 -PSDKDIR=C:\Program Files\Microsoft Platform SDK for Windows XP SP2 -CLFLAGS=-O -CLLIBS=wbemuuid.lib libcmt.lib kernel32.lib uuid.lib ole32.lib oleaut32.lib \ - ws2_32.lib - -ndis_events: ndis_events.cpp - INCLUDE="$(CLDIR)\include;$(PSDKDIR)\Include" \ - LIB="$(CLDIR)\lib;$(PSDKDIR)\Lib" \ - $(CL) $(CLFLAGS) -o ndis_events.exe ndis_events.cpp \ - /link -nodefaultlib $(CLLIBS) - -wpa_supplicant.exe: wpa_supplicant - mv -f $< $@ -wpa_cli.exe: wpa_cli - mv -f $< $@ -wpa_passphrase.exe: wpa_passphrase - mv -f $< $@ -win_if_list.exe: win_if_list - mv -f $< $@ - -WINALL=wpa_supplicant.exe wpa_cli.exe wpa_passphrase.exe win_if_list.exe - -windows-bin: $(WINALL) - $(STRIP) $(WINALL) - -TEST_SRC_MS_FUNCS = ms_funcs.c crypto.c sha1.c md5.c -test-ms_funcs: $(TEST_SRC_MS_FUNCS) - $(CC) -o test-ms_funcs -Wall -Werror $(TEST_SRC_MS_FUNCS) \ - -DTEST_MAIN_MS_FUNCS -lcrypto -I../hostapd - ./test-ms_funcs - rm test-ms_funcs - -TEST_SRC_SHA1 = sha1.c -test-sha1: $(TEST_SRC_SHA1) - $(CC) -o test-sha1 -Wall -Werror $(TEST_SRC_SHA1) \ - -DTEST_MAIN -I../hostad - ./test-sha1 - rm test-sha1 - -TEST_SRC_AES_WRAP = aes_wrap.c -test-aes_wrap: $(TEST_SRC_AES_WRAP) - $(CC) -o test-aes_wrap -Wall -Werror $(TEST_SRC_AES_WRAP) \ - -DTEST_MAIN -I../hostad - ./test-aes_wrap - rm test-aes_wrap - -TEST_SRC_EAP_SIM_COMMON = eap_sim_common.c sha1.c md5.c \ - aes_wrap.c common.c -test-eap_sim_common: $(TEST_SRC_EAP_SIM_COMMON) - $(CC) -o test-eap_sim_common -Wall -Werror $(TEST_SRC_EAP_SIM_COMMON) \ - -DTEST_MAIN_EAP_SIM_COMMON -I../hostapd - ./test-eap_sim_common - rm test-eap_sim_common - -tests: test-ms_funcs test-sha1 test-aes_wrap test-eap_sim_common - -clean: - rm -f core *~ *.o *.d $(ALL) $(WINALL) - --include $(OBJS:%.o=%.d) diff --git a/contrib/wpa_supplicant/README b/contrib/wpa_supplicant/README deleted file mode 100644 index bab25d586725..000000000000 --- a/contrib/wpa_supplicant/README +++ /dev/null @@ -1,858 +0,0 @@ -WPA Supplicant -============== - -Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> and -contributors -All Rights Reserved. - -This program is dual-licensed under both the GPL version 2 and BSD -license. Either license may be used at your option. - - - -License -------- - -GPL v2: - -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. - -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 - -(this copy of the license is in COPYING file) - - -Alternatively, this software may be distributed under the terms of BSD -license: - -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. Neither the name(s) of the above-listed copyright holder(s) nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER 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. - - - -Features --------- - -Supported WPA/IEEE 802.11i features: -- WPA-PSK ("WPA-Personal") -- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") - Following authentication methods are supported with an integrate IEEE 802.1X - Supplicant: - * EAP-TLS - * EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1) - * EAP-PEAP/TLS (both PEAPv0 and PEAPv1) - * EAP-PEAP/GTC (both PEAPv0 and PEAPv1) - * EAP-PEAP/OTP (both PEAPv0 and PEAPv1) - * EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1) - * EAP-TTLS/EAP-MD5-Challenge - * EAP-TTLS/EAP-GTC - * EAP-TTLS/EAP-OTP - * EAP-TTLS/EAP-MSCHAPv2 - * EAP-TTLS/EAP-TLS - * EAP-TTLS/MSCHAPv2 - * EAP-TTLS/MSCHAP - * EAP-TTLS/PAP - * EAP-TTLS/CHAP - * EAP-SIM - * EAP-AKA - * EAP-PSK - * LEAP (note: requires special support from the driver for IEEE 802.11 - authentication) - (following methods are supported, but since they do not generate keying - material, they cannot be used with WPA or IEEE 802.1X WEP keying) - * EAP-MD5-Challenge - * EAP-MSCHAPv2 - * EAP-GTC - * EAP-OTP - Alternatively, an external program, e.g., Xsupplicant, can be used for EAP - authentication. -- key management for CCMP, TKIP, WEP104, WEP40 -- RSN/WPA2 (IEEE 802.11i) - * pre-authentication - * PMKSA caching - - - -Requirements ------------- - -Current hardware/software requirements: -- Linux kernel 2.4.x or 2.6.x with Linux Wireless Extensions v15 or newer -- FreeBSD 6-CURRENT -- Microsoft Windows with WinPcap (at least WinXP, may work with other versions) -- drivers: - Host AP driver for Prism2/2.5/3 (development snapshot/v0.2.x) - (http://hostap.epitest.fi/) - Driver need to be set in Managed mode ('iwconfig wlan0 mode managed'). - Please note that station firmware version needs to be 1.7.0 or newer - to work in WPA mode. - - Linuxant DriverLoader (http://www.linuxant.com/driverloader/) - with Windows NDIS driver for your wlan card supporting WPA. - - Agere Systems Inc. Linux Driver - (http://www.agere.com/support/drivers/) - Please note that the driver interface file (driver_hermes.c) and - hardware specific include files are not included in the - wpa_supplicant distribution. You will need to copy these from the - source package of the Agere driver. - - madwifi driver for cards based on Atheros chip set (ar521x) - (http://sourceforge.net/projects/madwifi/) - Please note that you will need to modify the wpa_supplicant .config - file to use the correct path for the madwifi driver root directory - (CFLAGS += -I../madwifi/wpa line in example defconfig). - - ATMEL AT76C5XXx driver for USB and PCMCIA cards - (http://atmelwlandriver.sourceforge.net/). - - Linux ndiswrapper (http://ndiswrapper.sourceforge.net/) with - Windows NDIS driver. - - Broadcom wl.o driver - This is a generic Linux driver for Broadcom IEEE 802.11a/g cards. - However, it is proprietary driver that is not publicly available - except for couple of exceptions, mainly Broadcom-based APs/wireless - routers that use Linux. The driver binary can be downloaded, e.g., - from Linksys support site (http://www.linksys.com/support/gpl.asp) - for Linksys WRT54G. The GPL tarball includes cross-compiler and - the needed header file, wlioctl.h, for compiling wpa_supplicant. - This driver support in wpa_supplicant is expected to work also with - other devices based on Broadcom driver (assuming the driver includes - client mode support). - - Intel ipw2100 driver - (http://sourceforge.net/projects/ipw2100/) - - Intel ipw2200 driver - (http://sourceforge.net/projects/ipw2200/) - - In theory, any driver that supports Linux wireless extensions can be - used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in - configuration file. - - BSD net80211 layer (e.g., Atheros driver) - At the moment, this is for FreeBSD 6-CURRENT branch. - - Windows NDIS - The current Windows port requires WinPcap (http://winpcap.polito.it/). - See README-Windows.txt for more information. - -wpa_supplicant was designed to be portable for different drivers and -operating systems. Hopefully, support for more wlan cards and OSes will be -added in the future. See developer.txt for more information about the -design of wpa_supplicant and porting to other drivers. One main goal -is to add full WPA/WPA2 support to Linux wireless extensions to allow -new drivers to be supported without having to implement new -driver-specific interface code in wpa_supplicant. - -Optional libraries for layer2 packet processing: -- libpcap (tested with 0.7.2, most relatively recent versions assumed to work, - this is likely to be available with most distributions, - http://tcpdump.org/) -- libdnet (tested with v1.4, most versions assumed to work, - http://libdnet.sourceforge.net/) - -These libraries are _not_ used in the default Linux build. Instead, -internal Linux specific implementation is used. libpcap/libdnet are -more portable and they can be used by adding CONFIG_DNET_PCAP=y into -.config. They may also be selected automatically for other operating -systems. - - -Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS: -- openssl (tested with 0.9.7c and 0.9.7d, assumed to work with most - relatively recent versions; this is likely to be available with most - distributions, http://www.openssl.org/) - -This library is only needed when EAP-TLS, EAP-PEAP, or EAP-TTLS -support is enabled. WPA-PSK mode does not require this or EAPOL/EAP -implementation. A configuration file, .config, for compilation is -needed to enable IEEE 802.1X/EAPOL and EAP methods. Note that EAP-MD5, -EAP-GTC, EAP-OTP, and EAP-MSCHAPV2 cannot be used alone with WPA, so -they should only be enabled if testing the EAPOL/EAP state -machines. However, there can be used as inner authentication -algorithms with EAP-PEAP and EAP-TTLS. - -See Building and installing section below for more detailed -information about the wpa_supplicant build time configuration. - - - -WPA ---- - -The original security mechanism of IEEE 802.11 standard was not -designed to be strong and has proven to be insufficient for most -networks that require some kind of security. Task group I (Security) -of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked -to address the flaws of the base standard and has in practice -completed its work in May 2004. The IEEE 802.11i amendment to the IEEE -802.11 standard was approved in June 2004 and this amendment is likely -to be published in July 2004. - -Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the -IEEE 802.11i work (draft 3.0) to define a subset of the security -enhancements that can be implemented with existing wlan hardware. This -is called Wi-Fi Protected Access<TM> (WPA). This has now become a -mandatory component of interoperability testing and certification done -by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web -site (http://www.wi-fi.org/OpenSection/protected_access.asp). - -IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm -for protecting wireless networks. WEP uses RC4 with 40-bit keys, -24-bit initialization vector (IV), and CRC32 to protect against packet -forgery. All these choices have proven to be insufficient: key space is -too small against current attacks, RC4 key scheduling is insufficient -(beginning of the pseudorandom stream should be skipped), IV space is -too small and IV reuse makes attacks easier, there is no replay -protection, and non-keyed authentication does not protect against bit -flipping packet data. - -WPA is an intermediate solution for the security issues. It uses -Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a -compromise on strong security and possibility to use existing -hardware. It still uses RC4 for the encryption like WEP, but with -per-packet RC4 keys. In addition, it implements replay protection, -keyed packet authentication mechanism (Michael MIC). - -Keys can be managed using two different mechanisms. WPA can either use -an external authentication server (e.g., RADIUS) and EAP just like -IEEE 802.1X is using or pre-shared keys without need for additional -servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal", -respectively. Both mechanisms will generate a master session key for -the Authenticator (AP) and Supplicant (client station). - -WPA implements a new key handshake (4-Way Handshake and Group Key -Handshake) for generating and exchanging data encryption keys between -the Authenticator and Supplicant. This handshake is also used to -verify that both Authenticator and Supplicant know the master session -key. These handshakes are identical regardless of the selected key -management mechanism (only the method for generating master session -key changes). - - - -IEEE 802.11i / WPA2 -------------------- - -The design for parts of IEEE 802.11i that were not included in WPA has -finished (May 2004) and this amendment to IEEE 802.11 was approved in -June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new -version of WPA called WPA2. This includes, e.g., support for more -robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC) -to replace TKIP and optimizations for handoff (reduced number of -messages in initial key handshake, pre-authentication, and PMKSA caching). - -Some wireless LAN vendors are already providing support for CCMP in -their WPA products. There is no "official" interoperability -certification for CCMP and/or mixed modes using both TKIP and CCMP, so -some interoperability issues can be expected even though many -combinations seem to be working with equipment from different vendors. -Certification for WPA2 is likely to start during the second half of -2004. - - - -wpa_supplicant --------------- - -wpa_supplicant is an implementation of the WPA Supplicant component, -i.e., the part that runs in the client stations. It implements WPA key -negotiation with a WPA Authenticator and EAP authentication with -Authentication Server. In addition, it controls the roaming and IEEE -802.11 authentication/association of the wlan driver. - -wpa_supplicant is designed to be a "daemon" program that runs in the -background and acts as the backend component controlling the wireless -connection. wpa_supplicant supports separate frontend programs and an -example text-based frontend, wpa_cli, is included with wpa_supplicant. - -Following steps are used when associating with an AP using WPA: - -- wpa_supplicant requests the kernel driver to scan neighboring BSSes -- wpa_supplicant selects a BSS based on its configuration -- wpa_supplicant requests the kernel driver to associate with the chosen - BSS -- If WPA-EAP: integrated IEEE 802.1X Supplicant or external Xsupplicant - completes EAP authentication with the authentication server (proxied - by the Authenticator in the AP) -- If WPA-EAP: master key is received from the IEEE 802.1X Supplicant -- If WPA-PSK: wpa_supplicant uses PSK as the master session key -- wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake - with the Authenticator (AP) -- wpa_supplicant configures encryption keys for unicast and broadcast -- normal data packets can be transmitted and received - - - -Building and installing ------------------------ - -In order to be able to build wpa_supplicant, you will first need to -select which parts of it will be included. This is done by creating a -build time configuration file, .config, in the wpa_supplicant root -directory. Configuration options are text lines using following -format: CONFIG_<option>=y. Lines starting with # are considered -comments and are ignored. See defconfig file for example configuration -and list of available option. - -The build time configuration can be used to select only the needed -features and limit the binary size and requirements for external -libraries. The main configuration parts are the selection of which -driver interfaces (e.g., hostap, madwifi, ..) and which authentication -methods (e.g., EAP-TLS, EAP-PEAP, ..) are included. - -Following build time configuration options are used to control IEEE -802.1X/EAPOL and EAP state machines and all EAP methods. Including -TLS, PEAP, or TTLS will require linking wpa_supplicant with openssl -library for TLS implementation. - -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_MD5=y -CONFIG_EAP_MSCHAPV2=y -CONFIG_EAP_TLS=y -CONFIG_EAP_PEAP=y -CONFIG_EAP_TTLS=y -CONFIG_EAP_GTC=y -CONFIG_EAP_OTP=y -CONFIG_EAP_SIM=y -CONFIG_EAP_AKA=y -CONFIG_EAP_PSK=y -CONFIG_EAP_LEAP=y - -Following option can be used to include GSM SIM/USIM interface for GSM/UMTS -authentication algorithm (for EAP-SIM/EAP-AKA). This requires pcsc-lite -(http://www.linuxnet.com/) for smart card access. - -CONFIG_PCSC=y - -Following option can be used to replace the native Linux packet socket -interface with libpcap/libdnet. - -CONFIG_DNET_PCAP=y - -Following options can be added to .config to select which driver -interfaces are included. Prism54.org driver is not yet complete and -Hermes driver interface needs to be downloaded from Agere (see above). -Most Linux driver need to include CONFIG_WIRELESS_EXTENSION. - -CONFIG_WIRELESS_EXTENSION=y -CONFIG_DRIVER_HOSTAP=y -CONFIG_DRIVER_PRISM54=y -CONFIG_DRIVER_HERMES=y -CONFIG_DRIVER_MADWIFI=y -CONFIG_DRIVER_ATMEL=y -CONFIG_DRIVER_WEXT=y -CONFIG_DRIVER_NDISWRAPPER=y -CONFIG_DRIVER_BROADCOM=y -CONFIG_DRIVER_IPW=y -CONFIG_DRIVER_BSD=y -CONFIG_DRIVER_NDIS=y - -Following example includes all features and driver interfaces that are -included in the wpa_supplicant package: - -CONFIG_DRIVER_HOSTAP=y -CONFIG_DRIVER_PRISM54=y -CONFIG_DRIVER_HERMES=y -CONFIG_DRIVER_MADWIFI=y -CONFIG_DRIVER_ATMEL=y -CONFIG_DRIVER_WEXT=y -CONFIG_DRIVER_NDISWRAPPER=y -CONFIG_DRIVER_BROADCOM=y -CONFIG_DRIVER_IPW=y -CONFIG_DRIVER_BSD=y -CONFIG_DRIVER_NDIS=y -CONFIG_WIRELESS_EXTENSION=y -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_MD5=y -CONFIG_EAP_MSCHAPV2=y -CONFIG_EAP_TLS=y -CONFIG_EAP_PEAP=y -CONFIG_EAP_TTLS=y -CONFIG_EAP_GTC=y -CONFIG_EAP_OTP=y -CONFIG_EAP_SIM=y -CONFIG_EAP_AKA=y -CONFIG_EAP_PSK=y -CONFIG_EAP_LEAP=y -CONFIG_PCSC=y - -EAP-PEAP and EAP-TTLS will automatically include configured EAP -methods (MD5, OTP, GTC, MSCHAPV2) for inner authentication selection. - - -After you have created a configuration file, you can build -wpa_supplicant and wpa_cli with 'make' command. You may then install -the binaries to a suitable system directory, e.g., /usr/local/bin. - -Example commands: - -# build wpa_supplicant and wpa_cli -make -# install binaries (this may need root privileges) -cp wpa_cli wpa_supplicant /usr/local/bin - - -You will need to make a configuration file, e.g., -/etc/wpa_supplicant.conf, with network configuration for the networks -you are going to use. Configuration file section below includes -explanation fo the configuration file format and includes various -examples. Once the configuration is ready, you can test whether the -configuration work by first running wpa_supplicant with following -command to start it on foreground with debugging enabled: - -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d - -Assuming everything goes fine, you can start using following command -to start wpa_supplicant on background without debugging: - -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B - -Please note that if you included more than one driver interface in the -build time configuration (.config), you may need to specify which -interface to use by including -D<driver name> option on the command -line. See following section for more details on command line options -for wpa_supplicant. - - - -Command line options --------------------- - -usage: - wpa_supplicant [-BddehLqqvw] -i<ifname> -c<config file> [-D<driver>] \ - [-N -i<ifname> -c<conf> [-D<driver>] ...] - -options: - -B = run daemon in the background - -d = increase debugging verbosity (-dd even more) - -K = include keys (passwords, etc.) in debug output - -t = include timestamp in debug messages - -e = use external IEEE 802.1X Supplicant (e.g., xsupplicant) - (this disables the internal Supplicant) - -h = show this help text - -L = show license (GPL and BSD) - -q = decrease debugging verbosity (-qq even less) - -v = show version - -w = wait for interface to be added, if needed - -N = start describing new interface - -drivers: - hostap = Host AP driver (Intersil Prism2/2.5/3) [default] - (this can also be used with Linuxant DriverLoader) - prism54 = Prism54.org driver (Intersil Prism GT/Duette/Indigo) - not yet fully implemented - hermes = Agere Systems Inc. driver (Hermes-I/Hermes-II) - madwifi = MADWIFI 802.11 support (Atheros, etc.) - atmel = ATMEL AT76C5XXx (USB, PCMCIA) - wext = Linux wireless extensions (generic) - ndiswrapper = Linux ndiswrapper - broadcom = Broadcom wl.o driver - ipw = Intel ipw2100/2200 driver - bsd = BSD 802.11 support (Atheros, etc.) - ndis = Windows NDIS driver - -In most common cases, wpa_supplicant is started with - -wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0 - -This makes the process fork into background and wait for the wlan0 -interface if it is not available at startup time. - -The easiest way to debug problems, and to get debug log for bug -reports, is to start wpa_supplicant on foreground with debugging -enabled: - -wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d - - -wpa_supplicant can control multiple interfaces (radios) either by -running one process for each interface separately or by running just -one process and list of options at command line. Each interface is -separated with -N argument. As an example, following command would -start wpa_supplicant for two interfaces: - -wpa_supplicant \ - -c wpa1.conf -i wlan0 -D hostap -N \ - -c wpa2.conf -i ath0 -D madwifi - - -Configuration file ------------------- - -wpa_supplicant is configured using a text file that lists all accepted -networks and security policies, including pre-shared keys. See -example configuration file, wpa_supplicant.conf, for detailed -information about the configuration format and supported fields. - -Changes to configuration file can be reloaded be sending SIGHUP signal -to wpa_supplicant ('killall -HUP wpa_supplicant'). Similarly, -reloading can be triggered with 'wpa_cli reconfigure' command. - -Configuration file can include one or more network blocks, e.g., one -for each used SSID. wpa_supplicant will automatically select the best -betwork based on the order of network blocks in the configuration -file, network security level (WPA/WPA2 is prefered), and signal -strength. - -Example configuration files for some common configurations: - -1) WPA-Personal (PSK) as home network and WPA-Enterprise with EAP-TLS as work - network - -# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -# -# home network; allow all valid ciphers -network={ - ssid="home" - scan_ssid=1 - key_mgmt=WPA-PSK - psk="very secret passphrase" -} -# -# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers -network={ - ssid="work" - scan_ssid=1 - key_mgmt=WPA-EAP - pairwise=CCMP TKIP - group=CCMP TKIP - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" -} - - -2) WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that use old peaplabel - (e.g., Funk Odyssey and SBR, Meetinghouse Aegis, Interlink RAD-Series) - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=PEAP - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase1="peaplabel=0" - phase2="auth=MSCHAPV2" -} - - -3) EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the - unencrypted use. Real identity is sent only within an encrypted TLS tunnel. - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase2="auth=MD5" -} - - -4) IEEE 802.1X (i.e., no WPA) with dynamic WEP keys (require both unicast and - broadcast); use EAP-TLS for authentication - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="1x-test" - scan_ssid=1 - key_mgmt=IEEE8021X - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - eapol_flags=3 -} - - -5) Catch all example that allows more or less all configuration modes. The - configuration options are used based on what security policy is used in the - selected SSID. This is mostly for testing and is not recommended for normal - use. - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk="very secret passphrase" - eap=TTLS PEAP TLS - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - phase1="peaplabel=0" - ca_cert2="/etc/cert/ca2.pem" - client_cert2="/etc/cer/user.pem" - private_key2="/etc/cer/user.prv" - private_key2_passwd="password" -} - - - -Certificates ------------- - -Some EAP authentication methods require use of certificates. EAP-TLS -uses both server side and client certificates whereas EAP-PEAP and -EAP-TTLS only require the server side certificate. When client -certificate is used, a matching private key file has to also be -included in configuration. If the private key uses a passphrase, this -has to be configured in wpa_supplicant.conf ("private_key_passwd"). - -wpa_supplicant supports X.509 certificates in PEM and DER -formats. User certificate and private key can be included in the same -file. - -If the user certificate and private key is received in PKCS#12/PFX -format, they need to be converted to suitable PEM/DER format for -wpa_supplicant. This can be done, e.g., with following commands: - -# convert client certificate and private key to PEM format -openssl pkcs12 -in example.pfx -out user.pem -clcerts -# convert CA certificate (if included in PFX file) to PEM format -openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys - - - -wpa_cli -------- - -wpa_cli is a text-based frontend program for interacting with -wpa_supplicant. It is used to query current status, change -configuration, trigger events, and request interactive user input. - -wpa_cli can show the current authentication status, selected security -mode, dot11 and dot1x MIBs, etc. In addition, it can configuring some -variables like EAPOL state machine parameters and trigger events like -reassociation and IEEE 802.1X logoff/logon. wpa_cli provides a user -interface to request authentication information, like username and -password, if these are not included in the configuration. This can be -used to implement, e.g., one-time-passwords or generic token card -authentication where the authentication is based on a -challenge-response that uses an external device for generating the -response. - -The control interface of wpa_supplicant can be configured to allow -non-root user access (ctrl_interface_group in the configuration -file). This makes it possible to run wpa_cli with a normal user -account. - -wpa_cli supports two modes: interactive and command line. Both modes -share the same command set and the main difference is in interactive -mode providing access to unsolicited messages (event messages, -username/password requests). - -Interactive mode is started when wpa_cli is executed without including -the command as a command line parameter. Commands are then entered on -the wpa_cli prompt. In command line mode, the same commands are -entered as command line arguments for wpa_cli. - - -Interactive authentication parameters request - -When wpa_supplicant need authentication parameters, like username and -password, which are not present in the configuration file, it sends a -request message to all attached frontend programs, e.g., wpa_cli in -interactive mode. wpa_cli shows these requests with -"CTRL-REQ-<type>-<id>:<text>" prefix. <type> is IDENTITY, PASSWORD, or -OTP (one-time-password). <id> is a unique identifier for the current -network. <text> is description of the request. In case of OTP request, -it includes the challenge from the authentication server. - -The reply to these requests can be given with 'identity', 'password', -and 'otp' commands. <id> needs to be copied from the the matching -request. 'password' and 'otp' commands can be used regardless of -whether the request was for PASSWORD or OTP. The main difference -between these two commands is that values given with 'password' are -remembered as long as wpa_supplicant is running whereas values given -with 'otp' are used only once and then forgotten, i.e., wpa_supplicant -will ask frontend for a new value for every use. This can be used to -implement one-time-password lists and generic token card -based -authentication. - -Example request for password and a matching reply: - -CTRL-REQ-PASSWORD-1:Password needed for SSID foobar -> password 1 mysecretpassword - -Example request for generic token card challenge-response: - -CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar -> otp 2 9876 - - -wpa_cli commands - - status = get current WPA/EAPOL/EAP status - mib = get MIB variables (dot1x, dot11) - help = show this usage help - interface [ifname] = show interfaces/select interface - level <debug level> = change debug level - license = show full wpa_cli license - logoff = IEEE 802.1X EAPOL state machine logoff - logon = IEEE 802.1X EAPOL state machine logon - set = set variables (shows list of variables when run without arguments) - pmksa = show PMKSA cache - reassociate = force reassociation - reconfigure = force wpa_supplicant to re-read its configuration file - preauthenticate <BSSID> = force preauthentication - identity <network id> <identity> = configure identity for an SSID - password <network id> <password> = configure password for an SSID - otp <network id> <password> = configure one-time-password for an SSID - terminate = terminate wpa_supplicant - quit = exit wpa_cli - - - -Integrating with pcmcia-cs/cardmgr scripts ------------------------------------------- - -wpa_supplicant needs to be running when using a wireless network with -WPA. It can be started either from system startup scripts or from -pcmcia-cs/cardmgr scripts (when using PC Cards). WPA handshake must be -completed before data frames can be exchanged, so wpa_supplicant -should be started before DHCP client. - -Command line option '-w' can be used if wpa_supplicant is started -before the wireless LAN interface is present (e.g., before inserting -the PC Card) or is not yet up. - -For example, following small changes to pcmcia-cs scripts can be used -to enable WPA support: - -Add MODE="Managed" and WPA="y" to the network scheme in -/etc/pcmcia/wireless.opts. - -Add the following block to the end of 'start' action handler in -/etc/pcmcia/wireless: - - if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - /usr/local/bin/wpa_supplicant -Bw -c/etc/wpa_supplicant.conf \ - -i$DEVICE - fi - -Add the following block to the end of 'stop' action handler (may need -to be separated from other actions) in /etc/pcmcia/wireless: - - if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - killall wpa_supplicant - fi - -This will make cardmgr start wpa_supplicant when the card is plugged -in. wpa_supplicant will wait until the interface is set up--either -when a static IP address is configured or when DHCP client is -started--and will then negotiate keys with the AP. - - - -Optional integration with Xsupplicant -------------------------------------- - -wpa_supplicant has an integrated IEEE 802.1X Supplicant that supports -most commonly used EAP methods. In addition, wpa_supplicant has an -experimental interface for integrating it with Xsupplicant -(http://www.open1x.org/) for the WPA with EAP authentication. - -When using WPA-EAP, both wpa_supplicant and Xsupplicant must be -configured with the network security policy. See Xsupplicant documents -for information about its configuration. Please also note, that a new -command line option -W (enable WPA) must be used when starting -xsupplicant. - -Example configuration for xsupplicant: - -network_list = all -default_netname = jkm - -jkm -{ - type = wireless - allow_types = eap_peap - identity = <BEGIN_ID>jkm<END_ID> - eap-peap { - random_file = /dev/urandom - root_cert = /home/jkm/CA.pem - chunk_size = 1398 - allow_types = eap_mschapv2 - eap-mschapv2 { - username = <BEGIN_UNAME>jkm<END_UNAME> - password = <BEGIN_PASS>jkm<END_PASS> - } - } -} - - -Example configuration for wpa_supplicant: - -network={ - ssid="jkm" - key_mgmt=WPA-EAP -} - - -Both wpa_supplicant and xsupplicant need to be started. Please remember -to add '-W' option for xsupplicant in order to provide keying material -for wpa_supplicant and '-e' option for wpa_supplicant to disable internal -IEEE 802.1X implementation. - -wpa_supplicant -iwlan0 -cwpa_supplicant.conf -e -xsupplicant -iwlan0 -cxsupplicant.conf -W diff --git a/contrib/wpa_supplicant/aes.c b/contrib/wpa_supplicant/aes.c deleted file mode 100644 index eabebd074653..000000000000 --- a/contrib/wpa_supplicant/aes.c +++ /dev/null @@ -1,1132 +0,0 @@ -/* - * Modifications to public domain implementation: - * - support only 128-bit keys - * - cleanup - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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. - */ - -/** - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> - * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> - * @author Paulo Barreto <paulo.barreto@terra.com.br> - * - * 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. - */ - -#define FULL_UNROLL - - -/* -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]; -*/ - -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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 */ -}; - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#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 - -/** - * 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] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - rk += 4; - } -} - -/** - * 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; - rk[0] = - Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[0] ) & 0xff] & 0xff]; - rk[1] = - Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[1] ) & 0xff] & 0xff]; - rk[2] = - Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[2] ) & 0xff] & 0xff]; - rk[3] = - Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[3] ) & 0xff] & 0xff]; - } -} - -void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - 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]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; - rk += Nr << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - t0 = - Te0[(s0 >> 24) ] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[4]; - t1 = - Te0[(s1 >> 24) ] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[5]; - t2 = - Te0[(s2 >> 24) ] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[6]; - t3 = - Te0[(s3 >> 24) ] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Te0[(t0 >> 24) ] ^ - Te1[(t1 >> 16) & 0xff] ^ - Te2[(t2 >> 8) & 0xff] ^ - Te3[(t3 ) & 0xff] ^ - rk[0]; - s1 = - Te0[(t1 >> 24) ] ^ - Te1[(t2 >> 16) & 0xff] ^ - Te2[(t3 >> 8) & 0xff] ^ - Te3[(t0 ) & 0xff] ^ - rk[1]; - s2 = - Te0[(t2 >> 24) ] ^ - Te1[(t3 >> 16) & 0xff] ^ - Te2[(t0 >> 8) & 0xff] ^ - Te3[(t1 ) & 0xff] ^ - rk[2]; - s3 = - Te0[(t3 >> 24) ] ^ - Te1[(t0 >> 16) & 0xff] ^ - Te2[(t1 >> 8) & 0xff] ^ - Te3[(t2 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Te4[(t0 >> 24) ] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(ct , s0); - s1 = - (Te4[(t1 >> 24) ] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(ct + 4, s1); - s2 = - (Te4[(t2 >> 24) ] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(ct + 8, s2); - s3 = - (Te4[(t3 >> 24) ] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(ct + 12, s3); -} - -void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - 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]; -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; - s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; - s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; - s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; - t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; - t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; - t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; - rk += Nr << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - t0 = - Td0[(s0 >> 24) ] ^ - Td1[(s3 >> 16) & 0xff] ^ - Td2[(s2 >> 8) & 0xff] ^ - Td3[(s1 ) & 0xff] ^ - rk[4]; - t1 = - Td0[(s1 >> 24) ] ^ - Td1[(s0 >> 16) & 0xff] ^ - Td2[(s3 >> 8) & 0xff] ^ - Td3[(s2 ) & 0xff] ^ - rk[5]; - t2 = - Td0[(s2 >> 24) ] ^ - Td1[(s1 >> 16) & 0xff] ^ - Td2[(s0 >> 8) & 0xff] ^ - Td3[(s3 ) & 0xff] ^ - rk[6]; - t3 = - Td0[(s3 >> 24) ] ^ - Td1[(s2 >> 16) & 0xff] ^ - Td2[(s1 >> 8) & 0xff] ^ - Td3[(s0 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Td0[(t0 >> 24) ] ^ - Td1[(t3 >> 16) & 0xff] ^ - Td2[(t2 >> 8) & 0xff] ^ - Td3[(t1 ) & 0xff] ^ - rk[0]; - s1 = - Td0[(t1 >> 24) ] ^ - Td1[(t0 >> 16) & 0xff] ^ - Td2[(t3 >> 8) & 0xff] ^ - Td3[(t2 ) & 0xff] ^ - rk[1]; - s2 = - Td0[(t2 >> 24) ] ^ - Td1[(t1 >> 16) & 0xff] ^ - Td2[(t0 >> 8) & 0xff] ^ - Td3[(t3 ) & 0xff] ^ - rk[2]; - s3 = - Td0[(t3 >> 24) ] ^ - Td1[(t2 >> 16) & 0xff] ^ - Td2[(t1 >> 8) & 0xff] ^ - Td3[(t0 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Td4[(t0 >> 24) ] & 0xff000000) ^ - (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(pt , s0); - s1 = - (Td4[(t1 >> 24) ] & 0xff000000) ^ - (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(pt + 4, s1); - s2 = - (Td4[(t2 >> 24) ] & 0xff000000) ^ - (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(pt + 8, s2); - s3 = - (Td4[(t3 >> 24) ] & 0xff000000) ^ - (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(pt + 12, s3); -} diff --git a/contrib/wpa_supplicant/aes_wrap.c b/contrib/wpa_supplicant/aes_wrap.c deleted file mode 100644 index dbcc136517e7..000000000000 --- a/contrib/wpa_supplicant/aes_wrap.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * 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-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "common.h" -#include "aes_wrap.h" - -#ifdef EAP_TLS_FUNCS - -#include <openssl/aes.h> - -#else /* EAP_TLS_FUNCS */ - -#include "aes.c" - -struct aes_key_st { - u32 rk[44]; -}; -typedef struct aes_key_st AES_KEY; - -#define AES_set_encrypt_key(userKey, bits, key) \ - rijndaelKeySetupEnc((key)->rk, (userKey)) -#define AES_set_decrypt_key(userKey, bits, key) \ - rijndaelKeySetupDec((key)->rk, (userKey)) -#define AES_encrypt(in, out, key) \ - rijndaelEncrypt((key)->rk, in, out) -#define AES_decrypt(in, out, key) \ - rijndaelDecrypt((key)->rk, in, out) - -#endif /* EAP_TLS_FUNCS */ - - -/* - * @kek: key encryption key (KEK) - * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes - * @plain: plaintext key to be wrapped, n * 64 bit - * @cipher: wrapped key, (n + 1) * 64 bit - */ -void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher) -{ - u8 *a, *r, b[16]; - int i, j; - AES_KEY key; - - a = cipher; - r = cipher + 8; - - /* 1) Initialize variables. */ - memset(a, 0xa6, 8); - memcpy(r, plain, 8 * n); - - AES_set_encrypt_key(kek, 128, &key); - - /* 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++) { - memcpy(b, a, 8); - memcpy(b + 8, r, 8); - AES_encrypt(b, b, &key); - memcpy(a, b, 8); - a[7] ^= n * j + i; - memcpy(r, b + 8, 8); - r += 8; - } - } - - /* 3) Output the results. - * - * These are already in @cipher due to the location of temporary - * variables. - */ -} - - -/* - * @kek: key encryption key (KEK) - * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes - * @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit - * @plain: plaintext key, n * 64 bit - */ -int aes_unwrap(u8 *kek, int n, u8 *cipher, u8 *plain) -{ - u8 a[8], *r, b[16]; - int i, j; - AES_KEY key; - - /* 1) Initialize variables. */ - memcpy(a, cipher, 8); - r = plain; - memcpy(r, cipher + 8, 8 * n); - - AES_set_decrypt_key(kek, 128, &key); - - /* 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--) { - memcpy(b, a, 8); - b[7] ^= n * j + i; - - memcpy(b + 8, r, 8); - AES_decrypt(b, b, &key); - memcpy(a, b, 8); - memcpy(r, b + 8, 8); - r -= 8; - } - } - - /* 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; -} - - -#define BLOCK_SIZE 16 - -static void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[BLOCK_SIZE - 1] ^= 0x87; -} - - -void omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) -{ - AES_KEY akey; - u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE]; - const u8 *pos = data; - int i; - size_t left = data_len; - - AES_set_encrypt_key(key, 128, &akey); - memset(cbc, 0, BLOCK_SIZE); - - while (left >= BLOCK_SIZE) { - for (i = 0; i < BLOCK_SIZE; i++) - cbc[i] ^= *pos++; - if (left > BLOCK_SIZE) - AES_encrypt(cbc, cbc, &akey); - left -= BLOCK_SIZE; - } - - memset(pad, 0, BLOCK_SIZE); - AES_encrypt(pad, pad, &akey); - gf_mulx(pad); - - if (left || data_len == 0) { - for (i = 0; i < left; i++) - cbc[i] ^= *pos++; - cbc[left] ^= 0x80; - gf_mulx(pad); - } - - for (i = 0; i < BLOCK_SIZE; i++) - pad[i] ^= cbc[i]; - AES_encrypt(pad, mac, &akey); -} - - -void aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) -{ - AES_KEY akey; - AES_set_encrypt_key(key, 128, &akey); - AES_encrypt(in, out, &akey); -} - - -void aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len) -{ - AES_KEY akey; - size_t len, left = data_len; - int i; - u8 *pos = data; - u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE]; - - AES_set_encrypt_key(key, 128, &akey); - memcpy(counter, nonce, BLOCK_SIZE); - - while (left > 0) { - AES_encrypt(counter, buf, &akey); - - len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE; - for (i = 0; i < len; i++) - pos[i] ^= buf[i]; - pos += len; - left -= len; - - for (i = BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } -} - - -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[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[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 = malloc(buf_len); - if (buf == NULL) - return -1; - - memset(buf, 0, 15); - - buf[15] = 0; - memcpy(buf + 16, nonce, nonce_len); - omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac); - - buf[15] = 1; - memcpy(buf + 16, hdr, hdr_len); - omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac); - - aes_128_ctr_encrypt(key, nonce_mac, data, data_len); - buf[15] = 2; - memcpy(buf + 16, data, data_len); - omac1_aes_128(key, buf, 16 + data_len, data_mac); - - free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) - tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; - - return 0; -} - - -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[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[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 = malloc(buf_len); - if (buf == NULL) - return -1; - - memset(buf, 0, 15); - - buf[15] = 0; - memcpy(buf + 16, nonce, nonce_len); - omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac); - - buf[15] = 1; - memcpy(buf + 16, hdr, hdr_len); - omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac); - - buf[15] = 2; - memcpy(buf + 16, data, data_len); - omac1_aes_128(key, buf, 16 + data_len, data_mac); - - free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) { - if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) - return -2; - } - - aes_128_ctr_encrypt(key, nonce_mac, data, data_len); - - return 0; -} - - -void aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len) -{ - AES_KEY akey; - u8 cbc[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - AES_set_encrypt_key(key, 128, &akey); - memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - AES_encrypt(cbc, cbc, &akey); - memcpy(pos, cbc, BLOCK_SIZE); - pos += BLOCK_SIZE; - } -} - - -void aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len) -{ - AES_KEY akey; - u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - AES_set_decrypt_key(key, 128, &akey); - memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - memcpy(tmp, pos, BLOCK_SIZE); - AES_decrypt(pos, pos, &akey); - for (j = 0; j < BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - memcpy(cbc, tmp, BLOCK_SIZE); - pos += BLOCK_SIZE; - } -} - - -#ifdef TEST_MAIN - -#ifdef __i386__ -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - -static void test_aes_perf(void) -{ - const int num_iters = 10; - int i; - unsigned int start, end; - AES_KEY akey; - u8 key[16], pt[16], ct[16]; - - printf("keySetupEnc:"); - for (i = 0; i < num_iters; i++) { - rdtscll(start); - AES_set_encrypt_key(key, 128, &akey); - rdtscll(end); - printf(" %d", end - start); - } - printf("\n"); - - printf("Encrypt:"); - for (i = 0; i < num_iters; i++) { - rdtscll(start); - AES_encrypt(pt, ct, &akey); - rdtscll(end); - printf(" %d", end - start); - } - printf("\n"); -} -#endif /* __i386__ */ - - -static int test_eax(void) -{ - u8 msg[] = { 0xF7, 0xFB }; - u8 key[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B, - 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 }; - u8 nonce[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84, - 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD }; - u8 hdr[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA }; - u8 cipher[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D, - 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79, - 0x67, 0xE5 }; - u8 data[sizeof(msg)], tag[BLOCK_SIZE]; - - memcpy(data, msg, sizeof(msg)); - if (aes_128_eax_encrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr), - data, sizeof(data), tag)) { - printf("AES-128 EAX mode encryption failed\n"); - return 1; - } - if (memcmp(data, cipher, sizeof(data)) != 0) { - printf("AES-128 EAX mode encryption returned invalid cipher " - "text\n"); - return 1; - } - if (memcmp(tag, cipher + sizeof(data), BLOCK_SIZE) != 0) { - printf("AES-128 EAX mode encryption returned invalid tag\n"); - return 1; - } - - if (aes_128_eax_decrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr), - data, sizeof(data), tag)) { - printf("AES-128 EAX mode decryption failed\n"); - return 1; - } - if (memcmp(data, msg, sizeof(data)) != 0) { - printf("AES-128 EAX mode decryption returned invalid plain " - "text\n"); - return 1; - } - - return 0; -} - - -static int test_cbc(void) -{ - struct cbc_test_vector { - u8 key[16]; - u8 iv[16]; - u8 plain[32]; - u8 cipher[32]; - size_t len; - } vectors[] = { - { - { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, - 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 }, - { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, - 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 }, - "Single block msg", - { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, - 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a }, - 16 - }, - { - { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, - 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a }, - { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, - 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, - 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a, - 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, - 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 }, - 32 - } - }; - int i, ret = 0; - u8 *buf; - - for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { - struct cbc_test_vector *tv = &vectors[i]; - buf = malloc(tv->len); - if (buf == NULL) { - ret++; - break; - } - memcpy(buf, tv->plain, tv->len); - aes_128_cbc_encrypt(tv->key, tv->iv, buf, tv->len); - if (memcmp(buf, tv->cipher, tv->len) != 0) { - printf("AES-CBC encrypt %d failed\n", i); - ret++; - } - memcpy(buf, tv->cipher, tv->len); - aes_128_cbc_decrypt(tv->key, tv->iv, buf, tv->len); - if (memcmp(buf, tv->plain, tv->len) != 0) { - printf("AES-CBC decrypt %d failed\n", i); - ret++; - } - free(buf); - } - - return ret; -} - - -/* OMAC1 AES-128 test vectors from - * http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf - */ - -struct omac1_test_vector { - u8 k[16]; - u8 msg[64]; - int msg_len; - u8 tag[16]; -}; - -static struct omac1_test_vector test_vectors[] = -{ - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { }, - 0, - { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, - 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } - }, - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}, - 16, - { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, - 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } - }, - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, - 40, - { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, - 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } - }, - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, - 64, - { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, - 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } - }, -}; - - -int main(int argc, char *argv[]) -{ - u8 kek[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - }; - u8 plain[] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff - }; - u8 crypt[] = { - 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, - 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, - 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 - }; - u8 result[24]; - int ret = 0, i; - struct omac1_test_vector *tv; - - aes_wrap(kek, 2, plain, result); - if (memcmp(result, crypt, 24) != 0) { - printf("AES-WRAP-128-128 failed\n"); - ret++; - } - if (aes_unwrap(kek, 2, crypt, result)) { - printf("AES-UNWRAP-128-128 reported failure\n"); - ret++; - } - if (memcmp(result, plain, 16) != 0) { - int i; - printf("AES-UNWRAP-128-128 failed\n"); - ret++; - for (i = 0; i < 16; i++) - printf(" %02x", result[i]); - printf("\n"); - } - -#ifdef __i386__ - test_aes_perf(); -#endif /* __i386__ */ - - for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) { - tv = &test_vectors[i]; - omac1_aes_128(tv->k, tv->msg, tv->msg_len, result); - if (memcmp(result, tv->tag, 16) != 0) { - printf("OMAC1-AES-128 test vector %d failed\n", i); - ret++; - } - } - - ret += test_eax(); - - ret += test_cbc(); - - if (ret) - printf("FAILED!\n"); - - return ret; -} -#endif /* TEST_MAIN */ diff --git a/contrib/wpa_supplicant/aes_wrap.h b/contrib/wpa_supplicant/aes_wrap.h deleted file mode 100644 index 70e83ea09d73..000000000000 --- a/contrib/wpa_supplicant/aes_wrap.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef AES_WRAP_H -#define AES_WRAP_H - -void aes_wrap(u8 *kek, int n, u8 *plain, u8 *cipher); -int aes_unwrap(u8 *kek, int n, u8 *cipher, u8 *plain); -void omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); -void aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); -void aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len); -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); -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); -void aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -void aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); - -#endif /* AES_WRAP_H */ diff --git a/contrib/wpa_supplicant/common.c b/contrib/wpa_supplicant/common.c deleted file mode 100644 index 071ffe87c1d1..000000000000 --- a/contrib/wpa_supplicant/common.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Host AP (software wireless LAN access point) user space daemon for - * Host AP kernel driver / common helper functions, etc. - * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <stdarg.h> -#include <ctype.h> -#include <time.h> -#include <sys/time.h> - -#include "common.h" - - -int wpa_debug_level = MSG_INFO; -int wpa_debug_show_keys = 0; -int wpa_debug_timestamp = 0; - - -int hostapd_get_rand(u8 *buf, size_t len) -{ -#ifdef CONFIG_NATIVE_WINDOWS - int i; - /* FIX: use more secure pseudo random number generator */ - for (i = 0; i < len; i++) { - buf[i] = rand(); - } - return 0; -#else /* CONFIG_NATIVE_WINDOWS */ - FILE *f; - size_t rc; - - f = fopen("/dev/urandom", "r"); - 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; -#endif /* CONFIG_NATIVE_WINDOWS */ -} - - -void hostapd_hexdump(const char *title, const u8 *buf, size_t len) -{ - size_t i; - printf("%s - hexdump(len=%lu):", title, (unsigned long) len); - for (i = 0; i < len; i++) - printf(" %02x", buf[i]); - printf("\n"); -} - - -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; -} - - -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; -} - - -int hexstr2bin(const char *hex, u8 *buf, size_t len) -{ - int i, 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; -} - - -char * 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 strdup(rel_path); - - for (;;) { - buf = malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - 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 = malloc(ret_len); - if (ret) { - memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - free(buf); - return ret; -} - - -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 print_char(char c) -{ - if (c >= 32 && c < 127) - printf("%c", c); - else - printf("<%02x>", c); -} - - -void fprint_char(FILE *f, char c) -{ - if (c >= 32 && c < 127) - fprintf(f, "%c", c); - else - fprintf(f, "<%02x>", c); -} - - -static void wpa_debug_print_timestamp(void) -{ - struct timeval tv; - char buf[16]; - - if (!wpa_debug_timestamp) - return; - - gettimeofday(&tv, NULL); - if (strftime(buf, sizeof(buf), "%b %d %H:%M:%S", - localtime((const time_t *) &tv.tv_sec)) <= 0) { - snprintf(buf, sizeof(buf), "%u", (int) tv.tv_sec); - } - printf("%s.%06u: ", buf, (unsigned int) tv.tv_usec); -} - - -void wpa_printf(int level, char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (level >= wpa_debug_level) { - wpa_debug_print_timestamp(); - vprintf(fmt, ap); - printf("\n"); - } - va_end(ap); -} - - -static void _wpa_hexdump(int level, const char *title, const u8 *buf, - size_t len, int show) -{ - size_t i; - if (level < wpa_debug_level) - return; - wpa_debug_print_timestamp(); - printf("%s - hexdump(len=%lu):", title, (unsigned long) len); - if (show) { - for (i = 0; i < len; i++) - printf(" %02x", buf[i]); - } else { - printf(" [REMOVED]"); - } - printf("\n"); -} - -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) -{ - int i, llen; - const u8 *pos = buf; - const int line_len = 16; - - if (level < wpa_debug_level) - return; - wpa_debug_print_timestamp(); - if (!show) { - printf("%s - hexdump_ascii(len=%lu): [REMOVED]\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; - } -} - - -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); -} - - -#ifdef CONFIG_NATIVE_WINDOWS - -#define EPOCHFILETIME (116444736000000000ULL) - -int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - LARGE_INTEGER li; - ULONGLONG t; - - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = (li.QuadPart - EPOCHFILETIME) / 10; - tv->tv_sec = (long) (t / 1000000); - tv->tv_usec = (long) (t % 1000000); - - return 0; -} -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/wpa_supplicant/common.h b/contrib/wpa_supplicant/common.h deleted file mode 100644 index 0f154e901bff..000000000000 --- a/contrib/wpa_supplicant/common.h +++ /dev/null @@ -1,226 +0,0 @@ -#ifndef COMMON_H -#define COMMON_H - -#ifdef __linux__ -#include <endian.h> -#include <byteswap.h> -#endif -#ifdef __FreeBSD__ -#include <sys/types.h> -#include <sys/endian.h> -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#define bswap_16 bswap16 -#define bswap_32 bswap32 -#define bswap_64 bswap64 -#endif - -#ifdef CONFIG_NATIVE_WINDOWS -#include <winsock.h> -#include <winsock2.h> - -static inline int daemon(int nochdir, int noclose) -{ - printf("Windows - daemon() not supported yet\n"); - return -1; -} - -static inline void sleep(int seconds) -{ - Sleep(seconds * 1000); -} - -static inline void usleep(unsigned long usec) -{ - Sleep(usec / 1000); -} - -#ifndef timersub -#define timersub(a, b, res) do { \ - (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ - (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ - if ((res)->tv_usec < 0) { \ - (res)->tv_sec--; \ - (res)->tv_usec += 1000000; \ - } \ -} while (0) -#endif - -struct timezone { - int tz_minuteswest; - int tz_dsttime; -}; - -int gettimeofday(struct timeval *tv, struct timezone *tz); - -#endif /* CONFIG_NATIVE_WINDOWS */ - -#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) - -#else /* __CYGWIN__ */ - -#if __BYTE_ORDER == __LITTLE_ENDIAN -#define le_to_host16(n) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) bswap_16(n) -#define host_to_be16(n) bswap_16(n) -#define le_to_host32(n) (n) -#define be_to_host32(n) bswap_32(n) -#define host_to_be32(n) bswap_32(n) -#elif __BYTE_ORDER == __BIG_ENDIAN -#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) -#ifndef WORDS_BIGENDIAN -#define WORDS_BIGENDIAN -#endif -#else -#error Could not determine CPU byte order -#endif - -#endif /* __CYGWIN__ */ - - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif - -#include <stdint.h> -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; - -int hostapd_get_rand(u8 *buf, size_t len); -void hostapd_hexdump(const char *title, const u8 *buf, size_t len); -int hwaddr_aton(const char *txt, u8 *addr); -int hexstr2bin(const char *hex, u8 *buf, size_t len); -char * rel2abs_path(const char *rel_path); -void inc_byte_array(u8 *counter, size_t len); -void print_char(char c); -void fprint_char(FILE *f, char c); - - -/* 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 }; - -/** - * 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, char *fmt, ...) -__attribute__ ((format (printf, 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); - -/** - * 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); - -/** - * 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); - -#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 /* COMMON_H */ diff --git a/contrib/wpa_supplicant/config.c b/contrib/wpa_supplicant/config.c deleted file mode 100644 index 26307cf3f80b..000000000000 --- a/contrib/wpa_supplicant/config.c +++ /dev/null @@ -1,1051 +0,0 @@ -/* - * WPA Supplicant / Configuration file parser - * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "wpa.h" -#include "config.h" -#include "sha1.h" -#include "wpa_supplicant.h" -#include "eapol_sm.h" -#include "eap.h" -#include "config.h" - - -struct parse_data { - char *name; - int (*parser)(struct parse_data *data, int line, const char *value); - void *param1, *param2, *param3, *param4; - struct wpa_ssid *ssid; - int key_data; -}; - - -static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line) -{ - char *pos, *end, *sstart; - - while (fgets(s, size, stream)) { - (*line)++; - s[size - 1] = '\0'; - pos = s; - - while (*pos == ' ' || *pos == '\t' || *pos == '\r') - pos++; - if (*pos == '#' || *pos == '\n' || *pos == '\0' || - *pos == '\r') - continue; - - /* Remove # comments unless they are within a double quoted - * string. Remove trailing white space. */ - sstart = strchr(pos, '"'); - if (sstart) - sstart = strchr(sstart + 1, '"'); - if (!sstart) - sstart = pos; - end = strchr(sstart, '#'); - if (end) - *end-- = '\0'; - else - end = pos + strlen(pos) - 1; - while (end > pos && - (*end == '\n' || *end == ' ' || *end == '\t' || - *end == '\r')) { - *end-- = '\0'; - } - if (*pos == '\0') - continue; - - return pos; - } - - return NULL; -} - - -static char * wpa_config_parse_string(const char *value, size_t *len) -{ - if (*value == '"') { - char *pos; - value++; - pos = strchr(value, '"'); - if (pos == NULL || pos[1] != '\0') - return NULL; - *pos = '\0'; - *len = strlen(value); - return strdup(value); - } else { - u8 *str; - int hlen = strlen(value); - if (hlen % 1) - return NULL; - *len = hlen / 2; - str = malloc(*len); - if (str == NULL) - return NULL; - if (hexstr2bin(value, str, *len)) { - free(str); - return NULL; - } - return (char *) str; - } -} - - -static int wpa_config_parse_str(struct parse_data *data, - int line, const char *value) -{ - size_t res_len, *dst_len; - char **dst; - - dst = (char **) (((u8 *) data->ssid) + (long) data->param1); - dst_len = (size_t *) (((u8 *) data->ssid) + (long) data->param2); - - free(*dst); - *dst = wpa_config_parse_string(value, &res_len); - if (*dst == NULL) { - wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", - line, data->name, value); - return -1; - } - if (data->param2) - *dst_len = res_len; - - if (data->key_data) { - wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, - (u8 *) *dst, res_len); - } else { - wpa_hexdump_ascii(MSG_MSGDUMP, data->name, - (u8 *) *dst, res_len); - } - - if (data->param3 && res_len < (size_t) data->param3) { - wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " - "min_len=%ld)", line, data->name, - (unsigned long) res_len, (long) data->param3); - free(*dst); - *dst = NULL; - return -1; - } - - if (data->param4 && res_len > (size_t) data->param4) { - wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " - "max_len=%ld)", line, data->name, - (unsigned long) res_len, (long) data->param4); - free(*dst); - *dst = NULL; - return -1; - } - - return 0; -} - - -static int wpa_config_parse_int(struct parse_data *data, - int line, const char *value) -{ - int *dst; - - dst = (int *) (((u8 *) data->ssid) + (long) data->param1); - *dst = atoi(value); - wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); - - if (data->param3 && *dst < (long) data->param3) { - wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " - "min_value=%ld)", line, data->name, *dst, - (long) data->param3); - *dst = (long) data->param3; - return -1; - } - - if (data->param4 && *dst > (long) data->param4) { - wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " - "max_value=%ld)", line, data->name, *dst, - (long) data->param4); - *dst = (long) data->param4; - return -1; - } - - return 0; -} - - -static int wpa_config_parse_bssid(struct parse_data *data, int line, - const char *value) -{ - if (hwaddr_aton(value, data->ssid->bssid)) { - wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", - line, value); - return -1; - } - data->ssid->bssid_set = 1; - wpa_hexdump(MSG_MSGDUMP, "BSSID", data->ssid->bssid, ETH_ALEN); - return 0; -} - - -static int wpa_config_parse_psk(struct parse_data *data, int line, - const char *value) -{ - if (*value == '"') { - char *pos; - int len; - - value++; - pos = strrchr(value, '"'); - if (pos) - *pos = '\0'; - len = strlen(value); - if (len < 8 || len > 63) { - wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " - "length %d (expected: 8..63) '%s'.", - line, len, value); - return -1; - } - wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", - (u8 *) value, len); - data->ssid->passphrase = strdup(value); - return data->ssid->passphrase == NULL ? -1 : 0; - } - - if (hexstr2bin(value, data->ssid->psk, PMK_LEN) || - value[PMK_LEN * 2] != '\0') { - wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", - line, value); - return -1; - } - data->ssid->psk_set = 1; - wpa_hexdump_key(MSG_MSGDUMP, "PSK", data->ssid->psk, PMK_LEN); - return 0; -} - - -static int wpa_config_parse_proto(struct parse_data *data, int line, - const char *value) -{ - int val = 0, last, errors = 0; - char *start, *end, *buf; - - buf = strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (strcmp(start, "WPA") == 0) - val |= WPA_PROTO_WPA; - else if (strcmp(start, "RSN") == 0 || - strcmp(start, "WPA2") == 0) - val |= WPA_PROTO_RSN; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", - line, start); - errors++; - } - - if (last) - break; - start = end + 1; - } - free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, - "Line %d: no proto values configured.", line); - errors++; - } - - wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); - data->ssid->proto = val; - return errors ? -1 : 0; -} - - -static int wpa_config_parse_key_mgmt(struct parse_data *data, int line, - const char *value) -{ - int val = 0, last, errors = 0; - char *start, *end, *buf; - - buf = strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (strcmp(start, "WPA-PSK") == 0) - val |= WPA_KEY_MGMT_PSK; - else if (strcmp(start, "WPA-EAP") == 0) - val |= WPA_KEY_MGMT_IEEE8021X; - else if (strcmp(start, "IEEE8021X") == 0) - val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; - else if (strcmp(start, "NONE") == 0) - val |= WPA_KEY_MGMT_NONE; - else if (strcmp(start, "WPA-NONE") == 0) - val |= WPA_KEY_MGMT_WPA_NONE; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", - line, start); - errors++; - } - - if (last) - break; - start = end + 1; - } - free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, - "Line %d: no key_mgmt values configured.", line); - errors++; - } - - wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); - data->ssid->key_mgmt = val; - return errors ? -1 : 0; -} - - -static int wpa_config_parse_cipher(int line, const char *value) -{ - int val = 0, last; - char *start, *end, *buf; - - buf = strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (strcmp(start, "CCMP") == 0) - val |= WPA_CIPHER_CCMP; - else if (strcmp(start, "TKIP") == 0) - val |= WPA_CIPHER_TKIP; - else if (strcmp(start, "WEP104") == 0) - val |= WPA_CIPHER_WEP104; - else if (strcmp(start, "WEP40") == 0) - val |= WPA_CIPHER_WEP40; - else if (strcmp(start, "NONE") == 0) - val |= WPA_CIPHER_NONE; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", - line, start); - free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", - line); - return -1; - } - return val; -} - - -static int wpa_config_parse_pairwise(struct parse_data *data, int line, - const char *value) -{ - int val; - val = wpa_config_parse_cipher(line, value); - if (val == -1) - return -1; - if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) { - wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " - "(0x%x).", line, val); - return -1; - } - - wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); - data->ssid->pairwise_cipher = val; - return 0; -} - - -static int wpa_config_parse_group(struct parse_data *data, int line, - const char *value) -{ - int val; - val = wpa_config_parse_cipher(line, value); - if (val == -1) - return -1; - if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | - WPA_CIPHER_WEP40)) { - wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " - "(0x%x).", line, val); - return -1; - } - - wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); - data->ssid->group_cipher = val; - return 0; -} - - -static int wpa_config_parse_auth_alg(struct parse_data *data, int line, - const char *value) -{ - int val = 0, last, errors = 0; - char *start, *end, *buf; - - buf = strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - if (strcmp(start, "OPEN") == 0) - val |= WPA_AUTH_ALG_OPEN; - else if (strcmp(start, "SHARED") == 0) - val |= WPA_AUTH_ALG_SHARED; - else if (strcmp(start, "LEAP") == 0) - val |= WPA_AUTH_ALG_LEAP; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'", - line, start); - errors++; - } - - if (last) - break; - start = end + 1; - } - free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, - "Line %d: no auth_alg values configured.", line); - errors++; - } - - wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val); - data->ssid->auth_alg = val; - return errors ? -1 : 0; -} - - -static int wpa_config_parse_eap(struct parse_data *data, int line, - const char *value) -{ - int last, errors = 0; - char *start, *end, *buf; - u8 *methods = NULL, *tmp; - size_t num_methods = 0; - - buf = strdup(value); - if (buf == NULL) - return -1; - start = buf; - - while (*start != '\0') { - while (*start == ' ' || *start == '\t') - start++; - if (*start == '\0') - break; - end = start; - while (*end != ' ' && *end != '\t' && *end != '\0') - end++; - last = *end == '\0'; - *end = '\0'; - tmp = methods; - methods = realloc(methods, num_methods + 1); - if (methods == NULL) { - free(tmp); - return -1; - } - methods[num_methods] = eap_get_type(start); - if (methods[num_methods] == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " - "'%s'", line, start); - wpa_printf(MSG_ERROR, "You may need to add support for" - " this EAP method during wpa_supplicant\n" - "build time configuration.\n" - "See README for more information."); - errors++; - } else if (methods[num_methods] == EAP_TYPE_LEAP) - data->ssid->leap++; - else - data->ssid->non_leap++; - num_methods++; - if (last) - break; - start = end + 1; - } - free(buf); - - tmp = methods; - methods = realloc(methods, num_methods + 1); - if (methods == NULL) { - free(tmp); - return -1; - } - methods[num_methods] = EAP_TYPE_NONE; - num_methods++; - - wpa_hexdump(MSG_MSGDUMP, "eap methods", methods, num_methods); - data->ssid->eap_methods = methods; - return errors ? -1 : 0; -} - - -static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, - const char *value, int idx) -{ - char *buf, title[20]; - - buf = wpa_config_parse_string(value, len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", - line, idx, value); - return -1; - } - if (*len > MAX_WEP_KEY_LEN) { - wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", - line, idx, value); - free(buf); - return -1; - } - memcpy(key, buf, *len); - free(buf); - snprintf(title, sizeof(title), "wep_key%d", idx); - wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); - return 0; -} - - -static int wpa_config_parse_wep_key0(struct parse_data *data, int line, - const char *value) -{ - return wpa_config_parse_wep_key(data->ssid->wep_key[0], - &data->ssid->wep_key_len[0], line, - value, 0); -} - - -static int wpa_config_parse_wep_key1(struct parse_data *data, int line, - const char *value) -{ - return wpa_config_parse_wep_key(data->ssid->wep_key[1], - &data->ssid->wep_key_len[1], line, - value, 1); -} - - -static int wpa_config_parse_wep_key2(struct parse_data *data, int line, - const char *value) -{ - return wpa_config_parse_wep_key(data->ssid->wep_key[2], - &data->ssid->wep_key_len[2], line, - value, 2); -} - - -static int wpa_config_parse_wep_key3(struct parse_data *data, int line, - const char *value) -{ - return wpa_config_parse_wep_key(data->ssid->wep_key[3], - &data->ssid->wep_key_len[3], line, - value, 3); -} - - -#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) -#define STR(f) .name = #f, .parser = wpa_config_parse_str, .param1 = OFFSET(f) -#define STR_LEN(f) STR(f), .param2 = OFFSET(f ## _len) -#define STR_RANGE(f, min, max) STR_LEN(f), .param3 = (void *) (min), \ - .param4 = (void *) (max) -#define INT(f) .name = #f, .parser = wpa_config_parse_int, \ - .param1 = OFFSET(f), .param2 = (void *) 0 -#define INT_RANGE(f, min, max) INT(f), .param3 = (void *) (min), \ - .param4 = (void *) (max) -#define FUNC(f) .name = #f, .parser = wpa_config_parse_ ## f - -static struct parse_data ssid_fields[] = { - { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, - { INT_RANGE(scan_ssid, 0, 1) }, - { FUNC(bssid) }, - { FUNC(psk), .key_data = 1 }, - { FUNC(proto) }, - { FUNC(key_mgmt) }, - { FUNC(pairwise) }, - { FUNC(group) }, - { FUNC(auth_alg) }, - { FUNC(eap) }, - { STR_LEN(identity) }, - { STR_LEN(anonymous_identity) }, - { STR_RANGE(eappsk, EAP_PSK_LEN, EAP_PSK_LEN), .key_data = 1 }, - { STR_LEN(nai) }, - { STR_LEN(server_nai) }, - { STR_LEN(password), .key_data = 1 }, - { STR(ca_cert) }, - { STR(client_cert) }, - { STR(private_key) }, - { STR(private_key_passwd), .key_data = 1 }, - { STR(dh_file) }, - { STR(subject_match) }, - { STR(ca_cert2) }, - { STR(client_cert2) }, - { STR(private_key2) }, - { STR(private_key2_passwd), .key_data = 1 }, - { STR(dh_file2) }, - { STR(subject_match2) }, - { STR(phase1) }, - { STR(phase2) }, - { STR(pcsc) }, - { STR(pin), .key_data = 1 }, - { INT(eapol_flags) }, - { FUNC(wep_key0), .key_data = 1 }, - { FUNC(wep_key1), .key_data = 1 }, - { FUNC(wep_key2), .key_data = 1 }, - { FUNC(wep_key3), .key_data = 1 }, - { INT(wep_tx_keyidx) }, - { INT(priority) }, - { INT(eap_workaround) }, - { STR(pac_file) }, - { INT_RANGE(mode, 0, 1) }, -}; - -#undef OFFSET -#undef STR -#undef STR_LEN -#undef STR_RANGE -#undef INT -#undef INT_RANGE -#undef FUNC -#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0])) - - -static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) -{ - struct wpa_ssid *ssid; - int errors = 0, i, end = 0; - char buf[256], *pos, *pos2; - - wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", - *line); - ssid = (struct wpa_ssid *) malloc(sizeof(*ssid)); - if (ssid == NULL) - return NULL; - memset(ssid, 0, sizeof(*ssid)); - ssid->id = id; - - ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; - ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; - ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | - WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40; - ssid->key_mgmt = WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X; - ssid->eapol_flags = EAPOL_FLAG_REQUIRE_KEY_UNICAST | - EAPOL_FLAG_REQUIRE_KEY_BROADCAST; - ssid->eap_workaround = (unsigned int) -1; - - while ((pos = wpa_config_get_line(buf, sizeof(buf), f, line))) { - if (strcmp(pos, "}") == 0) { - end = 1; - break; - } - - pos2 = strchr(pos, '='); - if (pos2 == NULL) { - wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " - "'%s'.", *line, pos); - errors++; - continue; - } - - *pos2++ = '\0'; - if (*pos2 == '"') { - if (strchr(pos2 + 1, '"') == NULL) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "quotation '%s'.", *line, pos2); - errors++; - continue; - } - } - - for (i = 0; i < NUM_SSID_FIELDS; i++) { - struct parse_data *field = &ssid_fields[i]; - if (strcmp(pos, field->name) != 0) - continue; - - field->ssid = ssid; - if (field->parser(field, *line, pos2)) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "parse %s '%s'.", *line, pos, pos2); - errors++; - } - break; - } - if (i == NUM_SSID_FIELDS) { - wpa_printf(MSG_ERROR, "Line %d: unknown network field " - "'%s'.", *line, pos); - errors++; - } - } - - if (!end) { - wpa_printf(MSG_ERROR, "Line %d: network block was not " - "terminated properly.", *line); - errors++; - } - - if (ssid->passphrase) { - if (ssid->psk_set) { - wpa_printf(MSG_ERROR, "Line %d: both PSK and " - "passphrase configured.", *line); - errors++; - } - pbkdf2_sha1(ssid->passphrase, - (char *) ssid->ssid, ssid->ssid_len, 4096, - ssid->psk, PMK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", - ssid->psk, PMK_LEN); - ssid->psk_set = 1; - } - - if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { - wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " - "management, but no PSK configured.", *line); - errors++; - } - - if ((ssid->group_cipher & WPA_CIPHER_CCMP) && - !(ssid->pairwise_cipher & WPA_CIPHER_CCMP)) { - /* Group cipher cannot be stronger than the pairwise cipher. */ - wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" - " list since it was not allowed for pairwise " - "cipher", *line); - ssid->group_cipher &= ~WPA_CIPHER_CCMP; - } - - if (errors) { - free(ssid); - ssid = NULL; - } - - return ssid; -} - - -static int wpa_config_add_prio_network(struct wpa_config *config, - struct wpa_ssid *ssid) -{ - int prio; - struct wpa_ssid *prev, **nlist; - - for (prio = 0; prio < config->num_prio; prio++) { - prev = config->pssid[prio]; - if (prev->priority == ssid->priority) { - while (prev->pnext) - prev = prev->pnext; - prev->pnext = ssid; - return 0; - } - } - - /* First network for this priority - add new priority list */ - nlist = realloc(config->pssid, - (config->num_prio + 1) * sizeof(struct wpa_ssid *)); - if (nlist == NULL) - return -1; - - for (prio = 0; prio < config->num_prio; prio++) { - if (nlist[prio]->priority < ssid->priority) - break; - } - - memmove(&nlist[prio + 1], &nlist[prio], - (config->num_prio - prio) * sizeof(struct wpa_ssid *)); - - nlist[prio] = ssid; - config->num_prio++; - config->pssid = nlist; - - return 0; -} - - -struct wpa_config * wpa_config_read(const char *config_file) -{ - FILE *f; - char buf[256], *pos; - int errors = 0, line = 0; - struct wpa_ssid *ssid, *tail = NULL, *head = NULL; - struct wpa_config *config; - int id = 0, prio; - - config = malloc(sizeof(*config)); - if (config == NULL) - return NULL; - memset(config, 0, sizeof(*config)); - config->eapol_version = 1; - config->ap_scan = 1; - config->fast_reauth = 1; - wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", - config_file); - f = fopen(config_file, "r"); - if (f == NULL) { - free(config); - return NULL; - } - - while ((pos = wpa_config_get_line(buf, sizeof(buf), f, &line))) { - if (strcmp(pos, "network={") == 0) { - ssid = wpa_config_read_network(f, &line, id++); - if (ssid == NULL) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "parse network block.", line); - errors++; - continue; - } - if (head == NULL) { - head = tail = ssid; - } else { - tail->next = ssid; - tail = ssid; - } - if (wpa_config_add_prio_network(config, ssid)) { - wpa_printf(MSG_ERROR, "Line %d: failed to add " - "network block to priority list.", - line); - errors++; - continue; - } -#ifdef CONFIG_CTRL_IFACE - } else if (strncmp(pos, "ctrl_interface=", 15) == 0) { - free(config->ctrl_interface); - config->ctrl_interface = strdup(pos + 15); - wpa_printf(MSG_DEBUG, "ctrl_interface='%s'", - config->ctrl_interface); -#ifndef CONFIG_CTRL_IFACE_UDP - } else if (strncmp(pos, "ctrl_interface_group=", 21) == 0) { - struct group *grp; - char *endp; - const char *group = pos + 21; - - grp = getgrnam(group); - if (grp) { - config->ctrl_interface_gid = grp->gr_gid; - config->ctrl_interface_gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" - " (from group name '%s')", - (int) config->ctrl_interface_gid, - group); - continue; - } - - /* Group name not found - try to parse this as gid */ - config->ctrl_interface_gid = strtol(group, &endp, 10); - if (*group == '\0' || *endp != '\0') { - wpa_printf(MSG_DEBUG, "Line %d: Invalid group " - "'%s'", line, group); - errors++; - continue; - } - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", - (int) config->ctrl_interface_gid); -#endif /* CONFIG_CTRL_IFACE_UDP */ -#endif /* CONFIG_CTRL_IFACE */ - } else if (strncmp(pos, "eapol_version=", 14) == 0) { - config->eapol_version = atoi(pos + 14); - if (config->eapol_version < 1 || - config->eapol_version > 2) { - wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL " - "version (%d): '%s'.", - line, config->eapol_version, pos); - errors++; - continue; - } - wpa_printf(MSG_DEBUG, "eapol_version=%d", - config->eapol_version); - } else if (strncmp(pos, "ap_scan=", 8) == 0) { - config->ap_scan = atoi(pos + 8); - wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan); - } else if (strncmp(pos, "fast_reauth=", 12) == 0) { - config->fast_reauth = atoi(pos + 12); - wpa_printf(MSG_DEBUG, "fast_reauth=%d", - config->fast_reauth); - } else { - wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " - "line '%s'.", line, pos); - errors++; - continue; - } - } - - fclose(f); - - config->ssid = head; - for (prio = 0; prio < config->num_prio; prio++) { - ssid = config->pssid[prio]; - wpa_printf(MSG_DEBUG, "Priority group %d", - ssid->priority); - while (ssid) { - wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", - ssid->id, - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - ssid = ssid->pnext; - } - } - if (errors) { - wpa_config_free(config); - config = NULL; - head = NULL; - } - - return config; -} - - -void wpa_config_free(struct wpa_config *config) -{ - struct wpa_ssid *ssid, *prev = NULL; - ssid = config->ssid; - while (ssid) { - prev = ssid; - ssid = ssid->next; - free(prev->ssid); - free(prev->passphrase); - free(prev->eap_methods); - free(prev->identity); - free(prev->anonymous_identity); - free(prev->eappsk); - free(prev->nai); - free(prev->server_nai); - free(prev->password); - free(prev->ca_cert); - free(prev->client_cert); - free(prev->private_key); - free(prev->private_key_passwd); - free(prev->dh_file); - free(prev->subject_match); - free(prev->ca_cert2); - free(prev->client_cert2); - free(prev->private_key2); - free(prev->private_key2_passwd); - free(prev->dh_file2); - free(prev->subject_match2); - free(prev->phase1); - free(prev->phase2); - free(prev->pcsc); - free(prev->pin); - free(prev->otp); - free(prev->pending_req_otp); - free(prev->pac_file); - free(prev); - } - free(config->ctrl_interface); - free(config->pssid); - free(config); -} - - -int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method) -{ - u8 *pos; - - if (ssid == NULL || ssid->eap_methods == NULL) - return 1; - - pos = ssid->eap_methods; - while (*pos != EAP_TYPE_NONE) { - if (*pos == method) - return 1; - pos++; - } - return 0; -} - - -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"; - default: - return "UNKNOWN"; - } -} - - -const char * wpa_key_mgmt_txt(int key_mgmt, int proto) -{ - switch (key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - return proto == WPA_PROTO_RSN ? - "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; - case WPA_KEY_MGMT_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)"; - default: - return "UNKNOWN"; - } -} diff --git a/contrib/wpa_supplicant/config.h b/contrib/wpa_supplicant/config.h deleted file mode 100644 index 13deb3e3cb58..000000000000 --- a/contrib/wpa_supplicant/config.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#ifdef CONFIG_CTRL_IFACE -#ifndef CONFIG_CTRL_IFACE_UDP -#include <grp.h> -#endif /* CONFIG_CTRL_IFACE_UDP */ -#endif /* CONFIG_CTRL_IFACE */ - -#include "config_ssid.h" - -struct wpa_config { - struct wpa_ssid *ssid; /* global network list */ - struct wpa_ssid **pssid; /* per priority network lists (in priority - * order) */ - int num_prio; /* number of different priorities */ - int eapol_version; - int ap_scan; - char *ctrl_interface; /* directory for UNIX domain sockets */ -#ifdef CONFIG_CTRL_IFACE -#ifndef CONFIG_CTRL_IFACE_UDP - gid_t ctrl_interface_gid; -#endif /* CONFIG_CTRL_IFACE_UDP */ - int ctrl_interface_gid_set; -#endif /* CONFIG_CTRL_IFACE */ - int fast_reauth; -}; - - -struct wpa_config * wpa_config_read(const char *config_file); -void wpa_config_free(struct wpa_config *ssid); - -#endif /* CONFIG_H */ diff --git a/contrib/wpa_supplicant/config_ssid.h b/contrib/wpa_supplicant/config_ssid.h deleted file mode 100644 index 44bc98947ced..000000000000 --- a/contrib/wpa_supplicant/config_ssid.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef CONFIG_SSID_H -#define CONFIG_SSID_H - -#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) - -#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_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 MAX_SSID_LEN 32 -#define PMK_LEN 32 -#define EAP_PSK_LEN 16 - -struct wpa_ssid { - struct wpa_ssid *next; /* next network in global list */ - struct wpa_ssid *pnext; /* next network in per-priority list */ - int id; /* unique id for ctrl_iface */ - int priority; - u8 *ssid; - size_t ssid_len; - u8 bssid[ETH_ALEN]; - int bssid_set; - u8 psk[PMK_LEN]; - int psk_set; - char *passphrase; - /* Bitfields of allowed Pairwise/Group Ciphers, WPA_CIPHER_* */ - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int proto; /* Bitfield of allowed protocols (WPA_PROTO_*) */ - int auth_alg; /* Bitfield of allow authentication algorithms - * (WPA_AUTH_ALG_*) */ - int scan_ssid; /* scan this SSID with Probe Requests */ - u8 *identity; /* EAP Identity */ - size_t identity_len; - u8 *anonymous_identity; /* Anonymous EAP Identity (for unencrypted use - * with EAP types that support different - * tunnelled identity, e.g., EAP-TTLS) */ - size_t anonymous_identity_len; - u8 *eappsk; - size_t eappsk_len; - u8 *nai; - size_t nai_len; - u8 *server_nai; - size_t server_nai_len; - u8 *password; - size_t password_len; - u8 *ca_cert; - u8 *client_cert; - u8 *private_key; - u8 *private_key_passwd; - u8 *dh_file; - u8 *subject_match; - u8 *ca_cert2; - u8 *client_cert2; - u8 *private_key2; - u8 *private_key2_passwd; - u8 *dh_file2; - u8 *subject_match2; - u8 *eap_methods; /* zero (EAP_TYPE_NONE) terminated list of allowed - * EAP methods or NULL = any */ - char *phase1; - char *phase2; - char *pcsc; - char *pin; - -#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0) -#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1) - int eapol_flags; /* bit field of IEEE 802.1X/EAPOL options */ - -#define NUM_WEP_KEYS 4 -#define MAX_WEP_KEY_LEN 16 - u8 wep_key[NUM_WEP_KEYS][MAX_WEP_KEY_LEN]; - size_t wep_key_len[NUM_WEP_KEYS]; - int wep_tx_keyidx; - - /* Per SSID variables that are not read from the configuration file */ - u8 *otp; - size_t otp_len; - int pending_req_identity, pending_req_password; - char *pending_req_otp; - size_t pending_req_otp_len; - int leap, non_leap; - - unsigned int eap_workaround; - - char *pac_file; - - int mode; -}; - -int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int method); -const char * wpa_cipher_txt(int cipher); -const char * wpa_key_mgmt_txt(int key_mgmt, int proto); - -#endif /* CONFIG_SSID_H */ diff --git a/contrib/wpa_supplicant/crypto.c b/contrib/wpa_supplicant/crypto.c deleted file mode 100644 index cd278e0fae59..000000000000 --- a/contrib/wpa_supplicant/crypto.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libcrypto - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <openssl/md4.h> -#include <openssl/des.h> - -#include "common.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 */ - - -void md4_vector(size_t num_elem, const u8 *addr[], size_t *len, u8 *mac) -{ - MD4_CTX ctx; - int i; - - MD4_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4_Update(&ctx, addr[i], len[i]); - MD4_Final(mac, &ctx); -} - - -void md4(const u8 *addr, size_t len, u8 *mac) -{ - md4_vector(1, &addr, &len, mac); -} - - -/** - * @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) -{ - 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); -} diff --git a/contrib/wpa_supplicant/crypto.h b/contrib/wpa_supplicant/crypto.h deleted file mode 100644 index 3e1a0e5cd3f8..000000000000 --- a/contrib/wpa_supplicant/crypto.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef CRYPTO_H -#define CRYPTO_H - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); -void md4(const u8 *addr, size_t len, u8 *mac); -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); - -#endif /* CRYPTO_H */ diff --git a/contrib/wpa_supplicant/ctrl_iface.c b/contrib/wpa_supplicant/ctrl_iface.c deleted file mode 100644 index 25cf0dbcbde7..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#ifndef CONFIG_NATIVE_WINDOWS -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/uio.h> -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "common.h" -#include "eloop.h" -#include "wpa.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "eapol_sm.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" -#include "l2_packet.h" - - -#ifdef CONFIG_NATIVE_WINDOWS -typedef int socklen_t; -#endif /* CONFIG_NATIVE_WINDOWS */ - -#ifdef CONFIG_CTRL_IFACE_UDP -#define CTRL_IFACE_SOCK struct sockaddr_in -#else /* CONFIG_CTRL_IFACE_UDP */ -#define CTRL_IFACE_SOCK struct sockaddr_un -#endif /* CONFIG_CTRL_IFACE_UDP */ - - -struct wpa_ctrl_dst { - struct wpa_ctrl_dst *next; - CTRL_IFACE_SOCK addr; - socklen_t addrlen; - int debug_level; - int errors; -}; - - -static const char * wpa_state_txt(int state) -{ - switch (state) { - case WPA_DISCONNECTED: - return "DISCONNECTED"; - case WPA_SCANNING: - return "SCANNING"; - case WPA_ASSOCIATING: - return "ASSOCIATING"; - case WPA_ASSOCIATED: - return "ASSOCIATED"; - case WPA_4WAY_HANDSHAKE: - return "4WAY_HANDSHAKE"; - case WPA_GROUP_HANDSHAKE: - return "GROUP_HANDSHAKE"; - case WPA_COMPLETED: - return "COMPLETED"; - default: - return "UNKNOWN"; - } -} - - -static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, - char *cmd) -{ - char *value; - - value = strchr(cmd, ' '); - if (value == NULL) - return -1; - *value++ = '\0'; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); - if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { - eapol_sm_configure(wpa_s->eapol, - atoi(value), -1, -1, -1); - } else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) { - eapol_sm_configure(wpa_s->eapol, - -1, atoi(value), -1, -1); - } else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) { - eapol_sm_configure(wpa_s->eapol, - -1, -1, atoi(value), -1); - } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) { - eapol_sm_configure(wpa_s->eapol, - -1, -1, -1, atoi(value)); - } else - return -1; - return 0; -} - - -static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, - char *addr) -{ - u8 bssid[ETH_ALEN]; - - if (hwaddr_aton(addr, bssid)) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " - "'%s'", addr); - return -1; - } - - wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); - rsn_preauth_deinit(wpa_s); - if (rsn_preauth_init(wpa_s, bssid)) - return -1; - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s, - CTRL_IFACE_SOCK *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst; - - dst = malloc(sizeof(*dst)); - if (dst == NULL) - return -1; - memset(dst, 0, sizeof(*dst)); - memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK)); - dst->addrlen = fromlen; - dst->debug_level = MSG_INFO; - dst->next = wpa_s->ctrl_dst; - wpa_s->ctrl_dst = dst; -#ifdef CONFIG_CTRL_IFACE_UDP - wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", - inet_ntoa(from->sin_addr), ntohs(from->sin_port)); -#else /* CONFIG_CTRL_IFACE_UDP */ - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", - (u8 *) from->sun_path, fromlen); -#endif /* CONFIG_CTRL_IFACE_UDP */ - return 0; -} - - -static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s, - CTRL_IFACE_SOCK *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst, *prev = NULL; - - dst = wpa_s->ctrl_dst; - while (dst) { -#ifdef CONFIG_CTRL_IFACE_UDP - if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && - from->sin_port == dst->addr.sin_port) { - if (prev == NULL) - wpa_s->ctrl_dst = dst->next; - else - prev->next = dst->next; - free(dst); - wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " - "%s:%d", inet_ntoa(from->sin_addr), - ntohs(from->sin_port)); - return 0; - } -#else /* CONFIG_CTRL_IFACE_UDP */ - if (fromlen == dst->addrlen && - memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) { - if (prev == NULL) - wpa_s->ctrl_dst = dst->next; - else - prev->next = dst->next; - free(dst); - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", - (u8 *) from->sun_path, fromlen); - return 0; - } -#endif /* CONFIG_CTRL_IFACE_UDP */ - prev = dst; - dst = dst->next; - } - return -1; -} - - -static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s, - CTRL_IFACE_SOCK *from, - socklen_t fromlen, - char *level) -{ - struct wpa_ctrl_dst *dst; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); - - dst = wpa_s->ctrl_dst; - while (dst) { -#ifdef CONFIG_CTRL_IFACE_UDP - if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && - from->sin_port == dst->addr.sin_port) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level %s:%d", inet_ntoa(from->sin_addr), - ntohs(from->sin_port)); - dst->debug_level = atoi(level); - return 0; - } -#else /* CONFIG_CTRL_IFACE_UDP */ - if (fromlen == dst->addrlen && - memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level", (u8 *) from->sun_path, fromlen); - dst->debug_level = atoi(level); - return 0; - } -#endif /* CONFIG_CTRL_IFACE_UDP */ - dst = dst->next; - } - - return -1; -} - - -static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, - char *rsp) -{ - char *pos, *id_pos; - int id; - struct wpa_ssid *ssid; - - pos = strchr(rsp, '-'); - if (pos == NULL) - return -1; - *pos++ = '\0'; - id_pos = pos; - pos = strchr(pos, ':'); - if (pos == NULL) - return -1; - *pos++ = '\0'; - id = atoi(id_pos); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); - wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", - (u8 *) pos, strlen(pos)); - - ssid = wpa_s->conf->ssid; - while (ssid) { - if (id == ssid->id) - break; - ssid = ssid->next; - } - - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " - "to update", id); - return -1; - } - - if (strcmp(rsp, "IDENTITY") == 0) { - free(ssid->identity); - ssid->identity = (u8 *) strdup(pos); - ssid->identity_len = strlen(pos); - ssid->pending_req_identity = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else if (strcmp(rsp, "PASSWORD") == 0) { - free(ssid->password); - ssid->password = (u8 *) strdup(pos); - ssid->password_len = strlen(pos); - ssid->pending_req_password = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else if (strcmp(rsp, "OTP") == 0) { - free(ssid->otp); - ssid->otp = (u8 *) strdup(pos); - ssid->otp_len = strlen(pos); - free(ssid->pending_req_otp); - ssid->pending_req_otp = NULL; - ssid->pending_req_otp_len = 0; - } else { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, - const char *params, - char *buf, size_t buflen) -{ - char *pos, *end; - int res, verbose; - - verbose = strcmp(params, "-VERBOSE") == 0; - pos = buf; - end = buf + buflen; - pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n", - MAC2STR(wpa_s->bssid)); - if (wpa_s->current_ssid) { - pos += snprintf(pos, end - pos, "ssid=%s\n", - wpa_ssid_txt(wpa_s->current_ssid->ssid, - wpa_s->current_ssid->ssid_len)); - } - pos += snprintf(pos, end - pos, - "pairwise_cipher=%s\n" - "group_cipher=%s\n" - "key_mgmt=%s\n" - "wpa_state=%s\n", - wpa_cipher_txt(wpa_s->pairwise_cipher), - wpa_cipher_txt(wpa_s->group_cipher), - wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto), - wpa_state_txt(wpa_s->wpa_state)); - - res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose); - if (res >= 0) - pos += res; - - if (wpa_s->preauth_eapol) { - pos += snprintf(pos, end - pos, "Pre-authentication " - "EAPOL state machines:\n"); - res = eapol_sm_get_status(wpa_s->preauth_eapol, - pos, end - pos, verbose); - if (res >= 0) - pos += res; - } - - return pos - buf; -} - - -static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - char buf[256]; - int res; - CTRL_IFACE_SOCK from; - socklen_t fromlen = sizeof(from); - char *reply; - const int reply_size = 2048; - int reply_len; - int new_attached = 0, ctrl_rsp = 0; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - buf[res] = '\0'; - if (strncmp(buf, "CTRL-RSP-", 9) == 0) { - wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", - (u8 *) buf, res); - } else { - wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res); - } - - reply = malloc(reply_size); - if (reply == NULL) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - return; - } - - memcpy(reply, "OK\n", 3); - reply_len = 3; - - if (strcmp(buf, "PING") == 0) { - memcpy(reply, "PONG\n", 5); - reply_len = 5; - } else if (strcmp(buf, "MIB") == 0) { - reply_len = wpa_get_mib(wpa_s, reply, reply_size); - if (reply_len >= 0) { - res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } - } else if (strncmp(buf, "STATUS", 6) == 0) { - reply_len = wpa_supplicant_ctrl_iface_status( - wpa_s, buf + 6, reply, reply_size); - } else if (strcmp(buf, "PMKSA") == 0) { - reply_len = pmksa_cache_list(wpa_s, reply, reply_size); - } else if (strncmp(buf, "SET ", 4) == 0) { - if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) - reply_len = -1; - } else if (strcmp(buf, "LOGON") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, FALSE); - } else if (strcmp(buf, "LOGOFF") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, TRUE); - } else if (strcmp(buf, "REASSOCIATE") == 0) { - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } else if (strncmp(buf, "PREAUTH ", 8) == 0) { - if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) - reply_len = -1; - } else if (strcmp(buf, "ATTACH") == 0) { - if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen)) - reply_len = -1; - else - new_attached = 1; - } else if (strcmp(buf, "DETACH") == 0) { - if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen)) - reply_len = -1; - } else if (strncmp(buf, "LEVEL ", 6) == 0) { - if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen, - buf + 6)) - reply_len = -1; - } else if (strncmp(buf, "CTRL-RSP-", 9) == 0) { - if (wpa_supplicant_ctrl_iface_ctrl_rsp(wpa_s, buf + 9)) - reply_len = -1; - else - ctrl_rsp = 1; - } else if (strcmp(buf, "RECONFIGURE") == 0) { - if (wpa_supplicant_reload_configuration(wpa_s)) - reply_len = -1; - } else if (strcmp(buf, "TERMINATE") == 0) { - eloop_terminate(); - } else { - memcpy(reply, "UNKNOWN COMMAND\n", 16); - reply_len = 16; - } - - if (reply_len < 0) { - memcpy(reply, "FAIL\n", 5); - reply_len = 5; - } - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); - free(reply); - - if (new_attached) - eapol_sm_notify_ctrl_attached(wpa_s->eapol); - if (ctrl_rsp) - eapol_sm_notify_ctrl_response(wpa_s->eapol); -} - - -static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) -{ - char *buf; - size_t len; - - if (wpa_s->conf->ctrl_interface == NULL) - return NULL; - - len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2; - buf = malloc(len); - if (buf == NULL) - return NULL; - - snprintf(buf, len, "%s/%s", - wpa_s->conf->ctrl_interface, wpa_s->ifname); -#ifdef __CYGWIN__ - { - /* Windows/WinPcap uses interface names that are not suitable - * as a file name - convert invalid chars to underscores */ - char *pos = buf; - while (*pos) { - if (*pos == '\\') - *pos = '_'; - pos++; - } - } -#endif /* __CYGWIN__ */ - return buf; -} - - -int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) -{ - CTRL_IFACE_SOCK addr; - int s = -1; - char *fname = NULL; - - wpa_s->ctrl_sock = -1; - - if (wpa_s->conf->ctrl_interface == NULL) - return 0; - -#ifdef CONFIG_CTRL_IFACE_UDP - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket(PF_INET)"); - goto fail; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl((127 << 24) | 1); - addr.sin_port = htons(9877); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(AF_UNIX)"); - goto fail; - } -#else /* CONFIG_CTRL_IFACE_UDP */ - if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) { - if (errno == EEXIST) { - wpa_printf(MSG_DEBUG, "Using existing control " - "interface directory."); - } else { - perror("mkdir[ctrl_interface]"); - goto fail; - } - } - - if (wpa_s->conf->ctrl_interface_gid_set && - chown(wpa_s->conf->ctrl_interface, 0, - wpa_s->conf->ctrl_interface_gid) < 0) { - perror("chown[ctrl_interface]"); - return -1; - } - - if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >= - sizeof(addr.sun_path)) - goto fail; - - s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket(PF_UNIX)"); - goto fail; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - fname = wpa_supplicant_ctrl_iface_path(wpa_s); - if (fname == NULL) - goto fail; - strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not" - " allow connections - assuming it was left" - "over from forced program termination"); - if (unlink(fname) < 0) { - perror("unlink[ctrl_iface]"); - wpa_printf(MSG_ERROR, "Could not unlink " - "existing ctrl_iface socket '%s'", - fname); - goto fail; - } - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < - 0) { - perror("bind(PF_UNIX)"); - goto fail; - } - wpa_printf(MSG_DEBUG, "Successfully replaced leftover " - "ctrl_iface socket '%s'", fname); - } else { - wpa_printf(MSG_INFO, "ctrl_iface exists and seems to " - "be in use - cannot override it"); - wpa_printf(MSG_INFO, "Delete '%s' manually if it is " - "not used anymore", fname); - free(fname); - fname = NULL; - goto fail; - } - } - - if (wpa_s->conf->ctrl_interface_gid_set && - chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) { - perror("chown[ctrl_interface/ifname]"); - goto fail; - } - - if (chmod(fname, S_IRWXU | S_IRWXG) < 0) { - perror("chmod[ctrl_interface/ifname]"); - goto fail; - } - free(fname); -#endif /* CONFIG_CTRL_IFACE_UDP */ - - wpa_s->ctrl_sock = s; - eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s, - NULL); - - return 0; - -fail: - if (s >= 0) - close(s); - if (fname) { - unlink(fname); - free(fname); - } - return -1; -} - - -void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s) -{ - struct wpa_ctrl_dst *dst, *prev; - - if (wpa_s->ctrl_sock > -1) { - char *fname; - eloop_unregister_read_sock(wpa_s->ctrl_sock); - if (wpa_s->ctrl_dst) { - /* - * Wait a second before closing the control socket if - * there are any attached monitors in order to allow - * them to receive any pending messages. - */ - wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " - "monitors to receive messages"); - sleep(1); - } - close(wpa_s->ctrl_sock); - wpa_s->ctrl_sock = -1; - fname = wpa_supplicant_ctrl_iface_path(wpa_s); - if (fname) - unlink(fname); - free(fname); - - if (rmdir(wpa_s->conf->ctrl_interface) < 0) { - if (errno == ENOTEMPTY) { - wpa_printf(MSG_DEBUG, "Control interface " - "directory not empty - leaving it " - "behind"); - } else { - perror("rmdir[ctrl_interface]"); - } - } - } - - dst = wpa_s->ctrl_dst; - while (dst) { - prev = dst; - dst = dst->next; - free(prev); - } -} - - -void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level, - char *buf, size_t len) -{ - struct wpa_ctrl_dst *dst, *next; - char levelstr[10]; - int idx; -#ifdef CONFIG_CTRL_IFACE_UDP - char *sbuf; - int llen; - - dst = wpa_s->ctrl_dst; - if (wpa_s->ctrl_sock < 0 || dst == NULL) - return; - - snprintf(levelstr, sizeof(levelstr), "<%d>", level); - - llen = strlen(levelstr); - sbuf = malloc(llen + len); - if (sbuf == NULL) - return; - - memcpy(sbuf, levelstr, llen); - memcpy(sbuf + llen, buf, len); - - idx = 0; - while (dst) { - next = dst->next; - if (level >= dst->debug_level) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", - inet_ntoa(dst->addr.sin_addr), - ntohs(dst->addr.sin_port)); - if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0, - (struct sockaddr *) &dst->addr, - sizeof(dst->addr)) < 0) { - fprintf(stderr, "CTRL_IFACE monitor[%d]: ", - idx); - perror("sendto"); - dst->errors++; - if (dst->errors > 10) { - wpa_supplicant_ctrl_iface_detach( - wpa_s, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } - free(sbuf); -#else /* CONFIG_CTRL_IFACE_UDP */ - struct msghdr msg; - struct iovec io[2]; - - dst = wpa_s->ctrl_dst; - if (wpa_s->ctrl_sock < 0 || dst == NULL) - return; - - snprintf(levelstr, sizeof(levelstr), "<%d>", level); - io[0].iov_base = levelstr; - io[0].iov_len = strlen(levelstr); - io[1].iov_base = buf; - io[1].iov_len = len; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - - idx = 0; - while (dst) { - next = dst->next; - if (level >= dst->debug_level) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send", - (u8 *) dst->addr.sun_path, dst->addrlen); - msg.msg_name = &dst->addr; - msg.msg_namelen = dst->addrlen; - if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) { - fprintf(stderr, "CTRL_IFACE monitor[%d]: ", - idx); - perror("sendmsg"); - dst->errors++; - if (dst->errors > 10) { - wpa_supplicant_ctrl_iface_detach( - wpa_s, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } -#endif /* CONFIG_CTRL_IFACE_UDP */ -} diff --git a/contrib/wpa_supplicant/ctrl_iface.h b/contrib/wpa_supplicant/ctrl_iface.h deleted file mode 100644 index d7ad6dfe670a..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CTRL_IFACE_H -#define CTRL_IFACE_H - -#ifdef CONFIG_CTRL_IFACE - -int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s); -void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s); -void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level, - char *buf, size_t len); - -#else /* CONFIG_CTRL_IFACE */ - -static inline int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) -{ - return 0; -} - -static inline void -wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s) -{ -} - -static inline void -wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level, - char *buf, size_t len) -{ -} - -#endif /* CONFIG_CTRL_IFACE */ - -#endif /* CTRL_IFACE_H */ diff --git a/contrib/wpa_supplicant/defconfig b/contrib/wpa_supplicant/defconfig deleted file mode 100644 index 7e8e3811d06f..000000000000 --- a/contrib/wpa_supplicant/defconfig +++ /dev/null @@ -1,154 +0,0 @@ -# Example wpa_supplicant build time configuration -# -# This file lists the configuration options that are used when building the -# hostapd binary. All lines starting with # are ignored. Configuration option -# lines must be commented out complete, if they are not to be included, i.e., -# just setting VARIABLE=n is not disabling that variable. -# -# This file is included in Makefile, so variables like CFLAGS and LIBS can also -# be modified from here. In most cass, these lines should use += in order not -# to override previous values of the variables. - - -# Uncomment following two lines and fix the paths if you have installed openssl -# in non-default location -#CFLAGS += -I/usr/local/openssl/include -#LIBS += -L/usr/local/openssl/lib - -# Example configuration for various cross-compilation platforms - -#### sveasoft (e.g., for Linksys WRT54G) ###################################### -#CC=mipsel-uclibc-gcc -#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc -#CFLAGS += -Os -#CPPFLAGS += -I../src/include -I../../src/router/openssl/include -#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl -############################################################################### - -#### openwrt (e.g., for Linksys WRT54G) ####################################### -#CC=mipsel-uclibc-gcc -#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc -#CFLAGS += -Os -#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \ -# -I../WRT54GS/release/src/include -#LIBS = -lssl -############################################################################### - - -# Driver interface for Host AP driver -CONFIG_DRIVER_HOSTAP=y - -# Driver interface for Agere driver -#CONFIG_DRIVER_HERMES=y -# Change include directories to match with the local setup -#CFLAGS += -I../../hcf -I../../include -I../../include/hcf -#CFLAGS += -I../../include/wireless - -# Driver interface for madwifi driver -#CONFIG_DRIVER_MADWIFI=y -# Change include directories to match with the local setup -#CFLAGS += -I../madwifi/wpa - -# Driver interface for Prism54 driver -CONFIG_DRIVER_PRISM54=y - -# Driver interface for ndiswrapper -#CONFIG_DRIVER_NDISWRAPPER=y - -# Driver interface for Atmel driver -CONFIG_DRIVER_ATMEL=y - -# Driver interface for Broadcom driver -#CONFIG_DRIVER_BROADCOM=y -# Example path for wlioctl.h; change to match your configuration -#CFLAGS += -I/opt/WRT54GS/release/src/include - -# Driver interface for Intel ipw2100/2200 driver -#CONFIG_DRIVER_IPW=y - -# Driver interface for generic Linux wireless extensions -CONFIG_DRIVER_WEXT=y - -# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver) -#CONFIG_DRIVER_BSD=y -#CFLAGS += -I/usr/local/include -#LIBS += -L/usr/local/lib - -# Driver interface for Windows NDIS -#CONFIG_DRIVER_NDIS=y -#CFLAGS += -I/usr/include/w32api/ddk -#LIBS += -L/usr/local/lib -# For native build using mingw -#CONFIG_NATIVE_WINDOWS=y -# Additional directories for cross-compilation on Linux host for mingw target -#CFLAGS += -I/opt/mingw/mingw32/include/ddk -#LIBS += -L/opt/mingw/mingw32/lib -#CC=mingw32-gcc - -# Driver interface for development testing -#CONFIG_DRIVER_TEST=y - -# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is -# included) -CONFIG_IEEE8021X_EAPOL=y - -# EAP-MD5 (automatically included if EAP-TTLS is enabled) -CONFIG_EAP_MD5=y - -# EAP-MSCHAPv2 (automatically included if EAP-PEAP is enabled) -CONFIG_EAP_MSCHAPV2=y - -# EAP-TLS -CONFIG_EAP_TLS=y - -# EAL-PEAP -CONFIG_EAP_PEAP=y - -# EAP-TTLS -CONFIG_EAP_TTLS=y - -# EAP-GTC -CONFIG_EAP_GTC=y - -# EAP-OTP -CONFIG_EAP_OTP=y - -# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used) -#CONFIG_EAP_SIM=y - -# EAP-PSK (experimental; this is _not_ needed for WPA-PSK) -#CONFIG_EAP_PSK=y - -# LEAP -CONFIG_EAP_LEAP=y - -# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used) -#CONFIG_EAP_AKA=y - -# PKCS#12 (PFX) support (used to read private key and certificate file from -# a file that usually has extension .p12 or .pfx) -CONFIG_PKCS12=y - -# PC/SC interface for smartcards (USIM, GSM SIM) -# Enable this if EAP-SIM or EAP-AKA is included -#CONFIG_PCSC=y - -# Development testing -#CONFIG_EAPOL_TEST=y - -# Replace native Linux implementation of packet sockets with libdnet/libpcap. -# This will be automatically set for non-Linux OS. -#CONFIG_DNET_PCAP=y - -# Include control interface for external programs, e.g, wpa_cli -CONFIG_CTRL_IFACE=y - -# Include interface for using external supplicant (Xsupplicant) for EAP -# authentication -#CONFIG_XSUPPLICANT_IFACE=y - -# Include support for GNU Readline and History Libraries in wpa_cli. -# When building a wpa_cli binary for distribution, please note that these -# libraries are licensed under GPL and as such, BSD license may not apply for -# the resulting binary. -#CONFIG_READLINE=y diff --git a/contrib/wpa_supplicant/defs.h b/contrib/wpa_supplicant/defs.h deleted file mode 100644 index a5a515c552f5..000000000000 --- a/contrib/wpa_supplicant/defs.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef DEFS_H -#define DEFS_H - -#ifdef CONFIG_NATIVE_WINDOWS -#ifdef FALSE -#undef FALSE -#endif -#ifdef TRUE -#undef TRUE -#endif -#endif /* CONFIG_NATIVE_WINDOWS */ -typedef enum { FALSE = 0, TRUE = 1 } Boolean; - -#endif /* DEFS_H */ diff --git a/contrib/wpa_supplicant/developer.txt b/contrib/wpa_supplicant/developer.txt deleted file mode 100644 index bc5b34645d1a..000000000000 --- a/contrib/wpa_supplicant/developer.txt +++ /dev/null @@ -1,458 +0,0 @@ -Developer notes for wpa_supplicant -================================== - -The design goal for wpa_supplicant was to use hardware, driver, and OS -independent, portable C code for all WPA functionality. All -hardware/driver specific functionality is in separate files that -implement a well-defined driver API. - -The goal of this file and the comments in the header files is to give -enough information for other developers to be able to port the example -code. If any information is missing, feel free to contact Jouni Malinen -<jkmaline@cc.hut.fi> for more information. Contributions as patch files -are also very welcome at the same address. - -Structure of the source code ----------------------------- - -Program initialization, main control loop and event handling is -implemented in wpa_supplicant.c. WPA state machines and 4-Way/Group -Key Handshake processing in in wpa.c. IEEE 802.1X/EAPOL processing and -state machines are in eapol_sm.c. EAP state machine is in eap.c. EAP -methods for the internal EAP peer are in eap_*.c. Parser for the -configuration file is implemented in config.c. - -Driver interface API is defined in driver.h and all hardware/driver -dependent functionality is implemented in driver_*.c (see below). - - -Generic helper functions ------------------------- - -wpa_supplicant uses generic helper functions some of which are shared -with with hostapd. The following C files are currently used: - -eloop.[ch] - event loop (select() loop with registerable timeouts, socket read - callbacks, and signal callbacks) - -common.[ch] - common helper functions - -defs.h - definitions shared by multiple files - -l2_packet.[ch] - Layer 2 (link) access wrapper (includes native Linux implementation - and wrappers for libdnet/libpcap) - -pcsc_funcs.[ch] - Wrapper for PC/SC lite SIM and smart card readers - - -Cryptographic functions ------------------------ - -md5.c - MD5 (replaced with openssl/crypto if TLS support is included) - HMAC-MD5 (keyed checksum for message authenticity validation) - -rc4.c - RC4 (broadcast/default key encryption) - -sha1.c - SHA-1 (replaced with openssl/crypto if TLS support is included) - HMAC-SHA-1 (keyed checksum for message authenticity validation) - PRF-SHA-1 (pseudorandom (key/nonce generation) function) - PBKDF2-SHA-1 (ASCII passphrase to shared secret) - T-PRF (for EAP-FAST) - TLS-PRF (RFC 2246) - -aes_wrap.[ch], aes.c - AES - AES Key Wrap Algorithm with 128-bit KEK, RFC3394 (broadcast/default - key encryption) - One-Key CBC MAC (OMAC1) hash with AES-128 - AES-128 CTR mode encryption - AES-128 EAX mode encryption/decryption - AES-128 CBC - -crypto.[ch] - Wrapper functions for libcrypto (MD4 and DES) - -ms_funcs.[ch] - Helper functions for MSCHAPV2 and LEAP - -tls.h - Definition of TLS library wrapper - -tls_none.c - Dummy implementation of TLS library wrapper for cases where TLS - functionality is not included. - -tls_openssl.c - TLS library wrapper for openssl - - -Configuration -------------- - -config_ssid.h - Definition of per network configuration items - -config.h - Definition of the wpa_supplicant configuration - -config.c - Configuration file parser - - -Control interface ------------------ - -wpa_supplicant has a control interface that can be used to get status -information and manage operations from external programs. An example, -command line interface, wpa_cli, for this interface is included in the -wpa_supplicant distribution. - -ctrl_iface.[ch] - wpa_supplicant-side of the control interface - -wpa_ctrl.[ch] - Library functions for external programs to provide access to the - wpa_supplicant control interface - -wpa_cli.c - Example program for using wpa_supplicant control interface - - -EAP peer --------- - -eap.[ch] - EAP state machine - -eap_defs.h - Common EAP definitions - -eap_i.h - Internal definitions for EAP state machine and EAP methods - -eap_sim_common.[ch] - Common code for EAP-SIM and EAP-AKA - -eap_tls_common.[ch] - Common code for EAP-PEAP, EAP-TTLS, and EAP-FAST - -eap_tlv.[ch] - EAP-TLV code for EAP-PEAP and EAP-FAST - -eap_{aka,fast,gtc,leap,md5,mschapv2,otp,peap,psk,sim,tls,ttls}.c - EAP method implementations - - -EAPOL supplicant ----------------- - -eapol_sm.[ch] - EAPOL supplicant state machine and IEEE 802.1X processing - - -Windows port ------------- - -ndis_events.cpp - External program for receiving NdisMIndicateStatus() events and - delivering them to wpa_supplicant in more easier to use form - -win_if_list.c - External program for listing current network interface - - -Test programs -------------- - -radius_client.[ch] - RADIUS authentication client implementation for eapol_test - -eapol_test.c - Standalone EAP testing tool with integrated RADIUS authentication - client - -preauth_test.c - Standalone RSN pre-authentication tool - - -wpa_supplicant.c ----------------- - -main() -- parse command line -- call config file parser -- initialize Supplicant data structures -- call functions to initialize WPA support in the driver -- initialize event loop -- cleanup when exiting - -wpa_supplicant_dot1x_receive() -- receive master session key update from Xsupplicant (optional) - -wpa_supplicant_get_beacon_ie() - -wpa_supplicant_deauthenticate() - -wpa_supplicant_disassociate() - -wpa_supplicant_scan() - -wpa_supplicant_reconfig() -- SIGHUP signal processing - -wpa_supplicant_terminate() -- SIGINT and SIGTERM processing - -wpa_supplicant_reload_configuration() - -wpa_supplicant_event() -- receive driver events (through driver wrapper functions) - * wpa_supplicant_scan_results(): process scan result event, BSS selection - * wpa_supplicant_associnfo(): process association information event - -wpa_supplicant_associate() -- control association (select cipher and key management suites, initiate - association) - -wpa_supplicant_req_auth_timeout() - -wpa_supplicant_cancel_auth_timeout() - -wpa_supplicant_req_scan() - -wpa_supplicant_cancel_scan() - -wpa_supplicant_notify_eapol_done() - -wpa_eapol_send() -- send EAPOL frames - -wpa_eapol_send_preauth() -- send RSN preauthentication frames - -wpa_msg() -- event/debug function - - -wpa_supplicant.h ----------------- - -- driver event definition -- common function definition (e.g., wpa_msg) - - -wpa_supplicant_i.h ------------------- -- internal definitions for wpa_supplicant; must not be included into - common code, EAP methods, driver interface implementations - - -wpa.[ch] --------- -- WPA supplicant state machine and 4-Way/Group Key Handshake processing -- PMKSA cache and RSN pre-authentication - -pmksa_cache_free() - -pmksa_cache_get() - -pmksa_cache_list() - -pmksa_candidate_free() - -wpa_parse_wpa_ie() -- WPA/RSN IE parsing - -wpa_gen_wpa_ei() -- WPA/RSN IE generation - -wpa_supplicant_get_ssid() - -wpa_supplicant_key_request() -- trigger function to start key requests - -wpa_sm_rx_eapol() -- WPA processing for received EAPOL-Key frames - * wpa_supplicant_process_1_of_4() (message 1 of 4-Way Handshake) - * wpa_supplicant_process_3_of_4() (message 3 of 4-Way Handshake) - * wpa_supplicant_process_1_of_2() (message 1 of Group Key Handshake) - -wpa_supplicant_rx_eapol() -- l2_packet RX callback for EAPOL frames; sends the frames to WPA and EAPOL - state machines for further processing - -wpa_get_mib() - -rsn_preauth_receive() -- l2_packet RX callback for preauthentication frames - -rsn_preauth_eapol_cb() -- callback function to be called when EAPOL authentication has been completed - (either successfully or unsuccessfully) for RSN pre-authentication - -rsn_preauth_init() -rsn_preauth_deinit() - -pmksa_candidate_add() -- add a BSSID to PMKSA candidate list - -rsn_preauth_scan_results() -- update RSN pre-authentication candidate list based on scan results - - -Driver wrapper implementation (driver.h, drivers.c) ---------------------------------------------------- - -All hardware and driver dependent functionality is implemented in as a -separate C file(s) implementing defined wrapper functions. Other parts -of the wpa_supplicant are designed to be hardware, driver, and operating -system independent. - -Driver wrappers need to implement whatever calls are used in the -target operating system/driver for controlling wireless LAN -devices. As an example, in case of Linux, these are mostly some glue -code and ioctl() calls and netlink message parsing for Linux Wireless -Extensions. Since all features required for WPA are not yet included -in Wireless Extensions, some driver specific code is used in the -example implementation for Host AP driver. These driver dependent parts -are to be replaced with generic code once the needed changes are -included in the Wireless Extensions. After that, all Linux drivers, at -least in theory, could use the same driver wrapper code. - -A driver wrapper needs to implement some or all of the functions -defined in driver.h (see that file for detailed documentation of the -functions). Hardware independent parts of wpa_supplicant will call -these functions to control the driver/wlan card. In addition, support -for driver events is required. The event callback function, -wpa_supplicant_event(), and its parameters are documented in -wpa_supplicant.h. In addition, pointer to the 'struct wpa_driver_ops' -needs to be registered in drivers.c file. - -When porting to other operating systems, driver wrapper should be -modified to use the native interface of the target OS. It is possible -that some extra requirements for the interface between the driver -wrapper and generic wpa_supplicant code are discovered during porting -to a new operating system. These will be addresses on case by case -basic by modifying the interface and updating the other driver -wrappers for this. The goal is to avoid changing this interface -without very good reasons in order to limit the number of changes -needed to other wrappers and hardware independent parts of -wpa_supplicant. - -Generic Linux Wireless Extensions functions are implemented in -driver_wext.c. All Linux driver wrappers can use these when the kernel -driver supports the generic ioctl()s and wireless events. Driver -specific functions are implemented in separate C files, e.g., -driver_hostap.c. These files need to define struct wpa_driver_ops -entry that will be used in wpa_supplicant.c when calling driver -functions. These entries need to be added to the lists in -wpa_supplicant_set_driver() and usage() functions in wpa_supplicant.c. - -In general, it is likely to be useful to first take a look at couple -of the driver interfaces before starting on implementing a new -one. driver_hostap.c and driver_wext.c include a complete -implementation for Linux drivers that use wpa_supplicant-based control -of WPA IE and roaming. driver_ndis.c (with help from driver_ndis_.c) -is an example of a complete interface for Windows NDIS interface for -drivers that generate WPA IE themselves and decide when to roam. These -example implementations include full support for all security modes. - - -Driver requirements for WPA ---------------------------- - -WPA introduces new requirements for the device driver. At least some -of these need to be implemented in order to provide enough support for -wpa_supplicant. - -TKIP/CCMP - -WPA requires that the pairwise cipher suite (encryption algorithm for -unicast data packets) is TKIP or CCMP. These are new encryption -protocols and thus, the driver will need to be modified to support -them. Depending on the used wlan hardware, some parts of these may be -implemented by the hardware/firmware. - -Specification for both TKIP and CCMP is available from IEEE (IEEE -802.11i draft version 3.0). Fully functional, hardware independent -implementation of both encryption protocols is also available in Host -AP driver (driver/modules/hostap_{tkip,ccmp}.c). - -The driver will also need to provide configuration mechanism to allow -user space programs to configure TKIP and CCMP. Current Linux Wireless -Extensions (v16) does not yet support these algorithms or -individual/non-default keys. Host AP driver has an example of private -ioctl()s for this. Eventually, this should be replaced with modified -Linux Wireless Extensions. - -Roaming control and scanning support - -wpa_supplicant controls AP selections based on the information -received from Beacon and/or Probe Response frames. This means that the -driver should support external control for scan process. In case of -Linux, use of new Wireless Extensions scan support (i.e., 'iwlist -wlan0 scan') is recommended. The current driver wrapper (driver_wext.c) -uses this for scan results. - -Scan results must also include WPA information element. This is not -yet defined in Linux Wireless Extensions and Host AP driver uses a -custom event to provide the full WPA IE (including element id and -length) as a hex string that is included in the scan results. -Eventually, this should be defined as a Wireless Extensions ioctl -that can be used both with scan results and with configuration of WPA IE -for association request (and Beacon/Probe Response in case of an -AP/IBSS). - -wpa_supplicant needs to also be able to request the driver to -associate with a specific BSS. Current Host AP driver and matching -driver_hostap.c wrapper uses following sequence for this -request. Similar/identical mechanism should be usable also with other -drivers. - -- set WPA IE for AssocReq with private ioctl -- set SSID with SIOCSIWESSID -- set channel/frequency with SIOCSIWFREQ -- set BSSID with SIOCSIWAP - (this last ioctl will trigger the driver to request association) - -WPA IE generation - -wpa_supplicant selects which cipher suites and key management suites -are used. Based on this information, it generates a WPA IE. This is -provided to the driver interface in the associate call. This does not -match with Windows NDIS drivers which generate the WPA IE -themselves. - -wpa_supplicant allows Windows NDIS-like behavior by providing the -selected cipher and key management suites in the associate call. If -the driver generates its own WPA IE and that differs from the one -generated by wpa_supplicant, the driver has to inform wpa_supplicant -about the used WPA IE (i.e., the one it used in (Re)Associate -Request). This notification is done using EVENT_ASSOCINFO event (see -wpa_supplicant.h). - -Driver events - -wpa_supplicant needs to receive event callbacks when certain events -occur (association, disassociation, Michael MIC failure, scan results -available, PMKSA caching candidate). These events and the callback -details are defined in wpa_supplicant.h. - -On Linux, association and disassociation can use existing Wireless -Extensions event that is reporting new AP with SIOCGIWAP -event. Similarly, completion of scan can be reported with SIOCGIWSCAN -event. - -Michael MIC failure event is not yet included in Wireless Extensions, -so this needs a custom event. Host AP driver uses custom event with -following contents: MLME-MICHAELMICFAILURE.indication(keyid=# -broadcast/unicast addr=addr2). This is the recommended format until -the event is added to Linux Wireless Extensions. diff --git a/contrib/wpa_supplicant/doc/wpa_supplicant.fig b/contrib/wpa_supplicant/doc/wpa_supplicant.fig deleted file mode 100644 index dc1d9dfcf738..000000000000 --- a/contrib/wpa_supplicant/doc/wpa_supplicant.fig +++ /dev/null @@ -1,221 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single --2 -1200 2 -6 1875 4050 2925 4350 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1875 4050 2925 4050 2925 4350 1875 4350 1875 4050 -4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001 --6 -6 3450 1200 4275 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3450 1200 4275 1200 4275 1500 3450 1500 3450 1200 -4 0 0 50 -1 0 12 0.0000 4 180 585 3600 1425 wpa_cli\001 --6 -6 4725 1200 5925 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 1200 5925 1200 5925 1500 4725 1500 4725 1200 -4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001 --6 -6 6000 2700 7200 3225 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 2700 7200 2700 7200 3225 6000 3225 6000 2700 -4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001 --6 -6 6000 4950 7200 5475 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 4950 7200 4950 7200 5475 6000 5475 6000 4950 -4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001 --6 -6 8700 3000 9375 3300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8700 3000 9375 3000 9375 3300 8700 3300 8700 3000 -4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3225 crypto\001 --6 -6 4350 3900 5025 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4350 3900 5025 3900 5025 4425 4350 4425 4350 3900 -4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001 -4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001 --6 -6 4275 2550 5100 2850 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 2550 5100 2550 5100 2850 4275 2850 4275 2550 -4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001 --6 -6 6000 3900 7200 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 3900 7200 3900 7200 4425 6000 4425 6000 3900 -4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\001 --6 -6 1800 6000 7800 8100 -6 1800 6000 7800 7200 -6 1800 6900 2700 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1800 6900 2700 6900 2700 7200 1800 7200 1800 6900 -4 0 0 50 -1 0 12 0.0000 4 105 375 1875 7125 wext\001 --6 -6 4725 6900 5625 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 6900 5625 6900 5625 7200 4725 7200 4725 6900 -4 0 0 50 -1 0 12 0.0000 4 135 555 4800 7125 hermes\001 --6 -6 6675 6900 7800 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6675 6900 7800 6900 7800 7200 6675 7200 6675 6900 -4 0 0 50 -1 0 12 0.0000 4 180 930 6750 7125 ndiswrapper\001 --6 -6 5700 6900 6600 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 5700 6900 6600 6900 6600 7200 5700 7200 5700 6900 -4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 atmel\001 --6 -6 4275 6000 5100 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 6000 5100 6000 5100 6300 4275 6300 4275 6000 -4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001 --6 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 6900 3675 6900 3675 7200 2775 7200 2775 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3750 6900 4650 6900 4650 7200 3750 7200 3750 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 - 2250 6900 2250 6600 7200 6600 7200 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 3225 6900 3225 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4200 6900 4200 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5175 6900 5175 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6150 6900 6150 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6600 4650 6300 -4 0 0 50 -1 0 12 0.0000 4 180 510 2850 7125 hostap\001 -4 0 0 50 -1 0 12 0.0000 4 135 600 3825 7125 madwifi\001 --6 -6 3525 7800 5775 8100 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3525 7800 5775 7800 5775 8100 3525 8100 3525 7800 -4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001 --6 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 2250 7200 4200 7800 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 7200 7200 5100 7800 --6 -6 9600 3000 10275 3300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9600 3000 10275 3000 10275 3300 9600 3300 9600 3000 -4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3225 TLS\001 --6 -6 8100 4425 10425 6975 -6 8175 4725 9225 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 4725 9225 4725 9225 5025 8175 5025 8175 4725 -4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001 --6 -6 9300 4725 10350 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 4725 10350 4725 10350 5025 9300 5025 9300 4725 -4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001 --6 -6 8175 5100 9225 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5100 9225 5100 9225 5400 8175 5400 8175 5100 -4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001 --6 -6 9300 5100 10350 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5100 10350 5100 10350 5400 9300 5400 9300 5100 -4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001 --6 -6 8175 5475 9225 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5475 9225 5475 9225 5775 8175 5775 8175 5475 -4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001 --6 -6 9300 5475 10350 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5475 10350 5475 10350 5775 9300 5775 9300 5475 -4 0 0 50 -1 0 12 0.0000 4 135 765 9375 5700 EAP-OTP\001 --6 -6 8175 5850 9225 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5850 9225 5850 9225 6150 8175 6150 8175 5850 -4 0 0 50 -1 0 12 0.0000 4 135 750 8250 6075 EAP-SIM\001 --6 -6 8175 6600 9675 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6600 9675 6600 9675 6900 8175 6900 8175 6600 -4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 6825 EAP-MSCHAPv2\001 --6 -6 9300 6225 10350 6525 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 6225 10350 6225 10350 6525 9300 6525 9300 6225 -4 0 0 50 -1 0 12 0.0000 4 135 465 9375 6450 LEAP\001 --6 -6 8175 6225 9225 6525 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6225 9225 6225 9225 6525 8175 6525 8175 6225 -4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001 --6 -6 9300 5850 10350 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5850 10350 5850 10350 6150 9300 6150 9300 5850 -4 0 0 50 -1 0 12 0.0000 4 135 825 9375 6075 EAP-AKA\001 --6 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8100 6975 10425 6975 10425 4425 8100 4425 8100 6975 -4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001 --6 -2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 - 1275 4200 1875 4200 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4500 2550 3900 1500 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4800 2550 5400 1500 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2925 4200 4350 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 3900 6000 3000 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 4200 6000 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6000 4650 4425 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 4425 6600 4950 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 3225 6600 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 5250 8100 5250 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9075 4425 9075 3300 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 3000 8700 3150 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 3900 4650 2850 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 4125 8700 3300 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 4350 5025 6000 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 3150 4875 6000 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1500 2100 10800 2100 10800 7500 1500 7500 1500 2100 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9900 4425 9900 3300 -4 0 0 50 -1 0 12 0.0000 4 135 915 375 3975 EAPOL and\001 -4 0 0 50 -1 0 12 0.0000 4 180 630 375 4200 pre-auth\001 -4 0 0 50 -1 0 12 0.0000 4 180 810 375 4425 ethertypes\001 -4 0 0 50 -1 0 12 0.0000 4 135 1050 375 4650 from/to kernel\001 -4 0 0 50 -1 0 12 0.0000 4 135 1920 3675 1875 frontend control interface\001 -4 0 0 50 -1 2 14 0.0000 4 195 1425 1637 2371 wpa_supplicant\001 diff --git a/contrib/wpa_supplicant/driver.h b/contrib/wpa_supplicant/driver.h deleted file mode 100644 index da28014c9270..000000000000 --- a/contrib/wpa_supplicant/driver.h +++ /dev/null @@ -1,436 +0,0 @@ -#ifndef DRIVER_H -#define DRIVER_H - -#define WPA_SUPPLICANT_DRIVER_VERSION 2 - -typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; -typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 } wpa_cipher; -typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, - KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; - -#define AUTH_ALG_OPEN_SYSTEM 0x01 -#define AUTH_ALG_SHARED_KEY 0x02 -#define AUTH_ALG_LEAP 0x04 - -#define IEEE80211_MODE_INFRA 0 -#define IEEE80211_MODE_IBSS 1 - -#define SSID_MAX_WPA_IE_LEN 40 -struct wpa_scan_result { - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; - u8 wpa_ie[SSID_MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[SSID_MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - int freq; /* MHz */ - int caps; /* e.g. privacy */ - int qual; /* signal quality */ - int noise; - int level; - int maxrate; -}; - -/* Parameters for associate driver_ops. */ -struct wpa_driver_associate_params { - /* BSSID of the selected AP */ - const u8 *bssid; - - /* The selected SSID and its length in bytes */ - const u8 *ssid; - size_t ssid_len; - - /* frequency that the selected AP is using (in MHz as - * reported in the scan results) */ - int freq; - - /* WPA information element to be included in (Re)Association - * Request (including information element id and length). Use - * of this WPA IE is optional. If the driver generates the WPA - * IE, it can use @pairwise_suite, @group_suite, and - * @key_mgmt_suite to select proper algorithms. In this case, - * the driver has to notify wpa_supplicant about the used WPA - * IE by generating an event that the interface code will - * convert into EVENT_ASSOCINFO data (see wpa_supplicant.h). - * When using WPA2/IEEE 802.11i, @wpa_ie is used for RSN IE - * instead. The driver can determine which version is used by - * looking at the first byte of the IE (0xdd for WPA, 0x30 for - * WPA2/RSN). @wpa_ie_len: length of the @wpa_ie */ - const u8 *wpa_ie; - size_t wpa_ie_len; - - /* The selected pairwise/group cipher and key management - * suites. These are usually ignored if @wpa_ie is used. */ - wpa_cipher pairwise_suite; - wpa_cipher group_suite; - wpa_key_mgmt key_mgmt_suite; - - int auth_alg; /* bit field of AUTH_ALG_* */ - int mode; /* IEEE80211_MODE_* */ -}; - -struct wpa_driver_capa { -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA 0x00000001 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2 0x00000002 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK 0x00000004 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK 0x00000008 -#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE 0x00000010 - unsigned int key_mgmt; - -#define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001 -#define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 -#define WPA_DRIVER_CAPA_ENC_TKIP 0x00000004 -#define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008 - unsigned int enc; - -#define WPA_DRIVER_AUTH_OPEN 0x00000001 -#define WPA_DRIVER_AUTH_SHARED 0x00000002 -#define WPA_DRIVER_AUTH_LEAP 0x00000004 - unsigned int auth; - -/* Driver generated WPA/RSN IE */ -#define WPA_DRIVER_FLAGS_DRIVER_IE 0x00000001 -#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002 - unsigned int flags; -}; - - -struct wpa_driver_ops { - /* name of the driver interface */ - const char *name; - /* one line description of the driver interface */ - const char *desc; - - /** - * get_bssid - get the current BSSID - * @priv: private driver interface data - * @bssid: buffer for BSSID (ETH_ALEN = 6 bytes) - * - * Returns: 0 on success, -1 on failure - * - * Query kernel driver for the current BSSID and copy it to @bssid. - * Setting @bssid to 00:00:00:00:00:00 is recommended if the STA is not - * associated. - */ - int (*get_bssid)(void *priv, u8 *bssid); - - /** - * get_ssid - get the current SSID - * @priv: private driver interface data - * @ssid: buffer for SSID (at least 32 bytes) - * - * Returns: length of the SSID on success, -1 on failure - * - * Query kernel driver for the current SSID and copy it to @ssid. - * Returning zero is recommended if the STA is not associated. - * - * Note: SSID is an array of octets, i.e., it is not nul terminated and - * can, at least in theory, contain control characters (including nul) - * and as such, should be processed as binary data, not a printable - * string. - */ - int (*get_ssid)(void *priv, u8 *ssid); - - /** - * set_wpa - enable/disable WPA support - * @priv: private driver interface data - * @enabled: 1 = enable, 0 = disable - * - * Returns: 0 on success, -1 on failure - * - * Configure the kernel driver to enable/disable WPA support. This may - * be empty function, if WPA support is always enabled. Common - * configuration items are WPA IE (clearing it when WPA support is - * disabled), Privacy flag for capability field, roaming mode (need to - * allow wpa_supplicant to control roaming). - */ - int (*set_wpa)(void *priv, int enabled); - - /** - * set_key - configure encryption key - * @priv: private driver interface data - * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, - * %WPA_ALG_TKIP, %WPA_ALG_CCMP); %WPA_ALG_NONE clears the key. - * @addr: address of the peer STA or ff:ff:ff:ff:ff:ff for - * broadcast/default keys - * @key_idx: key index (0..3), always 0 for unicast keys - * @set_tx: configure this key as the default Tx key (only used when - * driver does not support separate unicast/individual key - * @seq: sequence number/packet number, @seq_len octets, the next - * packet number to be used for in replay protection; configured - * for Rx keys (in most cases, this is only used with broadcast - * keys and set to zero for unicast keys) - * @seq_len: length of the @seq, depends on the algorithm: - * TKIP: 6 octets, CCMP: 6 octets - * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, - * 8-byte Rx Mic Key - * @key_len: length of the key buffer in octets (WEP: 5 or 13, - * TKIP: 32, CCMP: 16) - * - * Returns: 0 on success, -1 on failure - * - * Configure the given key for the kernel driver. If the driver - * supports separate individual keys (4 default keys + 1 individual), - * @addr can be used to determine whether the key is default or - * individual. If only 4 keys are supported, the default key with key - * index 0 is used as the individual key. STA must be configured to use - * it as the default Tx key (@set_tx is set) and accept Rx for all the - * key indexes. In most cases, WPA uses only key indexes 1 and 2 for - * broadcast keys, so key index 0 is available for this kind of - * configuration. - */ - int (*set_key)(void *priv, wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len); - - /** - * init - initialize driver interface - * @ctx: context to be used when calling wpa_supplicant functions, - * e.g., wpa_supplicant_event() - * @ifname: interface name, e.g., wlan0 - * - * Return: pointer to private data, %NULL on failure - * - * Initialize driver interface, including event processing for kernel - * driver events (e.g., associated, scan results, Michael MIC failure). - * This function can allocate a private configuration data area for - * @ctx, file descriptor, interface name, etc. information that may be - * needed in future driver operations. If this is not used, non-NULL - * value will need to be returned because %NULL is used to indicate - * failure. The returned value will be used as 'void *priv' data for - * all other driver_ops functions. - * - * The main event loop (eloop.c) of wpa_supplicant can be used to - * register callback for read sockets (eloop_register_read_sock()). - * - * See wpa_supplicant.h for more information about events and - * wpa_supplicant_event() function. - */ - void * (*init)(void *ctx, const char *ifname); - - /** - * deinit - deinitialize driver interface - * @priv: pointer to private data (from matching - * wpa_driver_events_init()) - * - * Shut down driver interface and processing of driver events. Free - * private data buffer if one was allocated in init() handler. - */ - void (*deinit)(void *priv); - - /** - * set_countermeasures - enable/disable TKIP countermeasures - * @priv: private driver interface data - * @enabled: 1 = countermeasures enabled, 0 = disabled - * - * Return: 0 on success, -1 on failure - * - * Configure TKIP countermeasures. When these are enabled, the driver - * should drop all received and queued frames that are using TKIP. - */ - int (*set_countermeasures)(void *priv, int enabled); - - /** - * set_drop_unencrypted - enable/disable unencrypted frame filtering - * @priv: private driver interface data - * @enabled: 1 = unencrypted Tx/Rx frames will be dropped, 0 = disabled - * - * Return: 0 on success, -1 on failure - * - * Configure the driver to drop all non-EAPOL frames (both receive and - * transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must - * still be allowed for key negotiation. - */ - int (*set_drop_unencrypted)(void *priv, int enabled); - - /** - * scan - request the driver to initiate scan - * @priv: private driver interface data - * @ssid: specific SSID to scan for (ProbeReq) or %NULL to scan for - * all SSIDs (either active scan with broadcast SSID or passive - * scan - * @ssid_len: length of the SSID - * - * Return: 0 on success, -1 on failure - * - * Once the scan results are ready, the driver should report scan - * results event for wpa_supplicant which will eventually request the - * results with wpa_driver_get_scan_results(). - */ - int (*scan)(void *priv, const u8 *ssid, size_t ssid_len); - - /** - * get_scan_results - fetch the latest scan results - * @priv: private driver interface data - * @results: pointer to buffer for scan results - * @max_size: maximum number of entries (buffer size) - * - * Return: number of scan result entries used on success, -1 on failure - * - * If scan results include more than @max_size BSSes, @max_size will be - * returned and the remaining entries will not be included in the - * buffer. - */ - int (*get_scan_results)(void *priv, - struct wpa_scan_result *results, - size_t max_size); - - /** - * deauthenticate - request driver to deauthenticate - * @priv: private driver interface data - * @addr: peer address (BSSID of the AP) - * @reason_code: 16-bit reason code to be sent in the deauthentication - * frame - * - * Return: 0 on success, -1 on failure - */ - int (*deauthenticate)(void *priv, const u8 *addr, int reason_code); - - /** - * disassociate - request driver to disassociate - * @priv: private driver interface data - * @addr: peer address (BSSID of the AP) - * @reason_code: 16-bit reason code to be sent in the disassociation - * frame - * - * Return: 0 on success, -1 on failure - */ - int (*disassociate)(void *priv, const u8 *addr, int reason_code); - - /** - * associate - request driver to associate - * @priv: private driver interface data - * @params: association parameters - * - * Return: 0 on success, -1 on failure - */ - int (*associate)(void *priv, - struct wpa_driver_associate_params *params); - - /** - * set_auth_alg - set IEEE 802.11 authentication algorithm - * @priv: private driver interface data - * @auth_alg: bit field of AUTH_ALG_* - * - * If the driver supports more than one authentication algorithm at the - * same time, it should configure all supported algorithms. If not, one - * algorithm needs to be selected arbitrarily. Open System - * authentication should be ok for most cases and it is recommended to - * be used if other options are not supported. Static WEP configuration - * may also use Shared Key authentication and LEAP requires its own - * algorithm number. For LEAP, user can make sure that only one - * algorithm is used at a time by configuring LEAP as the only - * supported EAP method. This information is also available in - * associate() params, so set_auth_alg may not be needed in case of - * most drivers. - * - * Return: 0 on success, -1 on failure - */ - int (*set_auth_alg)(void *priv, int auth_alg); - - /** - * add_pmkid - add PMKSA cache entry to the driver - * @priv: private driver interface data - * @bssid: BSSID for the PMKSA cache entry - * @pmkid: PMKID for the PMKSA cache entry - * - * Return: 0 on success, -1 on failure - * - * This function is called when a new PMK is received, as a result of - * either normal authentication or RSN pre-authentication. - * - * If the driver generates RSN IE, i.e., it does not use @wpa_ie in - * associate(), add_pmkid() can be used to add new PMKSA cache entries - * in the driver. If the driver uses @wpa_ie from wpa_supplicant, this - * driver_ops function does not need to be implemented. Likewise, if - * the driver does not support WPA, this function is not needed. - */ - int (*add_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); - - /** - * remove_pmkid - remove PMKSA cache entry to the driver - * @priv: private driver interface data - * @bssid: BSSID for the PMKSA cache entry - * @pmkid: PMKID for the PMKSA cache entry - * - * Return: 0 on success, -1 on failure - * - * This function is called when the supplicant drops a PMKSA cache - * entry for any reason. - * - * If the driver generates RSN IE, i.e., it does not use @wpa_ie in - * associate(), remove_pmkid() can be used to synchronize PMKSA caches - * between the driver and wpa_supplicant. If the driver uses @wpa_ie - * from wpa_supplicant, this driver_ops function does not need to be - * implemented. Likewise, if the driver does not support WPA, this - * function is not needed. - */ - int (*remove_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); - - /** - * flush_pmkid - flush PMKSA cache - * @priv: private driver interface data - * - * Return: 0 on success, -1 on failure - * - * This function is called when the supplicant drops all PMKSA cache - * entries for any reason. - * - * If the driver generates RSN IE, i.e., it does not use @wpa_ie in - * associate(), remove_pmkid() can be used to synchronize PMKSA caches - * between the driver and wpa_supplicant. If the driver uses @wpa_ie - * from wpa_supplicant, this driver_ops function does not need to be - * implemented. Likewise, if the driver does not support WPA, this - * function is not needed. - */ - int (*flush_pmkid)(void *priv); - - /** - * flush_pmkid - flush PMKSA cache - * @priv: private driver interface data - * - * Return: 0 on success, -1 on failure - * - * Get driver/firmware/hardware capabilities. - */ - int (*get_capa)(void *priv, struct wpa_driver_capa *capa); - - /** - * poll - poll driver for association information - * @priv: private driver interface data - * - * This is an option callback that can be used when the driver does not - * provide event mechanism for association events. This is called when - * receiving WPA EAPOL-Key messages that require association - * information. The driver interface is supposed to generate associnfo - * event before returning from this callback function. In addition, the - * driver interface should generate an association event after having - * sent out associnfo. - */ - void (*poll)(void *priv); - - /** - * get_ifname - get interface name - * - * This optional function can be used to allow the driver interface to - * replace the interface name with something else, e.g., based on an - * interface mapping from a more descriptive name. - * - * Returns a pointer to the interface name. This can differ from the - * interface name used in init() call. - */ - const char * (*get_ifname)(void *priv); - - /** - * get_mac_addr - get own MAC address - * - * This optional function can be used to get the own MAC address of the - * device from the driver interface code. This is only needed if the - * l2_packet implementation for the OS does not provide easy access to - * a MAC address. */ - const u8 * (*get_mac_addr)(void *priv); -}; - -#endif /* DRIVER_H */ diff --git a/contrib/wpa_supplicant/driver_ndis.h b/contrib/wpa_supplicant/driver_ndis.h deleted file mode 100644 index a79afcbfcf2d..000000000000 --- a/contrib/wpa_supplicant/driver_ndis.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef DRIVER_NDIS_H -#define DRIVER_NDIS_H - -struct ndis_pmkid_entry { - struct ndis_pmkid_entry *next; - u8 bssid[ETH_ALEN]; - u8 pmkid[16]; -}; - -struct wpa_driver_ndis_data { - void *ctx; - char ifname[100]; - u8 own_addr[ETH_ALEN]; - LPADAPTER adapter; - u8 bssid[ETH_ALEN]; - - int has_capability; - int no_of_pmkid; - int radio_enabled; - struct wpa_driver_capa capa; - struct ndis_pmkid_entry *pmkid; - int event_sock; - char *adapter_desc; -}; - -#endif /* DRIVER_NDIS_H */ diff --git a/contrib/wpa_supplicant/driver_ndis_.c b/contrib/wpa_supplicant/driver_ndis_.c deleted file mode 100644 index e71b13be9a7a..000000000000 --- a/contrib/wpa_supplicant/driver_ndis_.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - event processing - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/unistd.h> -#include <sys/types.h> -#ifndef CONFIG_NATIVE_WINDOWS -#include <sys/socket.h> -#include <netinet/in.h> -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "common.h" -#include "driver.h" -#include "wpa_supplicant.h" -#include "l2_packet.h" -#include "eloop.h" -#include "wpa.h" - -/* Keep this event processing in a separate file and without WinPcap headers to - * avoid conflicts with some of the header files. */ -struct _ADAPTER; -typedef struct _ADAPTER * LPADAPTER; -#include "driver_ndis.h" - - -void wpa_driver_ndis_event_connect(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_disconnect(struct wpa_driver_ndis_data *drv); -void wpa_driver_ndis_event_media_specific(struct wpa_driver_ndis_data *drv, - const u8 *data, size_t data_len); - - -enum event_types { EVENT_CONNECT, EVENT_DISCONNECT, - EVENT_MEDIA_SPECIFIC }; - -/* Event data: - * enum event_types (as int, i.e., 4 octets) - * InstanceName length (1 octet) - * InstanceName (variable len) - * data length (1 octet, optional) - * data (variable len, optional) - */ - - -static void wpa_driver_ndis_event_cb(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wpa_driver_ndis_data *drv = eloop_ctx; - u8 buf[512], *pos, *data = NULL; - int res, i, desc_len; - enum event_types type; - unsigned char instance_len; - char *instance; - size_t data_len = 0; - - res = recv(sock, buf, sizeof(buf), 0); - if (res < 0) { - perror("wpa_driver_ndis_event_cb - recv"); - return; - } - wpa_hexdump(MSG_MSGDUMP, "NDIS: received event data", buf, res); - if (res < sizeof(int) + 1) - return; - type = *((int *) buf); - pos = buf + sizeof(int); - wpa_printf(MSG_DEBUG, "NDIS: event - type %d", type); - instance_len = *pos++; - if (instance_len > buf + res - pos) { - wpa_printf(MSG_DEBUG, "NDIS: event InstanceName overflow"); - return; - } - instance = pos; - pos += instance_len; - wpa_hexdump_ascii(MSG_MSGDUMP, "NDIS: event InstanceName", - instance, instance_len); - - if (buf + res - pos > 1) { - data_len = *pos++; - if (data_len > buf + res - pos) { - wpa_printf(MSG_DEBUG, "NDIS: event data overflow"); - return; - } - data = pos; - wpa_hexdump(MSG_MSGDUMP, "NDIS: event data", data, data_len); - } - - if (drv->adapter_desc) { - desc_len = strlen(drv->adapter_desc); - if (instance_len < desc_len || - strncmp(drv->adapter_desc, instance, desc_len)) { - wpa_printf(MSG_DEBUG, "NDIS: ignored event for " - "another adapter"); - return; - } - - /* InstanceName: - * <driver desc> #<num> - * <driver desc> #<num> - <intermediate drv name> Miniport - */ - for (i = desc_len + 1; i < instance_len; i++) { - if (instance[i] == '-') { - wpa_printf(MSG_DEBUG, "NDIS: ignored event " - "for intermediate miniport"); - return; - } - } - } - - switch (type) { - case EVENT_CONNECT: - wpa_driver_ndis_event_connect(drv); - break; - case EVENT_DISCONNECT: - wpa_driver_ndis_event_disconnect(drv); - break; - case EVENT_MEDIA_SPECIFIC: - wpa_driver_ndis_event_media_specific(drv, data, data_len); - break; - } -} - - -int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv) -{ - struct sockaddr_in addr; - - drv->event_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->event_sock < 0) { - perror("socket"); - return -1; - } - - /* These events are received from an external program, ndis_events, - * which is converting WMI events to more "UNIX-like" input for - * wpa_supplicant, i.e., UDP packets that can be received through the - * eloop mechanism. */ - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl((127 << 24) | 1); - addr.sin_port = htons(9876); - if (bind(drv->event_sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) - { - perror("bind"); - close(drv->event_sock); - drv->event_sock = -1; - return -1; - } - - eloop_register_read_sock(drv->event_sock, wpa_driver_ndis_event_cb, - drv, NULL); - - return 0; -} diff --git a/contrib/wpa_supplicant/drivers.c b/contrib/wpa_supplicant/drivers.c deleted file mode 100644 index cb016ba803e5..000000000000 --- a/contrib/wpa_supplicant/drivers.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * WPA Supplicant / driver interface list - * Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> - - -#ifdef CONFIG_DRIVER_HOSTAP -extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_PRISM54 -extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */ -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_HERMES -extern struct wpa_driver_ops wpa_driver_hermes_ops; /* driver_hermes.c */ -#endif /* CONFIG_DRIVER_HERMES */ -#ifdef CONFIG_DRIVER_MADWIFI -extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATMEL -extern struct wpa_driver_ops wpa_driver_atmel_ops; /* driver_atmel.c */ -#endif /* CONFIG_DRIVER_ATMEL */ -#ifdef CONFIG_DRIVER_WEXT -extern struct wpa_driver_ops wpa_driver_wext_ops; /* driver_wext.c */ -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_NDISWRAPPER -/* driver_ndiswrapper.c */ -extern struct wpa_driver_ops wpa_driver_ndiswrapper_ops; -#endif /* CONFIG_DRIVER_NDISWRAPPER */ -#ifdef CONFIG_DRIVER_BROADCOM -extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */ -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_IPW -extern struct wpa_driver_ops wpa_driver_ipw_ops; /* driver_ipw.c */ -#endif /* CONFIG_DRIVER_IPW */ -#ifdef CONFIG_DRIVER_BSD -extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */ -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_NDIS -extern struct wpa_driver_ops wpa_driver_ndis_ops; /* driver_ndis.c */ -#endif /* CONFIG_DRIVER_NDIS */ -#ifdef CONFIG_DRIVER_TEST -extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */ -#endif /* CONFIG_DRIVER_TEST */ - - -struct wpa_driver_ops *wpa_supplicant_drivers[] = -{ -#ifdef CONFIG_DRIVER_HOSTAP - &wpa_driver_hostap_ops, -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_PRISM54 - &wpa_driver_prism54_ops, -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_HERMES - &wpa_driver_hermes_ops, -#endif /* CONFIG_DRIVER_HERMES */ -#ifdef CONFIG_DRIVER_MADWIFI - &wpa_driver_madwifi_ops, -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATMEL - &wpa_driver_atmel_ops, -#endif /* CONFIG_DRIVER_ATMEL */ -#ifdef CONFIG_DRIVER_WEXT - &wpa_driver_wext_ops, -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_NDISWRAPPER - &wpa_driver_ndiswrapper_ops, -#endif /* CONFIG_DRIVER_NDISWRAPPER */ -#ifdef CONFIG_DRIVER_BROADCOM - &wpa_driver_broadcom_ops, -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_IPW - &wpa_driver_ipw_ops, -#endif /* CONFIG_DRIVER_IPW */ -#ifdef CONFIG_DRIVER_BSD - &wpa_driver_bsd_ops, -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_NDIS - &wpa_driver_ndis_ops, -#endif /* CONFIG_DRIVER_NDIS */ -#ifdef CONFIG_DRIVER_TEST - &wpa_driver_test_ops, -#endif /* CONFIG_DRIVER_TEST */ - NULL -}; diff --git a/contrib/wpa_supplicant/eap.c b/contrib/wpa_supplicant/eap.c deleted file mode 100644 index 267907c27fe0..000000000000 --- a/contrib/wpa_supplicant/eap.c +++ /dev/null @@ -1,1251 +0,0 @@ -/* - * WPA Supplicant / EAP state machines - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "tls.h" -#include "md5.h" - - -#define EAP_MAX_AUTH_ROUNDS 50 - - -#ifdef EAP_MD5 -extern const struct eap_method eap_method_md5; -#endif -#ifdef EAP_TLS -extern const struct eap_method eap_method_tls; -#endif -#ifdef EAP_MSCHAPv2 -extern const struct eap_method eap_method_mschapv2; -#endif -#ifdef EAP_PEAP -extern const struct eap_method eap_method_peap; -#endif -#ifdef EAP_TTLS -extern const struct eap_method eap_method_ttls; -#endif -#ifdef EAP_GTC -extern const struct eap_method eap_method_gtc; -#endif -#ifdef EAP_OTP -extern const struct eap_method eap_method_otp; -#endif -#ifdef EAP_SIM -extern const struct eap_method eap_method_sim; -#endif -#ifdef EAP_LEAP -extern const struct eap_method eap_method_leap; -#endif -#ifdef EAP_PSK -extern const struct eap_method eap_method_psk; -#endif -#ifdef EAP_AKA -extern const struct eap_method eap_method_aka; -#endif -#ifdef EAP_FAST -extern const struct eap_method eap_method_fast; -#endif - -static const struct eap_method *eap_methods[] = -{ -#ifdef EAP_MD5 - &eap_method_md5, -#endif -#ifdef EAP_TLS - &eap_method_tls, -#endif -#ifdef EAP_MSCHAPv2 - &eap_method_mschapv2, -#endif -#ifdef EAP_PEAP - &eap_method_peap, -#endif -#ifdef EAP_TTLS - &eap_method_ttls, -#endif -#ifdef EAP_GTC - &eap_method_gtc, -#endif -#ifdef EAP_OTP - &eap_method_otp, -#endif -#ifdef EAP_SIM - &eap_method_sim, -#endif -#ifdef EAP_LEAP - &eap_method_leap, -#endif -#ifdef EAP_PSK - &eap_method_psk, -#endif -#ifdef EAP_AKA - &eap_method_aka, -#endif -#ifdef EAP_FAST - &eap_method_fast, -#endif -}; -#define NUM_EAP_METHODS (sizeof(eap_methods) / sizeof(eap_methods[0])) - - -const struct eap_method * eap_sm_get_eap_methods(int method) -{ - int i; - for (i = 0; i < NUM_EAP_METHODS; i++) { - if (eap_methods[i]->method == method) - return eap_methods[i]; - } - return NULL; -} - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method); -static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len); -static void eap_sm_processIdentity(struct eap_sm *sm, u8 *req, size_t len); -static void eap_sm_processNotify(struct eap_sm *sm, u8 *req, size_t len); -static u8 * eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len); -static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len); -static const char * eap_sm_method_state_txt(int state); -static const char * eap_sm_decision_txt(int decision); - - -/* Definitions for clarifying state machine implementation */ -#define SM_STATE(machine, state) \ -static void sm_ ## machine ## _ ## state ## _Enter(struct eap_sm *sm, \ - int global) - -#define SM_ENTRY(machine, state) \ -if (!global || sm->machine ## _state != machine ## _ ## state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, "EAP: " #machine " entering state " #state); \ -} \ -sm->machine ## _state = machine ## _ ## state; - -#define SM_ENTER(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 0) -#define SM_ENTER_GLOBAL(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 1) - -#define SM_STEP(machine) \ -static void sm_ ## machine ## _Step(struct eap_sm *sm) - -#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) - - -static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) -{ - return sm->eapol_cb->get_bool(sm->eapol_ctx, var); -} - - -static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var, - Boolean value) -{ - sm->eapol_cb->set_bool(sm->eapol_ctx, var, value); -} - - -static unsigned int eapol_get_int(struct eap_sm *sm, enum eapol_int_var var) -{ - return sm->eapol_cb->get_int(sm->eapol_ctx, var); -} - - -static void eapol_set_int(struct eap_sm *sm, enum eapol_int_var var, - unsigned int value) -{ - sm->eapol_cb->set_int(sm->eapol_ctx, var, value); -} - - -static u8 * eapol_get_eapReqData(struct eap_sm *sm, size_t *len) -{ - return sm->eapol_cb->get_eapReqData(sm->eapol_ctx, len); -} - - -static void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) -{ - if (sm->m == NULL || sm->eap_method_priv == NULL) - return; - - wpa_printf(MSG_DEBUG, "EAP: deinitialize previously used EAP method " - "(%d, %s) at %s", sm->selectedMethod, sm->m->name, txt); - sm->m->deinit(sm, sm->eap_method_priv); - sm->eap_method_priv = NULL; - sm->m = NULL; -} - - -SM_STATE(EAP, INITIALIZE) -{ - SM_ENTRY(EAP, INITIALIZE); - if (sm->fast_reauth && sm->m && sm->m->has_reauth_data && - sm->m->has_reauth_data(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: maintaining EAP method data for " - "fast reauthentication"); - sm->m->deinit_for_reauth(sm, sm->eap_method_priv); - } else { - eap_deinit_prev_method(sm, "INITIALIZE"); - } - sm->selectedMethod = EAP_TYPE_NONE; - sm->methodState = METHOD_NONE; - sm->allowNotifications = TRUE; - sm->decision = DECISION_FAIL; - eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); - eapol_set_bool(sm, EAPOL_eapFail, FALSE); - free(sm->eapKeyData); - sm->eapKeyData = NULL; - sm->eapKeyAvailable = FALSE; - eapol_set_bool(sm, EAPOL_eapRestart, FALSE); - sm->lastId = -1; /* new session - make sure this does not match with - * the first EAP-Packet */ - /* draft-ietf-eap-statemachine-02.pdf does not reset eapResp and - * eapNoResp here. However, this seemed to be able to trigger cases - * where both were set and if EAPOL state machine uses eapNoResp first, - * it may end up not sending a real reply correctly. This occurred - * when the workaround in FAIL state set eapNoResp = TRUE.. Maybe that - * workaround needs to be fixed to do something else(?) */ - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); - sm->num_rounds = 0; -} - - -SM_STATE(EAP, DISABLED) -{ - SM_ENTRY(EAP, DISABLED); - sm->num_rounds = 0; -} - - -SM_STATE(EAP, IDLE) -{ - SM_ENTRY(EAP, IDLE); -} - - -SM_STATE(EAP, RECEIVED) -{ - u8 *eapReqData; - size_t eapReqDataLen; - - SM_ENTRY(EAP, RECEIVED); - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */ - eap_sm_parseEapReq(sm, eapReqData, eapReqDataLen); - sm->num_rounds++; -} - - -SM_STATE(EAP, GET_METHOD) -{ - SM_ENTRY(EAP, GET_METHOD); - if (eap_sm_allowMethod(sm, sm->reqMethod)) { - int reinit = 0; - if (sm->fast_reauth && - sm->m && sm->m->method == sm->reqMethod && - sm->m->has_reauth_data && - sm->m->has_reauth_data(sm, sm->eap_method_priv)) { - wpa_printf(MSG_DEBUG, "EAP: using previous method data" - " for fast re-authentication"); - reinit = 1; - } else - eap_deinit_prev_method(sm, "GET_METHOD"); - sm->selectedMethod = sm->reqMethod; - if (sm->m == NULL) - sm->m = eap_sm_get_eap_methods(sm->selectedMethod); - if (sm->m) { - wpa_printf(MSG_DEBUG, "EAP: initialize selected EAP " - "method (%d, %s)", - sm->selectedMethod, sm->m->name); - if (reinit) - sm->eap_method_priv = sm->m->init_for_reauth( - sm, sm->eap_method_priv); - else - sm->eap_method_priv = sm->m->init(sm); - if (sm->eap_method_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP: Failed to " - "initialize EAP method %d", - sm->selectedMethod); - sm->m = NULL; - sm->methodState = METHOD_NONE; - sm->selectedMethod = EAP_TYPE_NONE; - } else { - sm->methodState = METHOD_INIT; - return; - } - } - } - - free(sm->eapRespData); - sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen); -} - - -SM_STATE(EAP, METHOD) -{ - u8 *eapReqData; - size_t eapReqDataLen; - struct eap_method_ret ret; - - SM_ENTRY(EAP, METHOD); - if (sm->m == NULL) { - wpa_printf(MSG_WARNING, "EAP::METHOD - method not selected"); - return; - } - - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - - /* Get ignore, methodState, decision, allowNotifications, and - * eapRespData. */ - memset(&ret, 0, sizeof(ret)); - ret.ignore = sm->ignore; - ret.methodState = sm->methodState; - ret.decision = sm->decision; - ret.allowNotifications = sm->allowNotifications; - free(sm->eapRespData); - sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret, - eapReqData, eapReqDataLen, - &sm->eapRespDataLen); - wpa_printf(MSG_DEBUG, "EAP: method process -> ignore=%s " - "methodState=%s decision=%s", - ret.ignore ? "TRUE" : "FALSE", - eap_sm_method_state_txt(ret.methodState), - eap_sm_decision_txt(ret.decision)); - - sm->ignore = ret.ignore; - if (sm->ignore) - return; - sm->methodState = ret.methodState; - sm->decision = ret.decision; - sm->allowNotifications = ret.allowNotifications; - - if (sm->m->isKeyAvailable && sm->m->getKey && - sm->m->isKeyAvailable(sm, sm->eap_method_priv)) { - free(sm->eapKeyData); - sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv, - &sm->eapKeyDataLen); - } -} - - -SM_STATE(EAP, SEND_RESPONSE) -{ - SM_ENTRY(EAP, SEND_RESPONSE); - free(sm->lastRespData); - if (sm->eapRespData) { - if (sm->workaround) - memcpy(sm->last_md5, sm->req_md5, 16); - sm->lastId = sm->reqId; - sm->lastRespData = malloc(sm->eapRespDataLen); - if (sm->lastRespData) { - memcpy(sm->lastRespData, sm->eapRespData, - sm->eapRespDataLen); - sm->lastRespDataLen = sm->eapRespDataLen; - } - eapol_set_bool(sm, EAPOL_eapResp, TRUE); - } else - sm->lastRespData = NULL; - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); -} - - -SM_STATE(EAP, DISCARD) -{ - SM_ENTRY(EAP, DISCARD); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); -} - - -SM_STATE(EAP, IDENTITY) -{ - u8 *eapReqData; - size_t eapReqDataLen; - - SM_ENTRY(EAP, IDENTITY); - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - eap_sm_processIdentity(sm, eapReqData, eapReqDataLen); - free(sm->eapRespData); - sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, - &sm->eapRespDataLen, 0); -} - - -SM_STATE(EAP, NOTIFICATION) -{ - u8 *eapReqData; - size_t eapReqDataLen; - - SM_ENTRY(EAP, NOTIFICATION); - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - eap_sm_processNotify(sm, eapReqData, eapReqDataLen); - free(sm->eapRespData); - sm->eapRespData = eap_sm_buildNotify(sm, sm->reqId, - &sm->eapRespDataLen); -} - - -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - free(sm->eapRespData); - if (sm->lastRespData) { - sm->eapRespData = malloc(sm->lastRespDataLen); - if (sm->eapRespData) { - memcpy(sm->eapRespData, sm->lastRespData, - sm->lastRespDataLen); - sm->eapRespDataLen = sm->lastRespDataLen; - } - } else - sm->eapRespData = NULL; -} - - -SM_STATE(EAP, SUCCESS) -{ - SM_ENTRY(EAP, SUCCESS); - if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - /* draft-ietf-eap-statemachine-02.pdf does not clear eapReq here, but - * this seems to be required to avoid processing the same request - * twice when state machine is initialized. */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - /* draft-ietf-eap-statemachine-02.pdf does not set eapNoResp here, but - * this seems to be required to get EAPOL Supplicant backend state - * machine into SUCCESS state. In addition, either eapResp or eapNoResp - * is required to be set after processing the received EAP frame. */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); -} - - -SM_STATE(EAP, FAILURE) -{ - SM_ENTRY(EAP, FAILURE); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); - /* draft-ietf-eap-statemachine-02.pdf does not clear eapReq here, but - * this seems to be required to avoid processing the same request - * twice when state machine is initialized. */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - /* draft-ietf-eap-statemachine-02.pdf does not set eapNoResp here. - * However, either eapResp or eapNoResp is required to be set after - * processing the received EAP frame. */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); -} - - -static int eap_success_workaround(struct eap_sm *sm, int reqId, int lastId) -{ - /* - * At least Microsoft IAS and Meetinghouse Aegis seem to be sending - * EAP-Success/Failure with lastId + 1 even though RFC 3748 and - * draft-ietf-eap-statemachine-05.pdf require that reqId == lastId. - * In addition, it looks like Ringmaster v2.1.2.0 would be using - * lastId + 2 in EAP-Success. - * - * Accept this kind of Id if EAP workarounds are enabled. These are - * unauthenticated plaintext messages, so this should have minimal - * security implications (bit easier to fake EAP-Success/Failure). - */ - if (sm->workaround && (reqId == ((lastId + 1) & 0xff) || - reqId == ((lastId + 2) & 0xff))) { - wpa_printf(MSG_DEBUG, "EAP: Workaround for unexpected " - "identifier field in EAP Success: " - "reqId=%d lastId=%d (these are supposed to be " - "same)", reqId, lastId); - return 1; - } - wpa_printf(MSG_DEBUG, "EAP: EAP-Success Id mismatch - reqId=%d " - "lastId=%d", reqId, lastId); - return 0; -} - - -SM_STEP(EAP) -{ - int duplicate; - - if (eapol_get_bool(sm, EAPOL_eapRestart) && - eapol_get_bool(sm, EAPOL_portEnabled)) - SM_ENTER_GLOBAL(EAP, INITIALIZE); - else if (!eapol_get_bool(sm, EAPOL_portEnabled)) - SM_ENTER_GLOBAL(EAP, DISABLED); - else if (sm->num_rounds > EAP_MAX_AUTH_ROUNDS) { - if (sm->num_rounds == EAP_MAX_AUTH_ROUNDS + 1) { - wpa_printf(MSG_DEBUG, "EAP: more than %d " - "authentication rounds - abort", - EAP_MAX_AUTH_ROUNDS); - sm->num_rounds++; - SM_ENTER_GLOBAL(EAP, FAILURE); - } - } else switch (sm->EAP_state) { - case EAP_INITIALIZE: - SM_ENTER(EAP, IDLE); - break; - case EAP_DISABLED: - if (eapol_get_bool(sm, EAPOL_portEnabled)) - SM_ENTER(EAP, INITIALIZE); - break; - case EAP_IDLE: - if (eapol_get_bool(sm, EAPOL_eapReq)) - SM_ENTER(EAP, RECEIVED); - else if ((eapol_get_bool(sm, EAPOL_altAccept) && - sm->decision != DECISION_FAIL) || - (eapol_get_int(sm, EAPOL_idleWhile) == 0 && - sm->decision == DECISION_UNCOND_SUCC)) - SM_ENTER(EAP, SUCCESS); - else if (eapol_get_bool(sm, EAPOL_altReject) || - (eapol_get_int(sm, EAPOL_idleWhile) == 0 && - sm->decision != DECISION_UNCOND_SUCC) || - (eapol_get_bool(sm, EAPOL_altAccept) && - sm->methodState != METHOD_CONT && - sm->decision == DECISION_FAIL)) - SM_ENTER(EAP, FAILURE); - else if (sm->selectedMethod == EAP_TYPE_LEAP && - sm->leap_done && sm->decision != DECISION_FAIL && - sm->methodState == METHOD_DONE) - SM_ENTER(EAP, SUCCESS); - else if (sm->selectedMethod == EAP_TYPE_PEAP && - sm->peap_done && sm->decision != DECISION_FAIL && - sm->methodState == METHOD_DONE) - SM_ENTER(EAP, SUCCESS); - break; - case EAP_RECEIVED: - duplicate = sm->reqId == sm->lastId; - if (sm->workaround && duplicate && - memcmp(sm->req_md5, sm->last_md5, 16) != 0) { - /* draft-ietf-eap-statemachine-05.txt uses - * (reqId == lastId) as the only verification for - * duplicate EAP requests. However, this misses cases - * where the AS is incorrectly using the same id again; - * and unfortunately, such implementations exist. Use - * MD5 hash as an extra verification for the packets - * being duplicate to workaround these issues. */ - wpa_printf(MSG_DEBUG, "EAP: AS used the same Id again," - " but EAP packets were not identical"); - wpa_printf(MSG_DEBUG, "EAP: workaround - assume this " - "is not a duplicate packet"); - duplicate = 0; - } - - if (sm->rxSuccess && - (sm->reqId == sm->lastId || - eap_success_workaround(sm, sm->reqId, sm->lastId)) && - sm->decision != DECISION_FAIL) - SM_ENTER(EAP, SUCCESS); - else if (sm->methodState != METHOD_CONT && - ((sm->rxFailure && - sm->decision != DECISION_UNCOND_SUCC) || - (sm->rxSuccess && sm->decision == DECISION_FAIL)) && - (sm->reqId == sm->lastId || - eap_success_workaround(sm, sm->reqId, sm->lastId))) - SM_ENTER(EAP, FAILURE); - else if (sm->rxReq && duplicate) - SM_ENTER(EAP, RETRANSMIT); - else if (sm->rxReq && !duplicate && - sm->reqMethod == EAP_TYPE_NOTIFICATION && - sm->allowNotifications) - SM_ENTER(EAP, NOTIFICATION); - else if (sm->rxReq && !duplicate && - sm->selectedMethod == EAP_TYPE_NONE && - sm->reqMethod == EAP_TYPE_IDENTITY) - SM_ENTER(EAP, IDENTITY); - else if (sm->rxReq && !duplicate && - sm->selectedMethod == EAP_TYPE_NONE && - sm->reqMethod != EAP_TYPE_IDENTITY && - sm->reqMethod != EAP_TYPE_NOTIFICATION) - SM_ENTER(EAP, GET_METHOD); - else if (sm->rxReq && !duplicate && - sm->reqMethod == sm->selectedMethod && - sm->methodState != METHOD_DONE) - SM_ENTER(EAP, METHOD); - else if (sm->selectedMethod == EAP_TYPE_LEAP && - (sm->rxSuccess || sm->rxResp)) - SM_ENTER(EAP, METHOD); - else - SM_ENTER(EAP, DISCARD); - break; - case EAP_GET_METHOD: - if (sm->selectedMethod == sm->reqMethod) - SM_ENTER(EAP, METHOD); - else - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_METHOD: - if (sm->ignore) - SM_ENTER(EAP, DISCARD); - else - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_SEND_RESPONSE: - SM_ENTER(EAP, IDLE); - break; - case EAP_DISCARD: - SM_ENTER(EAP, IDLE); - break; - case EAP_IDENTITY: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_NOTIFICATION: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_RETRANSMIT: - SM_ENTER(EAP, SEND_RESPONSE); - break; - case EAP_SUCCESS: - break; - case EAP_FAILURE: - break; - } -} - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, EapType method) -{ - struct wpa_ssid *config = eap_get_config(sm); - int i; - - if (!wpa_config_allowed_eap_method(config, method)) - return FALSE; - for (i = 0; i < NUM_EAP_METHODS; i++) { - if (eap_methods[i]->method == method) - return TRUE; - } - return FALSE; -} - - -static u8 *eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *resp; - u8 *pos; - int i, found = 0; - - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Nak (requested type %d not " - "allowed)", sm->reqMethod); - *len = sizeof(struct eap_hdr) + 1; - resp = malloc(*len + NUM_EAP_METHODS); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_NAK; - - for (i = 0; i < NUM_EAP_METHODS; i++) { - if (wpa_config_allowed_eap_method(config, - eap_methods[i]->method)) { - *pos++ = eap_methods[i]->method; - (*len)++; - found++; - } - } - if (!found) { - *pos = EAP_TYPE_NONE; - (*len)++; - } - wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", - ((u8 *) (resp + 1)) + 1, found); - - resp->length = host_to_be16(*len); - - return (u8 *) resp; -} - - -static void eap_sm_processIdentity(struct eap_sm *sm, u8 *req, size_t len) -{ - struct eap_hdr *hdr = (struct eap_hdr *) req; - u8 *pos = (u8 *) (hdr + 1); - pos++; - /* TODO: could save displayable message so that it can be shown to the - * user in case of interaction is required */ - wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Identity data", - pos, be_to_host16(hdr->length) - 5); -} - - -u8 *eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len, - int encrypted) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *resp; - u8 *pos; - const u8 *identity; - size_t identity_len; - - if (config == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: configuration " - "was not available"); - return NULL; - } - - if (sm->m && sm->m->get_identity && - (identity = sm->m->get_identity(sm, sm->eap_method_priv, - &identity_len)) != NULL) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using method re-auth " - "identity", identity, identity_len); - } else if (!encrypted && config->anonymous_identity) { - identity = config->anonymous_identity; - identity_len = config->anonymous_identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using anonymous identity", - identity, identity_len); - } else { - identity = config->identity; - identity_len = config->identity_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP: using real identity", - identity, identity_len); - } - - if (identity == NULL) { - wpa_printf(MSG_WARNING, "EAP: buildIdentity: identity " - "configuration was not available"); - eap_sm_request_identity(sm, config); - return NULL; - } - - - *len = sizeof(struct eap_hdr) + 1 + identity_len; - resp = malloc(*len); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - resp->length = host_to_be16(*len); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_IDENTITY; - memcpy(pos, identity, identity_len); - - return (u8 *) resp; -} - - -static void eap_sm_processNotify(struct eap_sm *sm, u8 *req, size_t len) -{ - struct eap_hdr *hdr = (struct eap_hdr *) req; - u8 *pos = (u8 *) (hdr + 1); - pos++; - /* TODO: log the Notification Request and make it available for UI */ - wpa_hexdump_ascii(MSG_DEBUG, "EAP: EAP-Request Notification data", - pos, be_to_host16(hdr->length) - 5); -} - - -static u8 *eap_sm_buildNotify(struct eap_sm *sm, int id, size_t *len) -{ - struct eap_hdr *resp; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); - *len = sizeof(struct eap_hdr) + 1; - resp = malloc(*len); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - resp->length = host_to_be16(*len); - pos = (u8 *) (resp + 1); - *pos = EAP_TYPE_NOTIFICATION; - - return (u8 *) resp; -} - - -static void eap_sm_parseEapReq(struct eap_sm *sm, u8 *req, size_t len) -{ - struct eap_hdr *hdr; - size_t plen; - MD5_CTX context; - - sm->rxReq = sm->rxSuccess = sm->rxFailure = FALSE; - sm->reqId = 0; - sm->reqMethod = EAP_TYPE_NONE; - - if (req == NULL || len < sizeof(*hdr)) - return; - - hdr = (struct eap_hdr *) req; - plen = be_to_host16(hdr->length); - if (plen > len) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", - (unsigned long) len, (unsigned long) plen); - return; - } - - sm->reqId = hdr->identifier; - - if (sm->workaround) { - MD5Init(&context); - MD5Update(&context, req, len); - MD5Final(sm->req_md5, &context); - } - - switch (hdr->code) { - case EAP_CODE_REQUEST: - sm->rxReq = TRUE; - if (plen > sizeof(*hdr)) - sm->reqMethod = *((u8 *) (hdr + 1)); - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Request method=%d " - "id=%d", sm->reqMethod, sm->reqId); - break; - case EAP_CODE_RESPONSE: - if (sm->selectedMethod == EAP_TYPE_LEAP) { - sm->rxResp = TRUE; - if (plen > sizeof(*hdr)) - sm->reqMethod = *((u8 *) (hdr + 1)); - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " - "LEAP method=%d id=%d", - sm->reqMethod, sm->reqId); - break; - } - wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Response"); - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); - sm->rxSuccess = TRUE; - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); - sm->rxFailure = TRUE; - break; - default: - wpa_printf(MSG_DEBUG, "EAP: Ignored EAP-Packet with unknown " - "code %d", hdr->code); - break; - } -} - - -struct eap_sm *eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, - void *msg_ctx) -{ - struct eap_sm *sm; - - sm = malloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - memset(sm, 0, sizeof(*sm)); - sm->eapol_ctx = eapol_ctx; - sm->eapol_cb = eapol_cb; - sm->msg_ctx = msg_ctx; - sm->ClientTimeout = 60; - - sm->ssl_ctx = tls_init(); - if (sm->ssl_ctx == NULL) { - wpa_printf(MSG_WARNING, "SSL: Failed to initialize TLS " - "context."); - free(sm); - return NULL; - } - - return sm; -} - - -void eap_sm_deinit(struct eap_sm *sm) -{ - if (sm == NULL) - return; - eap_deinit_prev_method(sm, "EAP deinit"); - free(sm->lastRespData); - free(sm->eapRespData); - free(sm->eapKeyData); - tls_deinit(sm->ssl_ctx); - free(sm); -} - - -int eap_sm_step(struct eap_sm *sm) -{ - int res = 0; - do { - sm->changed = FALSE; - SM_STEP_RUN(EAP); - if (sm->changed) - res = 1; - } while (sm->changed); - return res; -} - - -void eap_sm_abort(struct eap_sm *sm) -{ - /* release system resources that may have been allocated for the - * authentication session */ - free(sm->eapRespData); - sm->eapRespData = NULL; - free(sm->eapKeyData); - sm->eapKeyData = NULL; -} - - -static const char * eap_sm_state_txt(int state) -{ - switch (state) { - case EAP_INITIALIZE: - return "INITIALIZE"; - case EAP_DISABLED: - return "DISABLED"; - case EAP_IDLE: - return "IDLE"; - case EAP_RECEIVED: - return "RECEIVED"; - case EAP_GET_METHOD: - return "GET_METHOD"; - case EAP_METHOD: - return "METHOD"; - case EAP_SEND_RESPONSE: - return "SEND_RESPONSE"; - case EAP_DISCARD: - return "DISCARD"; - case EAP_IDENTITY: - return "IDENTITY"; - case EAP_NOTIFICATION: - return "NOTIFICATION"; - case EAP_RETRANSMIT: - return "RETRANSMIT"; - case EAP_SUCCESS: - return "SUCCESS"; - case EAP_FAILURE: - return "FAILURE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eap_sm_method_state_txt(int state) -{ - switch (state) { - case METHOD_NONE: - return "NONE"; - case METHOD_INIT: - return "INIT"; - case METHOD_CONT: - return "CONT"; - case METHOD_MAY_CONT: - return "MAY_CONT"; - case METHOD_DONE: - return "DONE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eap_sm_decision_txt(int decision) -{ - switch (decision) { - case DECISION_FAIL: - return "FAIL"; - case DECISION_COND_SUCC: - return "COND_SUCC"; - case DECISION_UNCOND_SUCC: - return "UNCOND_SUCC"; - default: - return "UNKNOWN"; - } -} - - -int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, int verbose) -{ - int len; - - if (sm == NULL) - return 0; - - len = snprintf(buf, buflen, - "EAP state=%s\n", - eap_sm_state_txt(sm->EAP_state)); - - if (sm->selectedMethod != EAP_TYPE_NONE) { - const char *name; - if (sm->m) { - name = sm->m->name; - } else { - const struct eap_method *m = - eap_sm_get_eap_methods(sm->selectedMethod); - if (m) - name = m->name; - else - name = "?"; - } - len += snprintf(buf + len, buflen - len, - "selectedMethod=%d (EAP-%s)\n", - sm->selectedMethod, name); - - if (sm->m && sm->m->get_status) { - len += sm->m->get_status(sm, sm->eap_method_priv, - buf + len, buflen - len, - verbose); - } - } - - if (verbose) { - len += snprintf(buf + len, buflen - len, - "reqMethod=%d\n" - "methodState=%s\n" - "decision=%s\n" - "ClientTimeout=%d\n", - sm->reqMethod, - eap_sm_method_state_txt(sm->methodState), - eap_sm_decision_txt(sm->decision), - sm->ClientTimeout); - } - - return len; -} - - -typedef enum { TYPE_IDENTITY, TYPE_PASSWORD, TYPE_OTP } eap_ctrl_req_type; - -static void eap_sm_request(struct eap_sm *sm, struct wpa_ssid *config, - eap_ctrl_req_type type, char *msg, size_t msglen) -{ - char *buf; - size_t buflen; - int len; - char *field; - char *txt, *tmp; - - if (config == NULL || sm == NULL) - return; - - switch (type) { - case TYPE_IDENTITY: - field = "IDENTITY"; - txt = "Identity"; - config->pending_req_identity++; - break; - case TYPE_PASSWORD: - field = "PASSWORD"; - txt = "Password"; - config->pending_req_password++; - break; - case TYPE_OTP: - field = "OTP"; - if (msg) { - tmp = malloc(msglen + 3); - if (tmp == NULL) - return; - tmp[0] = '['; - memcpy(tmp + 1, msg, msglen); - tmp[msglen + 1] = ']'; - tmp[msglen + 2] = '\0'; - txt = tmp; - free(config->pending_req_otp); - config->pending_req_otp = tmp; - config->pending_req_otp_len = msglen + 3; - } else { - if (config->pending_req_otp == NULL) - return; - txt = config->pending_req_otp; - } - break; - default: - return; - } - - buflen = 100 + strlen(txt) + config->ssid_len; - buf = malloc(buflen); - if (buf == NULL) - return; - len = snprintf(buf, buflen, "CTRL-REQ-%s-%d:%s needed for SSID ", - field, config->id, txt); - if (config->ssid && buflen > len + config->ssid_len) { - memcpy(buf + len, config->ssid, config->ssid_len); - len += config->ssid_len; - buf[len] = '\0'; - } - wpa_msg(sm->msg_ctx, MSG_INFO, buf); - free(buf); -} - - -void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config) -{ - eap_sm_request(sm, config, TYPE_IDENTITY, NULL, 0); -} - - -void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config) -{ - eap_sm_request(sm, config, TYPE_PASSWORD, NULL, 0); -} - - -void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config, - char *msg, size_t msg_len) -{ - eap_sm_request(sm, config, TYPE_OTP, msg, msg_len); -} - - -void eap_sm_notify_ctrl_attached(struct eap_sm *sm) -{ - struct wpa_ssid *config = eap_get_config(sm); - - if (config == NULL) - return; - - /* Re-send any pending requests for user data since a new control - * interface was added. This handles cases where the EAP authentication - * starts immediately after system startup when the user interface is - * not yet running. */ - if (config->pending_req_identity) - eap_sm_request_identity(sm, config); - if (config->pending_req_password) - eap_sm_request_password(sm, config); - if (config->pending_req_otp) - eap_sm_request_otp(sm, config, NULL, 0); -} - - -u8 eap_get_type(const char *name) -{ - int i; - for (i = 0; i < NUM_EAP_METHODS; i++) { - if (strcmp(eap_methods[i]->name, name) == 0) - return eap_methods[i]->method; - } - return EAP_TYPE_NONE; -} - - -static int eap_allowed_phase2_type(int type) -{ - return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS && - type != EAP_TYPE_FAST; -} - - -u8 eap_get_phase2_type(const char *name) -{ - u8 type = eap_get_type(name); - if (eap_allowed_phase2_type(type)) - return type; - return EAP_TYPE_NONE; -} - - -u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count) -{ - u8 *buf, method; - int i; - - *count = 0; - buf = malloc(NUM_EAP_METHODS); - if (buf == NULL) - return NULL; - - for (i = 0; i < NUM_EAP_METHODS; i++) { - method = eap_methods[i]->method; - if (eap_allowed_phase2_type(method)) { - if (method == EAP_TYPE_TLS && config && - config->private_key2 == NULL) - continue; - buf[*count] = method; - (*count)++; - } - } - - return buf; -} - - -void eap_set_fast_reauth(struct eap_sm *sm, int enabled) -{ - sm->fast_reauth = enabled; -} - - -void eap_set_workaround(struct eap_sm *sm, unsigned int workaround) -{ - sm->workaround = workaround; -} - - -struct wpa_ssid * eap_get_config(struct eap_sm *sm) -{ - return sm->eapol_cb->get_config(sm->eapol_ctx); -} - - -int eap_key_available(struct eap_sm *sm) -{ - return sm ? sm->eapKeyAvailable : 0; -} - - -void eap_notify_success(struct eap_sm *sm) -{ - if (sm) { - sm->decision = DECISION_COND_SUCC; - sm->EAP_state = EAP_SUCCESS; - } -} - - -u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len) -{ - if (sm == NULL || sm->eapKeyData == NULL) { - *len = 0; - return NULL; - } - - *len = sm->eapKeyDataLen; - return sm->eapKeyData; -} - - -u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len) -{ - u8 *resp; - - if (sm == NULL || sm->eapRespData == NULL) { - *len = 0; - return NULL; - } - - resp = sm->eapRespData; - *len = sm->eapRespDataLen; - sm->eapRespData = NULL; - sm->eapRespDataLen = 0; - - return resp; -} - - -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx) -{ - if (sm) - sm->scard_ctx = ctx; -} diff --git a/contrib/wpa_supplicant/eap.h b/contrib/wpa_supplicant/eap.h deleted file mode 100644 index 3d7cc7210d7a..000000000000 --- a/contrib/wpa_supplicant/eap.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef EAP_H -#define EAP_H - -#include "defs.h" -#include "eap_defs.h" - -struct eap_sm; -struct wpa_ssid; - - -#ifdef IEEE8021X_EAPOL - -enum eapol_bool_var { - EAPOL_eapSuccess, EAPOL_eapRestart, EAPOL_eapFail, EAPOL_eapResp, - EAPOL_eapNoResp, EAPOL_eapReq, EAPOL_portEnabled, EAPOL_altAccept, - EAPOL_altReject -}; - -enum eapol_int_var { - EAPOL_idleWhile -}; - -struct eapol_callbacks { - struct wpa_ssid * (*get_config)(void *ctx); - Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable); - void (*set_bool)(void *ctx, enum eapol_bool_var variable, - Boolean value); - unsigned int (*get_int)(void *ctx, enum eapol_int_var variable); - void (*set_int)(void *ctx, enum eapol_int_var variable, - unsigned int value); - u8 * (*get_eapReqData)(void *ctx, size_t *len); -}; - -struct eap_sm *eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, - void *msg_ctx); -void eap_sm_deinit(struct eap_sm *sm); -int eap_sm_step(struct eap_sm *sm); -void eap_sm_abort(struct eap_sm *sm); -int eap_sm_get_status(struct eap_sm *sm, char *buf, size_t buflen, - int verbose); -u8 *eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len, - int encrypted); -const struct eap_method * eap_sm_get_eap_methods(int method); -void eap_sm_request_identity(struct eap_sm *sm, struct wpa_ssid *config); -void eap_sm_request_password(struct eap_sm *sm, struct wpa_ssid *config); -void eap_sm_request_otp(struct eap_sm *sm, struct wpa_ssid *config, - char *msg, size_t msg_len); -void eap_sm_notify_ctrl_attached(struct eap_sm *sm); -u8 eap_get_type(const char *name); -u8 eap_get_phase2_type(const char *name); -u8 *eap_get_phase2_types(struct wpa_ssid *config, size_t *count); -void eap_set_fast_reauth(struct eap_sm *sm, int enabled); -void eap_set_workaround(struct eap_sm *sm, unsigned int workaround); -struct wpa_ssid * eap_get_config(struct eap_sm *sm); -int eap_key_available(struct eap_sm *sm); -void eap_notify_success(struct eap_sm *sm); -u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len); -u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len); -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx); - -#else /* IEEE8021X_EAPOL */ - -static inline u8 eap_get_type(const char *name) -{ - return EAP_TYPE_NONE; -} - -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAP_H */ diff --git a/contrib/wpa_supplicant/eap_aka.c b/contrib/wpa_supplicant/eap_aka.c deleted file mode 100644 index 7fe6449ab896..000000000000 --- a/contrib/wpa_supplicant/eap_aka.c +++ /dev/null @@ -1,915 +0,0 @@ -/* - * WPA Supplicant / EAP-AKA (draft-arkko-pppext-eap-aka-12.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "sha1.h" -#include "pcsc_funcs.h" -#include "eap_sim_common.h" - -/* EAP-AKA Subtypes */ -#define EAP_AKA_SUBTYPE_CHALLENGE 1 -#define EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT 2 -#define EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE 4 -#define EAP_AKA_SUBTYPE_IDENTITY 5 -#define EAP_AKA_SUBTYPE_NOTIFICATION 12 -#define EAP_AKA_SUBTYPE_REAUTHENTICATION 13 -#define EAP_AKA_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_AKA_UNABLE_TO_PROCESS_PACKET 0 - -#define AKA_AUTS_LEN 14 -#define RES_MAX_LEN 16 -#define IK_LEN 16 -#define CK_LEN 16 -#define EAP_AKA_MAX_FAST_REAUTHS 1000 - -struct eap_aka_data { - u8 ik[IK_LEN], ck[CK_LEN], res[RES_MAX_LEN]; - size_t res_len; - u8 nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_aut[EAP_SIM_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 rand[AKA_RAND_LEN], autn[AKA_AUTN_LEN]; - u8 auts[AKA_AUTS_LEN]; - - int num_id_req, num_notification; - u8 *pseudonym; - size_t pseudonym_len; - u8 *reauth_id; - size_t reauth_id_len; - int reauth; - unsigned int counter, counter_too_small; - u8 *last_eap_identity; - size_t last_eap_identity_len; - enum { CONTINUE, SUCCESS, FAILURE } state; -}; - - -static void * eap_aka_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - - data->state = CONTINUE; - - return data; -} - - -static void eap_aka_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - if (data) { - free(data->pseudonym); - free(data->reauth_id); - free(data->last_eap_identity); - free(data); - } -} - - -static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); -#ifdef PCSC_FUNCS - return scard_umts_auth(sm->scard_ctx, data->rand, - data->autn, data->res, &data->res_len, - data->ik, data->ck, data->auts); -#else /* PCSC_FUNCS */ - /* These hardcoded Kc and SRES values are used for testing. - * Could consider making them configurable. */ - memset(data->res, '2', RES_MAX_LEN); - data->res_len = 16; - memset(data->ik, '3', IK_LEN); - memset(data->ck, '4', CK_LEN); - { - u8 autn[AKA_AUTN_LEN]; - memset(autn, '1', AKA_AUTN_LEN); - if (memcmp(autn, data->autn, AKA_AUTN_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " - "with expected value"); - return -1; - } - } - return 0; -#endif /* PCSC_FUNCS */ -} - - -static void eap_aka_derive_mk(struct eap_aka_data *data, - const u8 *identity, size_t identity_len) -{ - const u8 *addr[3]; - size_t len[3]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = data->ik; - len[1] = IK_LEN; - addr[2] = data->ck; - len[2] = CK_LEN; - - /* MK = SHA1(Identity|IK|CK) */ - sha1_vector(3, addr, len, data->mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", data->ik, IK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", data->ck, CK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", data->mk, EAP_SIM_MK_LEN); -} - - -#define CLEAR_PSEUDONYM 0x01 -#define CLEAR_REAUTH_ID 0x02 -#define CLEAR_EAP_ID 0x04 - -static void eap_aka_clear_identities(struct eap_aka_data *data, int id) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: forgetting old%s%s%s", - id & CLEAR_PSEUDONYM ? " pseudonym" : "", - id & CLEAR_REAUTH_ID ? " reauth_id" : "", - id & CLEAR_EAP_ID ? " eap_id" : ""); - if (id & CLEAR_PSEUDONYM) { - free(data->pseudonym); - data->pseudonym = NULL; - data->pseudonym_len = 0; - } - if (id & CLEAR_REAUTH_ID) { - free(data->reauth_id); - data->reauth_id = NULL; - data->reauth_id_len = 0; - } - if (id & CLEAR_EAP_ID) { - free(data->last_eap_identity); - data->last_eap_identity = NULL; - data->last_eap_identity_len = 0; - } -} - - -static int eap_aka_learn_ids(struct eap_aka_data *data, - struct eap_sim_attrs *attr) -{ - if (attr->next_pseudonym) { - free(data->pseudonym); - data->pseudonym = malloc(attr->next_pseudonym_len); - if (data->pseudonym == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " - "next pseudonym"); - return -1; - } - memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); - } - - if (attr->next_reauth_id) { - free(data->reauth_id); - data->reauth_id = malloc(attr->next_reauth_id_len); - if (data->reauth_id == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " - "next reauth_id"); - return -1; - } - memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); - data->reauth_id_len = attr->next_reauth_id_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", - data->reauth_id, - data->reauth_id_len); - } - - return 0; -} - - -static u8 * eap_aka_client_error(struct eap_sm *sm, struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen, int err) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CLIENT_ERROR); - eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_authentication_reject(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " - "(id=%d)", req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, - EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_synchronization_failure(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Synchronization-Failure " - "(id=%d)", req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, - EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE); - wpa_printf(MSG_DEBUG, " AT_AUTS"); - eap_sim_msg_add_full(msg, EAP_SIM_AT_AUTS, data->auts, AKA_AUTS_LEN); - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_response_identity(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen, - enum eap_sim_id_req id_req) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *identity = NULL; - size_t identity_len = 0; - struct eap_sim_msg *msg; - - data->reauth = 0; - if (id_req == ANY_ID && data->reauth_id) { - identity = data->reauth_id; - identity_len = data->reauth_id_len; - data->reauth = 1; - } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - eap_aka_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ && config && config->identity) { - identity = config->identity; - identity_len = config->identity_len; - eap_aka_clear_identities(data, - CLEAR_PSEUDONYM | CLEAR_REAUTH_ID); - } - if (id_req != NO_ID_REQ) - eap_aka_clear_identities(data, CLEAR_EAP_ID); - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Identity (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, EAP_AKA_SUBTYPE_IDENTITY); - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_response_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_RES"); - eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len, - data->res, data->res_len); - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, (u8 *) "", 0); -} - - -static u8 * eap_aka_response_reauth(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen, int counter_too_small) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Reauthentication (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, - EAP_AKA_SUBTYPE_REAUTHENTICATION); - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter_too_small) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); - counter = data->counter_too_small; - } else - counter = data->counter; - - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, data->nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static u8 * eap_aka_response_notification(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t *respDataLen, - u16 notification) -{ - struct eap_sim_msg *msg; - u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Notification (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, EAP_AKA_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION"); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0); - if (k_aut && data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - if (k_aut) { - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, respDataLen, k_aut, (u8 *) "", 0); -} - - -static u8 * eap_aka_process_identity(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - int id_error; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Identity"); - - id_error = 0; - switch (attr->id_req) { - case NO_ID_REQ: - break; - case ANY_ID: - if (data->num_id_req > 0) - id_error++; - data->num_id_req++; - break; - case FULLAUTH_ID: - if (data->num_id_req > 1) - id_error++; - data->num_id_req++; - break; - case PERMANENT_ID: - if (data->num_id_req > 2) - id_error++; - data->num_id_req++; - break; - } - if (id_error) { - wpa_printf(MSG_INFO, "EAP-AKA: Too many ID requests " - "used within one authentication"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - return eap_aka_response_identity(sm, data, req, respDataLen, - attr->id_req); -} - - -static u8 * eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *identity; - size_t identity_len; - int res; - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); - data->reauth = 0; - if (!attr->mac || !attr->rand || !attr->autn) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "did not include%s%s%s", - !attr->mac ? " AT_MAC" : "", - !attr->rand ? " AT_RAND" : "", - !attr->autn ? " AT_AUTN" : ""); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - memcpy(data->rand, attr->rand, AKA_RAND_LEN); - memcpy(data->autn, attr->autn, AKA_AUTN_LEN); - - res = eap_aka_umts_auth(sm, data); - if (res == -1) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN)"); - return eap_aka_authentication_reject(sm, data, req, - respDataLen); - } else if (res == -2) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN seq# -> AUTS)"); - return eap_aka_synchronization_failure(sm, data, req, - respDataLen); - } else if (res) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - if (data->last_eap_identity) { - identity = data->last_eap_identity; - identity_len = data->last_eap_identity_len; - } else if (data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - } else { - identity = config->identity; - identity_len = config->identity_len; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " - "derivation", identity, identity_len); - eap_aka_derive_mk(data, identity, identity_len); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk); - if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac, - (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "used invalid AT_MAC"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - /* Old reauthentication and pseudonym identities must not be used - * anymore. In other words, if no new identities are received, full - * authentication will be used on next reauthentication. */ - eap_aka_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | - CLEAR_EAP_ID); - - if (attr->encr_data) { - if (eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0)) { - return eap_aka_client_error( - sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - eap_aka_learn_ids(data, &eattr); - } - - if (data->state != FAILURE) - data->state = SUCCESS; - - data->num_id_req = 0; - data->num_notification = 0; - /* draft-arkko-pppext-eap-aka-12.txt specifies that counter - * is initialized to one after fullauth, but initializing it to - * zero makes it easier to implement reauth verification. */ - data->counter = 0; - return eap_aka_response_challenge(sm, data, req, respDataLen); -} - - -static int eap_aka_process_notification_reauth(struct eap_aka_data *data, - struct eap_hdr *req, - size_t reqDataLen, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Notification message after " - "reauth did not include encrypted data"); - return -1; - } - - if (eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from notification message"); - return -1; - } - - if (eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-AKA: Counter in notification " - "message does not match with counter in reauth " - "message"); - return -1; - } - - return 0; -} - - -static int eap_aka_process_notification_auth(struct eap_aka_data *data, - struct eap_hdr *req, - size_t reqDataLen, - struct eap_sim_attrs *attr) -{ - if (attr->mac == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: no AT_MAC in after_auth " - "Notification message"); - return -1; - } - - if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac, - (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Notification message " - "used invalid AT_MAC"); - return -1; - } - - if (data->reauth && - eap_aka_process_notification_reauth(data, req, reqDataLen, attr)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Invalid notification " - "message after reauth"); - return -1; - } - - return 0; -} - - -static u8 * eap_aka_process_notification(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Notification"); - if (data->num_notification > 0) { - wpa_printf(MSG_INFO, "EAP-AKA: too many notification " - "rounds (only one allowed)"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - data->num_notification++; - if (attr->notification == -1) { - wpa_printf(MSG_INFO, "EAP-AKA: no AT_NOTIFICATION in " - "Notification message"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_aka_process_notification_auth(data, req, reqDataLen, attr)) { - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); - if (attr->notification >= 0 && attr->notification < 32768) { - data->state = FAILURE; - } - return eap_aka_response_notification(sm, data, req, respDataLen, - attr->notification); -} - - -static u8 * eap_aka_process_reauthentication(struct eap_sm *sm, - struct eap_aka_data *data, - struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); - - if (data->reauth_id == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Server is trying " - "reauthentication, but no reauth_id available"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, - attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "did not have valid AT_MAC"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "message did not include encrypted data"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Failed to parse encrypted " - "data from reauthentication message"); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.nonce_s == NULL || eattr.counter < 0) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) No%s%s in reauth packet", - !eattr.nonce_s ? " AT_NONCE_S" : "", - eattr.counter < 0 ? " AT_COUNTER" : ""); - return eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter <= data->counter) { - wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current - * reauth_id must not be used to start a new reauthentication. - * However, since it was used in the last EAP-Response-Identity - * packet, it has to saved for the following fullauth to be - * used in MK derivation. */ - free(data->last_eap_identity); - data->last_eap_identity = data->reauth_id; - data->last_eap_identity_len = data->reauth_id_len; - data->reauth_id = NULL; - data->reauth_id_len = 0; - return eap_aka_response_reauth(sm, data, req, respDataLen, 1); - } - data->counter = eattr.counter; - - memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-AKA: (encr) AT_NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - eap_sim_derive_keys_reauth(data->counter, - data->reauth_id, data->reauth_id_len, - data->nonce_s, data->mk, data->msk); - eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_aka_learn_ids(data, &eattr); - - if (data->state != FAILURE) - data->state = SUCCESS; - - data->num_id_req = 0; - data->num_notification = 0; - if (data->counter > EAP_AKA_MAX_FAST_REAUTHS) { - wpa_printf(MSG_DEBUG, "EAP-AKA: Maximum number of " - "fast reauths performed - force fullauth"); - eap_aka_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - } - return eap_aka_response_reauth(sm, data, req, respDataLen, 0); -} - - -static u8 * eap_aka_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_aka_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req; - u8 *pos, subtype, *res; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump(MSG_DEBUG, "EAP-AKA: EAP data", reqData, reqDataLen); - if (config == NULL || config->identity == NULL) { - wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); - eap_sm_request_identity(sm, config); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_AKA || - (len = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - pos++; - subtype = *pos++; - wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); - pos += 2; /* Reserved */ - - if (eap_sim_parse_attr(pos, reqData + len, &attr, 1, 0)) { - res = eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_AKA_SUBTYPE_IDENTITY: - res = eap_aka_process_identity(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_CHALLENGE: - res = eap_aka_process_challenge(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_NOTIFICATION: - res = eap_aka_process_notification(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_REAUTHENTICATION: - res = eap_aka_process_reauthentication(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); - res = eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); - res = eap_aka_client_error(sm, data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - } - -done: - if (data->state == FAILURE) { - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_DONE; - } else if (data->state == SUCCESS) { - ret->decision = DECISION_UNCOND_SUCC; - ret->methodState = METHOD_DONE; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return res; -} - - -static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->pseudonym || data->reauth_id; -} - - -static void eap_aka_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - eap_aka_clear_identities(data, CLEAR_EAP_ID); -} - - -static void * eap_aka_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - data->num_id_req = 0; - data->num_notification = 0; - data->state = CONTINUE; - return priv; -} - - -static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, - size_t *len) -{ - struct eap_aka_data *data = priv; - - if (data->reauth_id) { - *len = data->reauth_id_len; - return data->reauth_id; - } - - if (data->pseudonym) { - *len = data->pseudonym_len; - return data->pseudonym; - } - - return NULL; -} - - -static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_aka_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_aka_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - - *len = EAP_SIM_KEYING_DATA_LEN; - memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - - return key; -} - - -const struct eap_method eap_method_aka = -{ - .method = EAP_TYPE_AKA, - .name = "AKA", - .init = eap_aka_init, - .deinit = eap_aka_deinit, - .process = eap_aka_process, - .isKeyAvailable = eap_aka_isKeyAvailable, - .getKey = eap_aka_getKey, - .has_reauth_data = eap_aka_has_reauth_data, - .deinit_for_reauth = eap_aka_deinit_for_reauth, - .init_for_reauth = eap_aka_init_for_reauth, - .get_identity = eap_aka_get_identity, -}; diff --git a/contrib/wpa_supplicant/eap_defs.h b/contrib/wpa_supplicant/eap_defs.h deleted file mode 100644 index effe665f0919..000000000000 --- a/contrib/wpa_supplicant/eap_defs.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef EAP_DEFS_H -#define EAP_DEFS_H - -/* RFC 3748 - Extensible Authentication Protocol (EAP) */ - -struct eap_hdr { - u8 code; - u8 identifier; - u16 length; /* including code and identifier */ - /* followed by length-4 octets of data */ -} __attribute__ ((packed)); - -enum { EAP_CODE_REQUEST = 1, EAP_CODE_RESPONSE = 2, EAP_CODE_SUCCESS = 3, - EAP_CODE_FAILURE = 4 }; - -/* EAP Request and Response data begins with one octet Type. Success and - * Failure do not have additional data. */ - -typedef enum { - EAP_TYPE_NONE = 0, - EAP_TYPE_IDENTITY = 1, - EAP_TYPE_NOTIFICATION = 2, - EAP_TYPE_NAK = 3 /* Response only */, - EAP_TYPE_MD5 = 4, - EAP_TYPE_OTP = 5 /* RFC 2284 */, - EAP_TYPE_GTC = 6, /* RFC 2284 */ - EAP_TYPE_TLS = 13 /* RFC 2716 */, - EAP_TYPE_LEAP = 17 /* Cisco proprietary */, - EAP_TYPE_SIM = 18 /* draft-haverinen-pppext-eap-sim-12.txt */, - EAP_TYPE_TTLS = 21 /* draft-ietf-pppext-eap-ttls-02.txt */, - EAP_TYPE_AKA = 23 /* draft-arkko-pppext-eap-aka-12.txt */, - EAP_TYPE_PEAP = 25 /* draft-josefsson-pppext-eap-tls-eap-06.txt */, - EAP_TYPE_MSCHAPV2 = 26 /* draft-kamath-pppext-eap-mschapv2-00.txt */, - EAP_TYPE_TLV = 33 /* draft-josefsson-pppext-eap-tls-eap-07.txt */, - EAP_TYPE_FAST = 43 /* draft-cam-winget-eap-fast-00.txt */, - EAP_TYPE_EXPANDED_NAK = 254 /* RFC 3748 */, - EAP_TYPE_PSK = 255 /* EXPERIMENTAL - type not yet allocated - * draft-bersani-eap-psk-03 */ -} EapType; - -#endif /* EAP_DEFS_H */ diff --git a/contrib/wpa_supplicant/eap_fast.c b/contrib/wpa_supplicant/eap_fast.c deleted file mode 100644 index 1c9c3ff2370f..000000000000 --- a/contrib/wpa_supplicant/eap_fast.c +++ /dev/null @@ -1,1906 +0,0 @@ -/* - * WPA Supplicant / EAP-FAST (draft-cam-winget-eap-fast-00.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "tls.h" -#include "eap_tlv.h" -#include "sha1.h" - -/* TODO: - * - encrypt PAC-Key in the PAC file - * - test session resumption and enable it if it interoperates - */ - -#define EAP_FAST_VERSION 1 -#define EAP_FAST_KEY_LEN 64 -#define EAP_FAST_PAC_KEY_LEN 32 - -#define TLS_EXT_PAC_OPAQUE 35 - -static char *pac_file_hdr = "wpa_supplicant EAP-FAST PAC file - version 1"; - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv); - - -#define PAC_TYPE_PAC_KEY 1 -#define PAC_TYPE_PAC_OPAQUE 2 -#define PAC_TYPE_CRED_LIFETIME 3 -#define PAC_TYPE_A_ID 4 -#define PAC_TYPE_I_ID 5 -#define PAC_TYPE_SERVER_PROTECTED_DATA 6 -#define PAC_TYPE_A_ID_INFO 7 -#define PAC_TYPE_PAC_ACKNOWLEDGEMENT 8 -#define PAC_TYPE_PAC_INFO 9 - -struct pac_tlv_hdr { - u16 type; - u16 len; -}; - - -/* draft-cam-winget-eap-fast-00.txt, 6.2 EAP-FAST Authentication Phase 1 */ -struct eap_fast_key_block_auth { - /* RC4-128-SHA */ - u8 client_write_MAC_secret[20]; - u8 server_write_MAC_secret[20]; - u8 client_write_key[16]; - u8 server_write_key[16]; - /* u8 client_write_IV[0]; */ - /* u8 server_write_IV[0]; */ - u8 session_key_seed[40]; -}; - - -/* draft-cam-winget-eap-fast-00.txt, 7.3 EAP-FAST Provisioning Exchange */ -struct eap_fast_key_block_provisioning { - /* AES128-SHA */ - u8 client_write_MAC_secret[20]; - u8 server_write_MAC_secret[20]; - u8 client_write_key[16]; - u8 server_write_key[16]; - u8 client_write_IV[16]; - u8 server_write_IV[16]; - u8 session_key_seed[40]; - u8 server_challenge[16]; - u8 client_challenge[16]; -}; - - -struct eap_fast_pac { - struct eap_fast_pac *next; - - u8 pac_key[EAP_FAST_PAC_KEY_LEN]; - u8 *pac_opaque; - size_t pac_opaque_len; - u8 *pac_info; - size_t pac_info_len; - u8 *a_id; - size_t a_id_len; - u8 *i_id; - size_t i_id_len; - u8 *a_id_info; - size_t a_id_info_len; -}; - - -struct eap_fast_data { - struct eap_ssl_data ssl; - - int fast_version; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - - u8 phase2_type; - u8 *phase2_types; - size_t num_phase2_types; - int resuming; /* starting a resumed session */ - struct eap_fast_key_block_auth *key_block_a; - struct eap_fast_key_block_provisioning *key_block_p; - int provisioning_allowed; /* is PAC provisioning allowed */ - int provisioning; /* doing PAC provisioning (not the normal auth) */ - - u8 key_data[EAP_FAST_KEY_LEN]; - int success; - - struct eap_fast_pac *pac; - struct eap_fast_pac *current_pac; - - int tls_master_secret_set; -}; - - -static void eap_fast_free_pac(struct eap_fast_pac *pac) -{ - free(pac->pac_opaque); - free(pac->pac_info); - free(pac->a_id); - free(pac->i_id); - free(pac->a_id_info); - free(pac); -} - - -static struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_data *data, - const u8 *a_id, size_t a_id_len) -{ - struct eap_fast_pac *pac = data->pac; - - while (pac) { - if (pac->a_id_len == a_id_len && - memcmp(pac->a_id, a_id, a_id_len) == 0) { - return pac; - } - pac = pac->next; - } - return NULL; -} - - -static int eap_fast_add_pac(struct eap_fast_data *data, - struct eap_fast_pac *entry) -{ - struct eap_fast_pac *pac, *prev; - - if (entry == NULL || entry->a_id == NULL) - return -1; - - /* Remove a possible old entry for the matching A-ID. */ - pac = data->pac; - prev = NULL; - while (pac) { - if (pac->a_id_len == entry->a_id_len && - memcmp(pac->a_id, entry->a_id, pac->a_id_len) == 0) { - if (prev == NULL) { - data->pac = pac->next; - } else { - prev->next = pac->next; - } - if (data->current_pac == pac) - data->current_pac = NULL; - eap_fast_free_pac(pac); - break; - } - prev = pac; - pac = pac->next; - } - - /* Allocate a new entry and add it to the list of PACs. */ - pac = malloc(sizeof(*pac)); - if (pac == NULL) - return -1; - - memset(pac, 0, sizeof(*pac)); - memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN); - if (entry->pac_opaque) { - pac->pac_opaque = malloc(entry->pac_opaque_len); - if (pac->pac_opaque == NULL) { - eap_fast_free_pac(pac); - return -1; - } - memcpy(pac->pac_opaque, entry->pac_opaque, - entry->pac_opaque_len); - pac->pac_opaque_len = entry->pac_opaque_len; - } - if (entry->pac_info) { - pac->pac_info = malloc(entry->pac_info_len); - if (pac->pac_info == NULL) { - eap_fast_free_pac(pac); - return -1; - } - memcpy(pac->pac_info, entry->pac_info, - entry->pac_info_len); - pac->pac_info_len = entry->pac_info_len; - } - if (entry->a_id) { - pac->a_id = malloc(entry->a_id_len); - if (pac->a_id == NULL) { - eap_fast_free_pac(pac); - return -1; - } - memcpy(pac->a_id, entry->a_id, - entry->a_id_len); - pac->a_id_len = entry->a_id_len; - } - if (entry->i_id) { - pac->i_id = malloc(entry->i_id_len); - if (pac->i_id == NULL) { - eap_fast_free_pac(pac); - return -1; - } - memcpy(pac->i_id, entry->i_id, - entry->i_id_len); - pac->i_id_len = entry->i_id_len; - } - if (entry->a_id_info) { - pac->a_id_info = malloc(entry->a_id_info_len); - if (pac->a_id_info == NULL) { - eap_fast_free_pac(pac); - return -1; - } - memcpy(pac->a_id_info, entry->a_id_info, - entry->a_id_info_len); - pac->a_id_info_len = entry->a_id_info_len; - } - pac->next = data->pac; - data->pac = pac; - return 0; -} - - -static int eap_fast_read_line(FILE *f, char *buf, size_t buf_len) -{ - char *pos; - - if (fgets(buf, buf_len, f) == NULL) { - return -1; - } - - buf[buf_len - 1] = '\0'; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n' || *pos == '\r') { - *pos = '\0'; - break; - } - pos++; - } - - return 0; -} - - -static u8 * eap_fast_parse_hex(const char *value, size_t *len) -{ - int hlen; - u8 *buf; - - if (value == NULL) - return NULL; - hlen = strlen(value); - if (hlen & 1) - return NULL; - *len = hlen / 2; - buf = malloc(*len); - if (buf == NULL) - return NULL; - if (hexstr2bin(value, buf, *len)) { - free(buf); - return NULL; - } - return buf; -} - - -static int eap_fast_load_pac(struct eap_fast_data *data, const char *pac_file) -{ - FILE *f; - struct eap_fast_pac *pac = NULL; - int count = 0; - char *buf, *pos; - const int buf_len = 2048; - int ret = 0, line = 0; - - if (pac_file == NULL) - return -1; - - f = fopen(pac_file, "r"); - if (f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - assume no " - "PAC entries have been provisioned", pac_file); - return 0; - } - - buf = malloc(buf_len); - if (buf == NULL) { - return -1; - } - - line++; - if (eap_fast_read_line(f, buf, buf_len) < 0 || - strcmp(pac_file_hdr, buf) != 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Unrecognized header line in " - "PAC file '%s'", pac_file); - free(buf); - fclose(f); - return -1; - } - - while (eap_fast_read_line(f, buf, buf_len) == 0) { - line++; - pos = strchr(buf, '='); - if (pos) { - *pos++ = '\0'; - } - - if (strcmp(buf, "START") == 0) { - if (pac) { - wpa_printf(MSG_INFO, "EAP-FAST: START line " - "without END in '%s:%d'", - pac_file, line); - ret = -1; - break; - } - pac = malloc(sizeof(*pac)); - if (pac == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No memory for " - "PAC entry"); - ret = -1; - break; - } - memset(pac, 0, sizeof(*pac)); - } else if (strcmp(buf, "END") == 0) { - if (pac == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: END line " - "without START in '%s:%d'", - pac_file, line); - ret = -1; - break; - } - pac->next = data->pac; - data->pac = pac; - pac = NULL; - count++; - } else if (pac && strcmp(buf, "PAC-Key") == 0) { - u8 *key; - size_t key_len; - key = eap_fast_parse_hex(pos, &key_len); - if (key == NULL || key_len != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "PAC-Key '%s:%d'", pac_file, line); - ret = -1; - free(key); - break; - } - - memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN); - free(key); - } else if (pac && strcmp(buf, "PAC-Opaque") == 0) { - pac->pac_opaque = - eap_fast_parse_hex(pos, &pac->pac_opaque_len); - if (pac->pac_opaque == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "PAC-Opaque '%s:%d'", - pac_file, line); - ret = -1; - break; - } - } else if (pac && strcmp(buf, "A-ID") == 0) { - pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len); - if (pac->a_id == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "A-ID '%s:%d'", pac_file, line); - ret = -1; - break; - } - } else if (pac && strcmp(buf, "I-ID") == 0) { - pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len); - if (pac->i_id == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "I-ID '%s:%d'", pac_file, line); - ret = -1; - break; - } - } else if (pac && strcmp(buf, "A-ID-Info") == 0) { - pac->a_id_info = - eap_fast_parse_hex(pos, &pac->a_id_info_len); - if (pac->a_id_info == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "A-ID-Info '%s:%d'", - pac_file, line); - ret = -1; - break; - } - } - } - - if (pac) { - wpa_printf(MSG_INFO, "EAP-FAST: PAC block not terminated with " - "END in '%s'", pac_file); - eap_fast_free_pac(pac); - ret = -1; - } - - free(buf); - fclose(f); - - if (ret == 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: read %d PAC entries from " - "'%s'", count, pac_file); - } - - return ret; -} - - -static void eap_fast_write(FILE *f, const char *field, const u8 *data, - size_t len, int txt) -{ - int i; - - if (data == NULL) - return; - - fprintf(f, "%s=", field); - for (i = 0; i < len; i++) { - fprintf(f, "%02x", data[i]); - } - fprintf(f, "\n"); - - if (txt) { - fprintf(f, "%s-txt=", field); - for (i = 0; i < len; i++) { - fprintf(f, "%c", data[i]); - } - fprintf(f, "\n"); - } -} - - -static int eap_fast_save_pac(struct eap_fast_data *data, const char *pac_file) -{ - FILE *f; - struct eap_fast_pac *pac; - int count = 0; - - if (pac_file == NULL) - return -1; - - f = fopen(pac_file, "w"); - if (f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC file '%s' " - "for writing", pac_file); - return -1; - } - - fprintf(f, "%s\n", pac_file_hdr); - - pac = data->pac; - while (pac) { - fprintf(f, "START\n"); - eap_fast_write(f, "PAC-Key", pac->pac_key, - EAP_FAST_PAC_KEY_LEN, 0); - eap_fast_write(f, "PAC-Opaque", pac->pac_opaque, - pac->pac_opaque_len, 0); - eap_fast_write(f, "PAC-Info", pac->pac_info, - pac->pac_info_len, 0); - eap_fast_write(f, "A-ID", pac->a_id, pac->a_id_len, 0); - eap_fast_write(f, "I-ID", pac->i_id, pac->i_id_len, 1); - eap_fast_write(f, "A-ID-Info", pac->a_id_info, - pac->a_id_info_len, 1); - fprintf(f, "END\n"); - count++; - pac = pac->next; - } - - fclose(f); - - wpa_printf(MSG_DEBUG, "EAP-FAST: wrote %d PAC entries into '%s'", - count, pac_file); - - return 0; -} - - -static void * eap_fast_init(struct eap_sm *sm) -{ - struct eap_fast_data *data; - struct wpa_ssid *config = eap_get_config(sm); - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - data->fast_version = EAP_FAST_VERSION; - - if (config && config->phase1) { - if (strstr(config->phase1, "fast_provisioning=1")) { - data->provisioning_allowed = 1; - wpa_printf(MSG_DEBUG, "EAP-FAST: Automatic PAC " - "provisioning is allowed"); - } - } - - if (config && config->phase2) { - char *start, *pos, *buf; - u8 method, *methods = NULL, *_methods; - size_t num_methods = 0; - start = buf = strdup(config->phase2); - if (buf == NULL) { - eap_fast_deinit(sm, data); - return NULL; - } - while (start && *start != '\0') { - pos = strstr(start, "auth="); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + 5; - continue; - } - - start = pos + 5; - pos = strchr(start, ' '); - if (pos) - *pos++ = '\0'; - method = eap_get_phase2_type(start); - if (method == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "EAP-FAST: Unsupported " - "Phase2 method '%s'", start); - } else { - num_methods++; - _methods = realloc(methods, num_methods); - if (_methods == NULL) { - free(methods); - eap_fast_deinit(sm, data); - return NULL; - } - methods = _methods; - methods[num_methods - 1] = method; - } - - start = pos; - } - free(buf); - data->phase2_types = methods; - data->num_phase2_types = num_methods; - } - if (data->phase2_types == NULL) { - data->phase2_types = - eap_get_phase2_types(config, &data->num_phase2_types); - } - if (data->phase2_types == NULL) { - wpa_printf(MSG_ERROR, "EAP-FAST: No Phase2 method available"); - eap_fast_deinit(sm, data); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 EAP types", - data->phase2_types, data->num_phase2_types); - data->phase2_type = EAP_TYPE_NONE; - - if (eap_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); - eap_fast_deinit(sm, data); - return NULL; - } - - /* The local RADIUS server in a Cisco AP does not seem to like empty - * fragments before data, so disable that workaround for CBC. - * TODO: consider making this configurable */ - tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn); - - if (eap_fast_load_pac(data, config->pac_file) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - if (data->pac == NULL && !data->provisioning_allowed) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC configured and " - "provisioning disabled"); - eap_fast_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - struct eap_fast_pac *pac, *prev; - - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - free(data->phase2_types); - free(data->key_block_a); - free(data->key_block_p); - eap_tls_ssl_deinit(sm, &data->ssl); - - pac = data->pac; - prev = NULL; - while (pac) { - prev = pac; - pac = pac->next; - eap_fast_free_pac(prev); - } - free(data); -} - - -static int eap_fast_encrypt(struct eap_sm *sm, struct eap_fast_data *data, - int id, u8 *plain, size_t plain_len, - u8 **out_data, size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *resp; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (resp == NULL) - return 0; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_FAST; - *pos++ = data->fast_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt Phase 2 " - "data"); - free(resp); - return 0; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - return 0; -} - - -static int eap_fast_phase2_nak(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct eap_hdr *resp_hdr; - u8 *pos = (u8 *) (hdr + 1); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Allowed Phase2 EAP types", - data->phase2_types, data->num_phase2_types); - *resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_types; - *resp = malloc(*resp_len); - if (*resp == NULL) - return -1; - - resp_hdr = (struct eap_hdr *) (*resp); - resp_hdr->code = EAP_CODE_RESPONSE; - resp_hdr->identifier = hdr->identifier; - resp_hdr->length = host_to_be16(*resp_len); - pos = (u8 *) (resp_hdr + 1); - *pos++ = EAP_TYPE_NAK; - memcpy(pos, data->phase2_types, data->num_phase2_types); - - return 0; -} - - -static int eap_fast_derive_msk(struct eap_sm *sm, struct eap_fast_data *data) -{ - u8 isk[32]; - u8 imck[60]; - - if (data->key_block_a == NULL) - return -1; - - memset(isk, 0, sizeof(isk)); - sha1_t_prf(data->key_block_a->session_key_seed, - sizeof(data->key_block_a->session_key_seed), - "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - sha1_t_prf(imck, 40, "Session Key Generating Function", (u8 *) "", 0, - data->key_data, EAP_FAST_KEY_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", - data->key_data, EAP_FAST_KEY_LEN); - - data->success = 1; - - return 0; -} - - -static int eap_fast_set_tls_master_secret(struct eap_sm *sm, - struct eap_fast_data *data, - const u8 *tls, size_t tls_len) -{ - struct tls_keys keys; - u8 master_secret[48], *seed; - const u8 *server_random; - size_t seed_len, server_random_len; - - if (data->tls_master_secret_set || !data->current_pac || - tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys)) { - return 0; - } - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", - keys.client_random, keys.client_random_len); - - /* TLS master secret is needed before TLS library has processed this - * message which includes both ServerHello and an encrypted handshake - * message, so we need to parse server_random from this message before - * passing it to TLS library. - * - * Example TLS packet header: - * (16 03 01 00 2a 02 00 00 26 03 01 <32 bytes server_random>) - * Content Type: Handshake: 0x16 - * Version: TLS 1.0 (0x0301) - * Lenghth: 42 (0x002a) - * Handshake Type: Server Hello: 0x02 - * Length: 38 (0x000026) - * Version TLS 1.0 (0x0301) - * Random: 32 bytes - */ - if (tls_len < 43 || tls[0] != 0x16 || - tls[1] != 0x03 || tls[2] != 0x01 || - tls[5] != 0x02 || tls[9] != 0x03 || tls[10] != 0x01) { - wpa_hexdump(MSG_DEBUG, "EAP-FAST: unrecognized TLS " - "ServerHello", tls, tls_len); - return -1; - } - server_random = tls + 11; - server_random_len = 32; - wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", - server_random, server_random_len); - - - seed_len = keys.client_random_len + server_random_len; - seed = malloc(seed_len); - if (seed == NULL) - return -1; - memcpy(seed, server_random, server_random_len); - memcpy(seed + server_random_len, - keys.client_random, keys.client_random_len); - - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: T-PRF seed", seed, seed_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: PAC-Key", - data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN); - /* master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", - * server_random + client_random, 48) */ - sha1_t_prf(data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN, - "PAC to master secret label hash", - seed, seed_len, master_secret, sizeof(master_secret)); - free(seed); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: TLS pre-master-secret", - master_secret, sizeof(master_secret)); - - data->tls_master_secret_set = 1; - - return tls_connection_set_master_key(sm->ssl_ctx, data->ssl.conn, - master_secret, - sizeof(master_secret)); -} - - -static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *random; - u8 *out; - - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - return NULL; - out = malloc(len); - random = malloc(keys.client_random_len + keys.server_random_len); - if (out == NULL || random == NULL) { - free(out); - free(random); - return NULL; - } - memcpy(random, keys.server_random, keys.server_random_len); - memcpy(random + keys.server_random_len, keys.client_random, - keys.client_random_len); - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " - "expansion", keys.master_key, keys.master_key_len); - if (tls_prf(keys.master_key, keys.master_key_len, - label, random, keys.client_random_len + - keys.server_random_len, out, len)) { - free(random); - free(out); - return NULL; - } - free(random); - return out; -} - - -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) -{ - free(data->key_block_a); - data->key_block_a = (struct eap_fast_key_block_auth *) - eap_fast_derive_key(sm, &data->ssl, "key expansion", - sizeof(*data->key_block_a)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed", - data->key_block_a->session_key_seed, - sizeof(data->key_block_a->session_key_seed)); -} - - -static void eap_fast_derive_key_provisioning(struct eap_sm *sm, - struct eap_fast_data *data) -{ - free(data->key_block_p); - data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm, &data->ssl, "key expansion", - sizeof(*data->key_block_p)); - if (data->key_block_p == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); - return; - } - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: session_key_seed", - data->key_block_p->session_key_seed, - sizeof(data->key_block_p->session_key_seed)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: server_challenge", - data->key_block_p->server_challenge, - sizeof(data->key_block_p->server_challenge)); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: client_challenge", - data->key_block_p->client_challenge, - sizeof(data->key_block_p->client_challenge)); -} - - -static void eap_fast_derive_keys(struct eap_sm *sm, struct eap_fast_data *data) -{ - if (data->current_pac) { - eap_fast_derive_key_auth(sm, data); - } else { - eap_fast_derive_key_provisioning(sm, data); - } -} - - -static int eap_fast_phase2_request(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-FAST: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1); - break; - default: - if (data->phase2_type == EAP_TYPE_NONE) { - int i; - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i] != *pos) - continue; - - data->phase2_type = *pos; - wpa_printf(MSG_DEBUG, "EAP-FAST: Selected " - "Phase 2 EAP method %d", - data->phase2_type); - break; - } - } - if (*pos != data->phase2_type || *pos == EAP_TYPE_NONE) { - if (eap_fast_phase2_nak(sm, data, hdr, resp, resp_len)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_sm_get_eap_methods(*pos); - if (data->phase2_method) { - if (data->key_block_p) { - sm->auth_challenge = - data->key_block_p-> - server_challenge; - sm->peer_challenge = - data->key_block_p-> - client_challenge; - } - sm->init_phase2 = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->auth_challenge = NULL; - sm->peer_challenge = NULL; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: failed to initialize " - "Phase 2 EAP method %d", *pos); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - memset(&iret, 0, sizeof(iret)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, (u8 *) hdr, len, - resp_len); - if (*resp == NULL || - (iret.methodState == METHOD_DONE && - iret.decision == DECISION_FAIL)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } else if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC)) { - data->phase2_success = 1; - } - if (*resp == NULL) - return -1; - break; - } - return 0; -} - - -static u8 * eap_fast_tlv_nak(int vendor_id, int tlv_type, size_t *len) -{ - struct eap_tlv_nak_tlv *nak; - *len = sizeof(*nak); - nak = malloc(*len); - if (nak == NULL) - return NULL; - nak->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_NAK_TLV); - nak->length = host_to_be16(6); - nak->vendor_id = host_to_be32(vendor_id); - nak->nak_type = host_to_be16(tlv_type); - return (u8 *) nak; -} - - -static u8 * eap_fast_tlv_result(int status, int intermediate, size_t *len) -{ - struct eap_tlv_intermediate_result_tlv *result; - *len = sizeof(*result); - result = malloc(*len); - if (result == NULL) - return NULL; - result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - (intermediate ? - EAP_TLV_INTERMEDIATE_RESULT_TLV : - EAP_TLV_RESULT_TLV)); - result->length = host_to_be16(2); - result->status = host_to_be16(status); - return (u8 *) result; -} - - -static u8 * eap_fast_tlv_pac_ack(size_t *len) -{ - struct eap_tlv_result_tlv *res; - struct eap_tlv_pac_ack_tlv *ack; - - *len = sizeof(*res) + sizeof(*ack); - res = malloc(*len); - if (res == NULL) - return NULL; - - memset(res, 0, *len); - res->tlv_type = host_to_be16(EAP_TLV_RESULT_TLV | - EAP_TLV_TYPE_MANDATORY); - res->length = host_to_be16(sizeof(*res) - sizeof(struct eap_tlv_hdr)); - res->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - ack = (struct eap_tlv_pac_ack_tlv *) (res + 1); - ack->tlv_type = host_to_be16(EAP_TLV_PAC_TLV | - EAP_TLV_TYPE_MANDATORY); - ack->length = host_to_be16(sizeof(*ack) - sizeof(struct eap_tlv_hdr)); - ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT); - ack->pac_len = host_to_be16(2); - ack->result = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - return (u8 *) res; -} - - -static u8 * eap_fast_tlv_eap_payload(u8 *buf, size_t *len) -{ - struct eap_tlv_hdr *tlv; - - /* Encapsulate EAP packet in EAP Payload TLV */ - tlv = malloc(sizeof(*tlv) + *len); - if (tlv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to " - "allocate memory for TLV " - "encapsulation"); - free(buf); - return NULL; - } - tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_EAP_PAYLOAD_TLV); - tlv->length = host_to_be16(*len); - memcpy(tlv + 1, buf, *len); - free(buf); - *len += sizeof(*tlv); - return (u8 *) tlv; -} - - -static u8 * eap_fast_process_crypto_binding( - struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_tlv_crypto_binding__tlv *bind, size_t bind_len, - size_t *resp_len, int final) -{ - u8 *resp, *sks = NULL; - struct eap_tlv_intermediate_result_tlv *rresult; - struct eap_tlv_crypto_binding__tlv *rbind; - u8 isk[32], imck[60], *cmk, cmac[20], *key; - size_t key_len; - int res; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - bind->version, bind->received_version, bind->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - bind->nonce, sizeof(bind->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - bind->compound_mac, sizeof(bind->compound_mac)); - - if (bind->version != EAP_FAST_VERSION || - bind->received_version != EAP_FAST_VERSION || - bind->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid version/subtype in " - "Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - bind->version, bind->received_version, - bind->subtype); - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1, - resp_len); - return resp; - } - - - if (data->provisioning) { - if (data->key_block_p) { - sks = data->key_block_p->session_key_seed; - } - } else { - if (data->key_block_a) { - sks = data->key_block_a->session_key_seed; - } - } - if (sks == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No Session Key Seed available " - "for processing Crypto-Binding TLV"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK for Compound MIC " - "calculation"); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[0] = SKS", sks, 40); - - memset(isk, 0, sizeof(isk)); - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "available"); - return NULL; - } - if (data->phase2_method->isKeyAvailable && data->phase2_method->getKey) - { - if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) - || - (key = data->phase2_method->getKey(sm, data->phase2_priv, - &key_len)) == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key " - "material from Phase 2"); - return NULL; - } - if (key_len > sizeof(isk)) - key_len = sizeof(isk); - /* FIX: which end is being padded? */ -#if 0 - memcpy(isk + (sizeof(isk) - key_len), key, key_len); -#else - memcpy(isk, key, key_len); -#endif - free(key); - } - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[0]", isk, sizeof(isk)); - sha1_t_prf(sks, 40, "Inner Methods Compound Keys", - isk, sizeof(isk), imck, sizeof(imck)); - /* S-IMCK[1] = imkc[0..39] */ - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[1]", imck, 40); - cmk = imck + 40; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK", cmk, 20); - - memcpy(cmac, bind->compound_mac, sizeof(cmac)); - memset(bind->compound_mac, 0, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound " - "MAC calculation", (u8 *) bind, bind_len); - hmac_sha1(cmk, 20, (u8 *) bind, bind_len, bind->compound_mac); - res = memcmp(cmac, bind->compound_mac, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC", - cmac, sizeof(cmac)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC", - bind->compound_mac, sizeof(cmac)); - if (res != 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match"); - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1, - resp_len); - memcpy(bind->compound_mac, cmac, sizeof(cmac)); - return resp; - } - - *resp_len = sizeof(*rresult) + sizeof(*rbind); - resp = malloc(*resp_len); - if (resp == NULL) - return NULL; - memset(resp, 0, *resp_len); - - /* Both intermediate and final Result TLVs are identical, so ok to use - * the same structure definition for them. */ - rresult = (struct eap_tlv_intermediate_result_tlv *) resp; - rresult->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - (final ? EAP_TLV_RESULT_TLV : - EAP_TLV_INTERMEDIATE_RESULT_TLV)); - rresult->length = host_to_be16(2); - rresult->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - if (!data->provisioning && data->phase2_success && - eap_fast_derive_msk(sm, data) < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - rresult->status = host_to_be16(EAP_TLV_RESULT_FAILURE); - data->phase2_success = 0; - } - - rbind = (struct eap_tlv_crypto_binding__tlv *) (rresult + 1); - rbind->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_CRYPTO_BINDING_TLV_); - rbind->length = host_to_be16(sizeof(*rbind) - - sizeof(struct eap_tlv_hdr)); - rbind->version = EAP_FAST_VERSION; - rbind->received_version = bind->version; - rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE; - memcpy(rbind->nonce, bind->nonce, sizeof(bind->nonce)); - inc_byte_array(rbind->nonce, sizeof(bind->nonce)); - hmac_sha1(cmk, 20, (u8 *) rbind, sizeof(*rbind), rbind->compound_mac); - - wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d " - "Received Version %d SubType %d", - rbind->version, rbind->received_version, rbind->subtype); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", - rbind->nonce, sizeof(rbind->nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", - rbind->compound_mac, sizeof(rbind->compound_mac)); - - if (final && data->phase2_success) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication completed " - "successfully."); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - - return resp; -} - - -static u8 * eap_fast_process_pac(struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - u8 *pac, size_t pac_len, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct pac_tlv_hdr *hdr; - u8 *pos; - size_t left, len; - int type, pac_key_found = 0; - struct eap_fast_pac entry; - - memset(&entry, 0, sizeof(entry)); - pos = pac; - left = pac_len; - while (left > sizeof(*hdr)) { - hdr = (struct pac_tlv_hdr *) pos; - type = be_to_host16(hdr->type); - len = be_to_host16(hdr->len); - pos += sizeof(*hdr); - left -= sizeof(*hdr); - if (len > left) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV overrun " - "(type=%d len=%lu left=%lu)", - type, (unsigned long) len, - (unsigned long) left); - return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - switch (type) { - case PAC_TYPE_PAC_KEY: - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key", - pos, len); - if (len != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid " - "PAC-Key length %lu", - (unsigned long) len); - break; - } - pac_key_found = 1; - memcpy(entry.pac_key, pos, len); - break; - case PAC_TYPE_PAC_OPAQUE: - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", - pos, len); - entry.pac_opaque = pos; - entry.pac_opaque_len = len; - break; - case PAC_TYPE_PAC_INFO: - wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info", - pos, len); - entry.pac_info = pos; - entry.pac_info_len = len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC " - "type %d", type); - break; - } - - pos += len; - left -= len; - } - - if (!pac_key_found || !entry.pac_opaque || !entry.pac_info) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV does not include " - "all the required fields"); - return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - - pos = entry.pac_info; - left = entry.pac_info_len; - while (left > sizeof(*hdr)) { - hdr = (struct pac_tlv_hdr *) pos; - type = be_to_host16(hdr->type); - len = be_to_host16(hdr->len); - pos += sizeof(*hdr); - left -= sizeof(*hdr); - if (len > left) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info overrun " - "(type=%d len=%lu left=%lu)", - type, (unsigned long) len, - (unsigned long) left); - return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - switch (type) { - case PAC_TYPE_A_ID: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - " - "A-ID", pos, len); - entry.a_id = pos; - entry.a_id_len = len; - break; - case PAC_TYPE_I_ID: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - " - "I-ID", pos, len); - entry.i_id = pos; - entry.i_id_len = len; - break; - case PAC_TYPE_A_ID_INFO: - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - " - "A-ID-Info", pos, len); - entry.a_id_info = pos; - entry.a_id_info_len = len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown " - "PAC-Info type %d", type); - break; - } - - pos += len; - left -= len; - } - - if (entry.a_id == NULL || entry.a_id_info == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info does not include " - "all the required fields"); - return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - - eap_fast_add_pac(data, &entry); - eap_fast_save_pac(data, config->pac_file); - - if (data->provisioning) { - /* EAP-FAST provisioning does not provide keying material and - * must end with an EAP-Failure. Authentication will be done - * separately after this. */ - data->success = 0; - ret->decision = DECISION_FAIL; - wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV " - "- Provisioning completed successfully"); - } else { - /* This is PAC refreshing, i.e., normal authentication that is - * expected to be completed with an EAP-Success. */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV " - "- PAC refreshing completed successfully"); - ret->decision = DECISION_UNCOND_SUCC; - } - ret->methodState = METHOD_DONE; - return eap_fast_tlv_pac_ack(resp_len); -} - - -static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, struct eap_hdr *req, - u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - u8 *in_decrypted, *pos, *end; - int buf_len, len_decrypted, len, res; - struct eap_hdr *hdr; - u8 *resp = NULL; - size_t resp_len; - int mandatory, tlv_type; - u8 *eap_payload_tlv = NULL, *pac = NULL; - size_t eap_payload_tlv_len = 0, pac_len = 0; - int iresult = 0, result = 0; - struct eap_tlv_crypto_binding__tlv *crypto_binding = NULL; - size_t crypto_binding_len = 0; - - wpa_printf(MSG_DEBUG, "EAP-FAST: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len); - if (res < 0 || res == 1) - return res; - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = malloc(buf_len); - if (in_decrypted == NULL) { - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-FAST: failed to allocate memory " - "for decryption"); - return -1; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 " - "data"); - free(in_decrypted); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Decrypted Phase 2 TLV(s)", - in_decrypted, len_decrypted); - - if (len_decrypted < 4) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " - "TLV frame (len=%d)", len_decrypted); - return -1; - } - - pos = in_decrypted; - end = in_decrypted + len_decrypted; - while (pos < end) { - mandatory = pos[0] & 0x80; - tlv_type = ((pos[0] & 0x3f) << 8) | pos[1]; - len = (pos[2] << 8) | pos[3]; - pos += 4; - if (pos + len > end) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); - return 0; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: received Phase 2: " - "TLV type %d length %d%s", - tlv_type, len, mandatory ? " (mandatory)" : ""); - - switch (tlv_type) { - case EAP_TLV_EAP_PAYLOAD_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP Payload TLV", - pos, len); - eap_payload_tlv = pos; - eap_payload_tlv_len = len; - break; - case EAP_TLV_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", - pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Result TLV"); - result = EAP_TLV_RESULT_FAILURE; - break; - } - result = (pos[0] << 16) | pos[1]; - if (result != EAP_TLV_RESULT_SUCCESS && - result != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown " - "Result %d", result); - result = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", - result == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_INTERMEDIATE_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate " - "Result TLV", pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Intermediate Result TLV"); - iresult = EAP_TLV_RESULT_FAILURE; - break; - } - iresult = (pos[0] << 16) | pos[1]; - if (iresult != EAP_TLV_RESULT_SUCCESS && - iresult != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown " - "Intermediate Result %d", iresult); - iresult = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, - "EAP-FAST: Intermediate Result: %s", - iresult == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_CRYPTO_BINDING_TLV_: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding " - "TLV", pos, len); - crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; - if (crypto_binding_len < sizeof(*crypto_binding)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Crypto-Binding TLV"); - iresult = EAP_TLV_RESULT_FAILURE; - pos = end; - break; - } - crypto_binding = - (struct eap_tlv_crypto_binding__tlv *) - (pos - sizeof(struct eap_tlv_hdr)); - break; - case EAP_TLV_PAC_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", - pos, len); - pac = pos; - pac_len = len; - break; - default: - if (mandatory) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " - "mandatory TLV type %d", tlv_type); - resp = eap_fast_tlv_nak(0, tlv_type, - &resp_len); - pos = end; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: ignored " - "unknown optional TLV type %d", - tlv_type); - } - break; - } - - pos += len; - } - - if (!resp && result == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - &resp_len); - if (!resp) { - free(in_decrypted); - return 0; - } - } - - if (!resp && iresult == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1, - &resp_len); - if (!resp) { - free(in_decrypted); - return 0; - } - } - - if (!resp && eap_payload_tlv) { - if (eap_payload_tlv_len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: too short EAP " - "Payload TLV (len=%lu)", - (unsigned long) eap_payload_tlv_len); - free(in_decrypted); - return 0; - } - hdr = (struct eap_hdr *) eap_payload_tlv; - if (be_to_host16(hdr->length) > eap_payload_tlv_len) { - wpa_printf(MSG_DEBUG, "EAP-FAST: EAP packet overflow " - "in EAP Payload TLV"); - } - if (hdr->code == EAP_CODE_REQUEST) { - if (eap_fast_phase2_request(sm, data, ret, req, hdr, - &resp, &resp_len)) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-FAST: Phase2 " - "Request processing failed"); - return 0; - } - resp = eap_fast_tlv_eap_payload(resp, &resp_len); - if (resp == NULL) { - free(in_decrypted); - return 0; - } - } else { - wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - free(in_decrypted); - return 0; - } - } - - if (!resp && crypto_binding) { - int final = result == EAP_TLV_RESULT_SUCCESS; - resp = eap_fast_process_crypto_binding(sm, data, ret, - crypto_binding, - crypto_binding_len, - &resp_len, final); - if (!resp) { - free(in_decrypted); - return 0; - } - } - - if (!resp && pac && result != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV " - "acnowledging success"); - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - &resp_len); - if (!resp) { - free(in_decrypted); - return 0; - } - } - - if (!resp && pac && result == EAP_TLV_RESULT_SUCCESS) { - resp = eap_fast_process_pac(sm, data, ret, pac, pac_len, - &resp_len); - if (!resp) { - free(in_decrypted); - return 0; - } - } - - free(in_decrypted); - - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send " - "empty response packet"); - resp = malloc(0); - if (resp == NULL) - return 0; - resp_len = 0; - } - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 data", - resp, resp_len); - if (eap_fast_encrypt(sm, data, req->identifier, resp, resp_len, - out_data, out_len)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 " - "frame"); - } - free(resp); - - return 0; -} - - -static u8 * eap_fast_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_hdr *req; - int left, res; - unsigned int tls_msg_len; - u8 flags, *pos, *resp, id; - struct eap_fast_data *data = priv; - - if (tls_get_errors(sm->ssl_ctx)) { - wpa_printf(MSG_INFO, "EAP-FAST: TLS errors detected"); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 2 || *pos != EAP_TYPE_FAST || - (left = host_to_be16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - left -= sizeof(struct eap_hdr); - id = req->identifier; - pos++; - flags = *pos++; - left -= 2; - wpa_printf(MSG_DEBUG, "EAP-FAST: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) reqDataLen, flags); - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-FAST: Short frame with TLS " - "length"); - ret->ignore = TRUE; - return NULL; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-FAST: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - if (flags & EAP_TLS_FLAGS_START) { - u8 *a_id; - size_t a_id_len; - struct pac_tlv_hdr *hdr; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Start (server ver=%d, own " - "ver=%d)", flags & EAP_PEAP_VERSION_MASK, - data->fast_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->fast_version) - data->fast_version = flags & EAP_PEAP_VERSION_MASK; - wpa_printf(MSG_DEBUG, "EAP-FAST: Using FAST version %d", - data->fast_version); - - a_id = pos; - a_id_len = left; - if (left > sizeof(*hdr)) { - int tlen; - hdr = (struct pac_tlv_hdr *) pos; - tlen = be_to_host16(hdr->len); - if (be_to_host16(hdr->type) == PAC_TYPE_A_ID && - sizeof(*hdr) + tlen <= left) { - a_id = (u8 *) (hdr + 1); - a_id_len = tlen; - } - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: A-ID", a_id, a_id_len); - - data->current_pac = eap_fast_get_pac(data, a_id, a_id_len); - if (data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC found for this " - "A-ID"); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-FAST: A-ID-Info", - data->current_pac->a_id_info, - data->current_pac->a_id_info_len); - } - - if (data->resuming && data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Trying to resume " - "session - do not add PAC-Opaque to TLS " - "ClientHello"); - if (tls_connection_client_hello_ext( - sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to " - "remove PAC-Opaque TLS extension"); - return NULL; - } - - } else if (data->current_pac) { - u8 *tlv; - size_t tlv_len, olen; - struct eap_tlv_hdr *hdr; - olen = data->current_pac->pac_opaque_len; - tlv_len = sizeof(*hdr) + olen; - tlv = malloc(tlv_len); - if (tlv) { - hdr = (struct eap_tlv_hdr *) tlv; - hdr->tlv_type = - host_to_be16(PAC_TYPE_PAC_OPAQUE); - hdr->length = host_to_be16(olen); - memcpy(hdr + 1, data->current_pac->pac_opaque, - olen); - } - if (tlv == NULL || - tls_connection_client_hello_ext( - sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, tlv, tlv_len) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to " - "add PAC-Opaque TLS extension"); - free(tlv); - return NULL; - } - free(tlv); - } else { - if (!data->provisioning_allowed) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found " - "and provisioning disabled"); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found - " - "starting provisioning"); - if (tls_connection_set_anon_dh(sm->ssl_ctx, - data->ssl.conn)) { - wpa_printf(MSG_INFO, "EAP-FAST: Could not " - "configure anonymous DH for TLS " - "connection"); - return NULL; - } - if (tls_connection_client_hello_ext( - sm->ssl_ctx, data->ssl.conn, - TLS_EXT_PAC_OPAQUE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to " - "remove PAC-Opaque TLS extension"); - return NULL; - } - data->provisioning = 1; - } - - left = 0; /* A-ID is not used in further packet processing */ - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - res = eap_fast_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - /* Ack possible Alert that may have caused failure in - * decryption */ - res = 1; - } - } else { - if (eap_fast_set_tls_master_secret(sm, data, pos, left) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to configure " - "TLS master secret"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, id, pos, left, - &resp, respDataLen); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, - "EAP-FAST: TLS done, proceed to Phase 2"); - data->resuming = 0; - eap_fast_derive_keys(sm, data); - } - } - - if (res == 1) - return eap_tls_build_ack(&data->ssl, respDataLen, id, - EAP_TYPE_FAST, data->fast_version); - return resp; -} - - -#if 0 /* FIX */ -static Boolean eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); -} - - -static void eap_fast_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ -} - - -static void * eap_fast_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - if (eap_tls_reauth_init(sm, &data->ssl)) { - free(data); - return NULL; - } - data->phase2_success = 0; - data->resuming = 1; - data->provisioning = 0; - return priv; -} -#endif - - -static int eap_fast_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_fast_data *data = priv; - return eap_tls_status(sm, &data->ssl, buf, buflen, verbose); -} - - -static Boolean eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - return data->success; -} - - -static u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_fast_data *data = priv; - u8 *key; - - if (!data->success) - return NULL; - - key = malloc(EAP_FAST_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_FAST_KEY_LEN; - memcpy(key, data->key_data, EAP_FAST_KEY_LEN); - - return key; -} - - -const struct eap_method eap_method_fast = -{ - .method = EAP_TYPE_FAST, - .name = "FAST", - .init = eap_fast_init, - .deinit = eap_fast_deinit, - .process = eap_fast_process, - .isKeyAvailable = eap_fast_isKeyAvailable, - .getKey = eap_fast_getKey, - .get_status = eap_fast_get_status, -#if 0 - .has_reauth_data = eap_fast_has_reauth_data, - .deinit_for_reauth = eap_fast_deinit_for_reauth, - .init_for_reauth = eap_fast_init_for_reauth, -#endif -}; diff --git a/contrib/wpa_supplicant/eap_gtc.c b/contrib/wpa_supplicant/eap_gtc.c deleted file mode 100644 index 42a7a49acaf1..000000000000 --- a/contrib/wpa_supplicant/eap_gtc.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * WPA Supplicant / EAP-GTC (RFC 2284) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" - - -struct eap_gtc_data { - int prefix; -}; - - -static void * eap_gtc_init(struct eap_sm *sm) -{ - struct eap_gtc_data *data; - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - - if (sm->m && sm->m->method == EAP_TYPE_FAST) { - wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " - "with challenge/response"); - data->prefix = 1; - } - return data; -} - - -static void eap_gtc_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - free(data); -} - - -static u8 * eap_gtc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_gtc_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req, *resp; - u8 *pos, *password; - size_t password_len, len, msg_len; - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 1 || *pos != EAP_TYPE_GTC || - (len = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - msg_len = len - sizeof(*req) - 1; - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", - pos, msg_len); - if (data->prefix && - (msg_len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " - "expected prefix"); - - /* Send an empty response in order to allow tunneled - * acknowledgement of the failure. This will also cover the - * error case which seems to use EAP-MSCHAPv2 like error - * reporting with EAP-GTC inside EAP-FAST tunnel. */ - *respDataLen = sizeof(struct eap_hdr) + 1; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_GTC; - return (u8 *) resp; - } - - if (config == NULL || - (config->password == NULL && config->otp == NULL)) { - wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); - eap_sm_request_otp(sm, config, (char *) pos, - len - sizeof(*req) - 1); - ret->ignore = TRUE; - return NULL; - } - - if (config->otp) { - password = config->otp; - password_len = config->otp_len; - } else { - password = config->password; - password_len = config->password_len; - } - - ret->ignore = FALSE; - - ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; - - *respDataLen = sizeof(struct eap_hdr) + 1 + password_len; - if (data->prefix) { - *respDataLen += 9 + config->identity_len + 1; - } - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_GTC; - if (data->prefix) { - memcpy(pos, "RESPONSE=", 9); - pos += 9; - memcpy(pos, config->identity, config->identity_len); - pos += config->identity_len; - *pos++ = '\0'; - } - memcpy(pos, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", - (u8 *) (resp + 1) + 1, - *respDataLen - sizeof(struct eap_hdr) - 1); - - if (config->otp) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); - memset(config->otp, 0, config->otp_len); - free(config->otp); - config->otp = NULL; - config->otp_len = 0; - } - - return (u8 *) resp; -} - - -const struct eap_method eap_method_gtc = -{ - .method = EAP_TYPE_GTC, - .name = "GTC", - .init = eap_gtc_init, - .deinit = eap_gtc_deinit, - .process = eap_gtc_process, -}; diff --git a/contrib/wpa_supplicant/eap_i.h b/contrib/wpa_supplicant/eap_i.h deleted file mode 100644 index c71981255783..000000000000 --- a/contrib/wpa_supplicant/eap_i.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef EAP_I_H -#define EAP_I_H - -#include "eap.h" - -/* draft-ietf-eap-statemachine-05.pdf - Peer state machine */ - -typedef enum { - DECISION_FAIL, DECISION_COND_SUCC, DECISION_UNCOND_SUCC -} EapDecision; - -typedef enum { - METHOD_NONE, METHOD_INIT, METHOD_CONT, METHOD_MAY_CONT, METHOD_DONE -} EapMethodState; - -struct eap_method_ret { - Boolean ignore; - EapMethodState methodState; - EapDecision decision; - Boolean allowNotifications; -}; - - -struct eap_method { - EapType method; - const char *name; - - void * (*init)(struct eap_sm *sm); - void (*deinit)(struct eap_sm *sm, void *priv); - u8 * (*process)(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen); - Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv); - u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); - int (*get_status)(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose); - - /* Optional handlers for fast re-authentication */ - Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv); - void (*deinit_for_reauth)(struct eap_sm *sm, void *priv); - void * (*init_for_reauth)(struct eap_sm *sm, void *priv); - const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len); -}; - - -struct eap_sm { - enum { - EAP_INITIALIZE, EAP_DISABLED, EAP_IDLE, EAP_RECEIVED, - EAP_GET_METHOD, EAP_METHOD, EAP_SEND_RESPONSE, EAP_DISCARD, - EAP_IDENTITY, EAP_NOTIFICATION, EAP_RETRANSMIT, EAP_SUCCESS, - EAP_FAILURE - } EAP_state; - /* Long-term local variables */ - EapType selectedMethod; - EapMethodState methodState; - int lastId; - u8 *lastRespData; - size_t lastRespDataLen; - EapDecision decision; - /* Short-term local variables */ - Boolean rxReq; - Boolean rxSuccess; - Boolean rxFailure; - int reqId; - EapType reqMethod; - Boolean ignore; - /* Constants */ - int ClientTimeout; - - /* Miscellaneous variables */ - Boolean allowNotifications; /* peer state machine <-> methods */ - u8 *eapRespData; /* peer to lower layer */ - size_t eapRespDataLen; /* peer to lower layer */ - Boolean eapKeyAvailable; /* peer to lower layer */ - u8 *eapKeyData; /* peer to lower layer */ - size_t eapKeyDataLen; /* peer to lower layer */ - const struct eap_method *m; /* selected EAP method */ - /* not defined in draft-ietf-eap-statemachine-02 */ - Boolean changed; - void *eapol_ctx; - struct eapol_callbacks *eapol_cb; - void *eap_method_priv; - int init_phase2; - int fast_reauth; - - Boolean rxResp /* LEAP only */; - Boolean leap_done; - Boolean peap_done; - u8 req_md5[16]; /* MD5() of the current EAP packet */ - u8 last_md5[16]; /* MD5() of the previously received EAP packet; used - * in duplicate request detection. */ - - void *msg_ctx; - void *scard_ctx; - void *ssl_ctx; - - unsigned int workaround; - - /* Optional challenges generated in Phase 1 (EAP-FAST) */ - u8 *peer_challenge, *auth_challenge; - - int num_rounds; -}; - -#endif /* EAP_I_H */ diff --git a/contrib/wpa_supplicant/eap_leap.c b/contrib/wpa_supplicant/eap_leap.c deleted file mode 100644 index 6409a6855f92..000000000000 --- a/contrib/wpa_supplicant/eap_leap.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * WPA Supplicant / EAP-LEAP - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "ms_funcs.h" -#include "md5.h" - -#define LEAP_VERSION 1 -#define LEAP_CHALLENGE_LEN 8 -#define LEAP_RESPONSE_LEN 24 -#define LEAP_KEY_LEN 16 - - -struct eap_leap_data { - enum { - LEAP_WAIT_CHALLENGE, - LEAP_WAIT_SUCCESS, - LEAP_WAIT_RESPONSE, - LEAP_DONE - } state; - - u8 peer_challenge[LEAP_CHALLENGE_LEN]; - u8 peer_response[LEAP_RESPONSE_LEN]; - - u8 ap_challenge[LEAP_CHALLENGE_LEN]; - u8 ap_response[LEAP_RESPONSE_LEN]; -}; - - -static void * eap_leap_init(struct eap_sm *sm) -{ - struct eap_leap_data *data; - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - data->state = LEAP_WAIT_CHALLENGE; - - sm->leap_done = FALSE; - return data; -} - - -static void eap_leap_deinit(struct eap_sm *sm, void *priv) -{ - free(priv); -} - - -static u8 * eap_leap_process_request(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_leap_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req, *resp; - u8 *pos, *challenge, challenge_len; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_LEAP) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - - if (*pos != LEAP_VERSION) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " - "%d", *pos); - ret->ignore = TRUE; - return NULL; - } - pos++; - - pos++; /* skip unused byte */ - - challenge_len = *pos++; - if (challenge_len != LEAP_CHALLENGE_LEN || - challenge_len > reqDataLen - sizeof(*req) - 4) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " - "(challenge_len=%d reqDataLen=%lu", - challenge_len, (unsigned long) reqDataLen); - ret->ignore = TRUE; - return NULL; - } - challenge = pos; - memcpy(data->peer_challenge, challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge from AP", - challenge, LEAP_CHALLENGE_LEN); - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Generating Challenge Response"); - - *respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_RESPONSE_LEN + - config->identity_len; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_LEAP; - *pos++ = LEAP_VERSION; - *pos++ = 0; /* unused */ - *pos++ = LEAP_RESPONSE_LEN; - nt_challenge_response(challenge, - config->password, config->password_len, pos); - memcpy(data->peer_response, pos, LEAP_RESPONSE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Response", pos, LEAP_RESPONSE_LEN); - pos += LEAP_RESPONSE_LEN; - memcpy(pos, config->identity, config->identity_len); - - data->state = LEAP_WAIT_SUCCESS; - - return (u8 *) resp; -} - - -static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_leap_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req, *resp; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success"); - - if (data->state != LEAP_WAIT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " - "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - - *respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_CHALLENGE_LEN + - config->identity_len; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_REQUEST; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_LEAP; - *pos++ = LEAP_VERSION; - *pos++ = 0; /* unused */ - *pos++ = LEAP_CHALLENGE_LEN; - if (hostapd_get_rand(pos, LEAP_CHALLENGE_LEN)) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " - "for challenge"); - free(resp); - ret->ignore = TRUE; - return NULL; - } - memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos, - LEAP_CHALLENGE_LEN); - pos += LEAP_CHALLENGE_LEN; - memcpy(pos, config->identity, config->identity_len); - - data->state = LEAP_WAIT_RESPONSE; - - return (u8 *) resp; -} - - -static u8 * eap_leap_process_response(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_leap_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *resp; - u8 *pos, response_len, pw_hash[16], pw_hash_hash[16], - expected[LEAP_RESPONSE_LEN]; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response"); - - resp = (struct eap_hdr *) reqData; - pos = (u8 *) (resp + 1); - if (reqDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_LEAP) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - - if (*pos != LEAP_VERSION) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " - "%d", *pos); - ret->ignore = TRUE; - return NULL; - } - pos++; - - pos++; /* skip unused byte */ - - response_len = *pos++; - if (response_len != LEAP_RESPONSE_LEN || - response_len > reqDataLen - sizeof(*resp) - 4) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " - "(response_len=%d reqDataLen=%lu", - response_len, (unsigned long) reqDataLen); - ret->ignore = TRUE; - return NULL; - } - - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Response from AP", - pos, LEAP_RESPONSE_LEN); - memcpy(data->ap_response, pos, LEAP_RESPONSE_LEN); - - nt_password_hash(config->password, config->password_len, pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - challenge_response(data->ap_challenge, pw_hash_hash, expected); - - ret->methodState = METHOD_DONE; - ret->allowNotifications = FALSE; - - if (memcmp(pos, expected, LEAP_RESPONSE_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid " - "response - authentication failed"); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: Expected response from AP", - expected, LEAP_RESPONSE_LEN); - ret->decision = DECISION_FAIL; - return NULL; - } - - ret->decision = DECISION_UNCOND_SUCC; - - /* LEAP is somewhat odd method since it sends EAP-Success in the middle - * of the authentication. Use special variable to transit EAP state - * machine to SUCCESS state. */ - sm->leap_done = TRUE; - data->state = LEAP_DONE; - - /* No more authentication messages expected; AP will send EAPOL-Key - * frames if encryption is enabled. */ - return NULL; -} - - -static u8 * eap_leap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *eap; - size_t len; - - if (config == NULL || config->password == NULL) { - wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured"); - eap_sm_request_password(sm, config); - ret->ignore = TRUE; - return NULL; - } - - eap = (struct eap_hdr *) reqData; - - if (reqDataLen < sizeof(*eap) || - (len = be_to_host16(eap->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->allowNotifications = TRUE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - - sm->leap_done = FALSE; - - switch (eap->code) { - case EAP_CODE_REQUEST: - return eap_leap_process_request(sm, priv, ret, reqData, len, - respDataLen); - case EAP_CODE_SUCCESS: - return eap_leap_process_success(sm, priv, ret, reqData, len, - respDataLen); - case EAP_CODE_RESPONSE: - return eap_leap_process_response(sm, priv, ret, reqData, len, - respDataLen); - default: - wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - " - "ignored", eap->code); - ret->ignore = TRUE; - return NULL; - } -} - - -static Boolean eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_leap_data *data = priv; - return data->state == LEAP_DONE; -} - - -static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_leap_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - u8 *key, pw_hash_hash[16], pw_hash[16]; - MD5_CTX context; - - if (data->state != LEAP_DONE) - return NULL; - - key = malloc(LEAP_KEY_LEN); - if (key == NULL) - return NULL; - - nt_password_hash(config->password, config->password_len, pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash", - pw_hash_hash, 16); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge", - data->peer_challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response", - data->peer_response, LEAP_RESPONSE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge", - data->ap_challenge, LEAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response", - data->ap_response, LEAP_RESPONSE_LEN); - - MD5Init(&context); - MD5Update(&context, pw_hash_hash, 16); - MD5Update(&context, data->ap_challenge, LEAP_CHALLENGE_LEN); - MD5Update(&context, data->ap_response, LEAP_RESPONSE_LEN); - MD5Update(&context, data->peer_challenge, LEAP_CHALLENGE_LEN); - MD5Update(&context, data->peer_response, LEAP_RESPONSE_LEN); - MD5Final(key, &context); - wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN); - *len = LEAP_KEY_LEN; - - return key; -} - - -const struct eap_method eap_method_leap = -{ - .method = EAP_TYPE_LEAP, - .name = "LEAP", - .init = eap_leap_init, - .deinit = eap_leap_deinit, - .process = eap_leap_process, - .isKeyAvailable = eap_leap_isKeyAvailable, - .getKey = eap_leap_getKey, -}; diff --git a/contrib/wpa_supplicant/eap_md5.c b/contrib/wpa_supplicant/eap_md5.c deleted file mode 100644 index bcb5558be97e..000000000000 --- a/contrib/wpa_supplicant/eap_md5.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * WPA Supplicant / EAP-MD5 - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "md5.h" - - -static void * eap_md5_init(struct eap_sm *sm) -{ - return (void *) 1; -} - - -static void eap_md5_deinit(struct eap_sm *sm, void *priv) -{ -} - - -static u8 * eap_md5_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req, *resp; - u8 *pos, *challenge; - int challenge_len; - MD5_CTX context; - size_t len; - - if (config == NULL || config->password == NULL) { - wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); - eap_sm_request_password(sm, config); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 2 || *pos != EAP_TYPE_MD5 || - (len = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - challenge_len = *pos++; - if (challenge_len == 0 || - challenge_len > len - sizeof(*req) - 2) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " - "(challenge_len=%d len=%lu", - challenge_len, (unsigned long) len); - ret->ignore = TRUE; - return NULL; - } - ret->ignore = FALSE; - challenge = pos; - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", - challenge, challenge_len); - - wpa_printf(MSG_DEBUG, "EAP-MD5: generating Challenge Response"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = TRUE; - - *respDataLen = sizeof(struct eap_hdr) + 1 + 1 + MD5_MAC_LEN; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_MD5; - *pos++ = MD5_MAC_LEN; /* Value-Size */ - - MD5Init(&context); - MD5Update(&context, &resp->identifier, 1); - MD5Update(&context, config->password, config->password_len); - MD5Update(&context, challenge, challenge_len); - MD5Final(pos, &context); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, MD5_MAC_LEN); - - return (u8 *) resp; -} - - -const struct eap_method eap_method_md5 = -{ - .method = EAP_TYPE_MD5, - .name = "MD5", - .init = eap_md5_init, - .deinit = eap_md5_deinit, - .process = eap_md5_process, -}; diff --git a/contrib/wpa_supplicant/eap_mschapv2.c b/contrib/wpa_supplicant/eap_mschapv2.c deleted file mode 100644 index 35c391c63c48..000000000000 --- a/contrib/wpa_supplicant/eap_mschapv2.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * WPA Supplicant / EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "ms_funcs.h" - - -struct eap_mschapv2_hdr { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_MSCHAPV2 */ - u8 op_code; /* MSCHAPV2_OP_* */ - u8 mschapv2_id; /* usually same as identifier */ - u8 ms_length[2]; /* Note: misaligned; length - 5 */ - /* followed by data */ -} __attribute__ ((packed)); - -#define MSCHAPV2_OP_CHALLENGE 1 -#define MSCHAPV2_OP_RESPONSE 2 -#define MSCHAPV2_OP_SUCCESS 3 -#define MSCHAPV2_OP_FAILURE 4 -#define MSCHAPV2_OP_CHANGE_PASSWORD 7 - -#define MSCHAPV2_RESP_LEN 49 - -#define ERROR_RESTRICTED_LOGON_HOURS 646 -#define ERROR_ACCT_DISABLED 647 -#define ERROR_PASSWD_EXPIRED 648 -#define ERROR_NO_DIALIN_PERMISSION 649 -#define ERROR_AUTHENTICATION_FAILURE 691 -#define ERROR_CHANGING_PASSWORD 709 - -#define PASSWD_CHANGE_CHAL_LEN 16 -#define MSCHAPV2_KEY_LEN 16 - - -struct eap_mschapv2_data { - u8 auth_response[20]; - int auth_response_valid; - - int prev_error; - u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN]; - int passwd_change_challenge_valid; - int passwd_change_version; - - /* Optional challenge values generated in EAP-FAST Phase 1 negotiation - */ - u8 *peer_challenge; - u8 *auth_challenge; - - int phase2; - u8 master_key[16]; - int master_key_valid; - int success; -}; - - -static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv); - - -static void * eap_mschapv2_init(struct eap_sm *sm) -{ - struct eap_mschapv2_data *data; - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - - if (sm->peer_challenge) { - data->peer_challenge = malloc(16); - if (data->peer_challenge == NULL) { - eap_mschapv2_deinit(sm, data); - return NULL; - } - memcpy(data->peer_challenge, sm->peer_challenge, 16); - } - - if (sm->auth_challenge) { - data->auth_challenge = malloc(16); - if (data->auth_challenge == NULL) { - eap_mschapv2_deinit(sm, data); - return NULL; - } - memcpy(data->auth_challenge, sm->auth_challenge, 16); - } - - data->phase2 = sm->init_phase2; - - return data; -} - - -static void eap_mschapv2_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - free(data->peer_challenge); - free(data->auth_challenge); - free(data); -} - - -static u8 * eap_mschapv2_challenge(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - struct eap_mschapv2_hdr *req, - size_t *respDataLen) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *challenge, *peer_challenge, *username, *pos; - int i, ms_len; - size_t len, challenge_len, username_len; - struct eap_mschapv2_hdr *resp; - u8 password_hash[16], password_hash_hash[16]; - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = config->identity; - username_len = config->identity_len; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received challenge"); - len = be_to_host16(req->length); - pos = (u8 *) (req + 1); - challenge_len = *pos++; - if (challenge_len != 16) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " - "%d", challenge_len); - ret->ignore = TRUE; - return NULL; - } - - if (len < 10 || len - 10 < challenge_len) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" - " packet: len=%lu challenge_len=%d", - (unsigned long) len, challenge_len); - ret->ignore = TRUE; - return NULL; - } - - challenge = pos; - pos += challenge_len; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", - pos, len - challenge_len - 10); - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); - - *respDataLen = sizeof(*resp) + 1 + MSCHAPV2_RESP_LEN + - config->identity_len; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - memset(resp, 0, *respDataLen); - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - resp->type = EAP_TYPE_MSCHAPV2; - resp->op_code = MSCHAPV2_OP_RESPONSE; - resp->mschapv2_id = req->mschapv2_id; - ms_len = *respDataLen - 5; - resp->ms_length[0] = ms_len >> 8; - resp->ms_length[1] = ms_len & 0xff; - pos = (u8 *) (resp + 1); - *pos++ = MSCHAPV2_RESP_LEN; /* Value-Size */ - - /* Response */ - peer_challenge = pos; - if (data->peer_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " - "in Phase 1"); - peer_challenge = data->peer_challenge; - } else if (hostapd_get_rand(peer_challenge, 16)) { - free(resp); - return NULL; - } - pos += 16; - pos += 8; /* Reserved, must be zero */ - if (data->auth_challenge) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " - "in Phase 1"); - challenge = data->auth_challenge; - } - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", challenge, 16); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", - peer_challenge, 16); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", - username, username_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: password", - config->password, config->password_len); - generate_nt_response(challenge, peer_challenge, - username, username_len, - config->password, config->password_len, - pos); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: response", pos, 24); - /* Authenticator response is not really needed yet, but calculate it - * here so that challenges need not be saved. */ - generate_authenticator_response(config->password, config->password_len, - peer_challenge, challenge, - username, username_len, pos, - data->auth_response); - data->auth_response_valid = 1; - - /* Likewise, generate master_key here since we have the needed data - * available. */ - nt_password_hash(config->password, config->password_len, - password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - get_master_key(password_hash_hash, pos /* nt_response */, - data->master_key); - data->master_key_valid = 1; - - pos += 24; - pos++; /* Flag / reserved, must be zero */ - - memcpy(pos, config->identity, config->identity_len); - return (u8 *) resp; -} - - -static u8 * eap_mschapv2_success(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - struct eap_mschapv2_hdr *req, - size_t *respDataLen) -{ - struct eap_mschapv2_hdr *resp; - u8 *pos, recv_response[20]; - int len, left; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); - len = be_to_host16(req->length); - pos = (u8 *) (req + 1); - if (!data->auth_response_valid || len < sizeof(*req) + 42 || - pos[0] != 'S' || pos[1] != '=' || - hexstr2bin((char *) (pos + 2), recv_response, 20) || - memcmp(data->auth_response, recv_response, 20) != 0) { - wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " - "response in success request"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - pos += 42; - left = len - sizeof(*req) - 42; - while (left > 0 && *pos == ' ') { - pos++; - left--; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message", - pos, left); - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded"); - *respDataLen = 6; - resp = malloc(6); - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " - "buffer for success response"); - ret->ignore = TRUE; - return NULL; - } - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(6); - resp->type = EAP_TYPE_MSCHAPV2; - resp->op_code = MSCHAPV2_OP_SUCCESS; - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - data->success = 1; - - return (u8 *) resp; -} - - -static int eap_mschapv2_failure_txt(struct eap_sm *sm, - struct eap_mschapv2_data *data, char *txt) -{ - char *pos, *msg = ""; - int retry = 1; - struct wpa_ssid *config = eap_get_config(sm); - - /* For example: - * E=691 R=1 C=<32 octets hex challenge> V=3 M=Authentication Failure - */ - - pos = txt; - - if (pos && strncmp(pos, "E=", 2) == 0) { - pos += 2; - data->prev_error = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: error %d", - data->prev_error); - pos = strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && strncmp(pos, "R=", 2) == 0) { - pos += 2; - retry = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: retry is %sallowed", - retry == 1 ? "" : "not "); - pos = strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && strncmp(pos, "C=", 2) == 0) { - int hex_len; - pos += 2; - hex_len = strchr(pos, ' ') - (char *) pos; - if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { - if (hexstr2bin(pos, data->passwd_change_challenge, - PASSWD_CHANGE_CHAL_LEN)) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid " - "failure challenge"); - } else { - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: failure " - "challenge", - data->passwd_change_challenge, - PASSWD_CHANGE_CHAL_LEN); - data->passwd_change_challenge_valid = 1; - } - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: invalid failure " - "challenge len %d", hex_len); - } - pos = strchr(pos, ' '); - if (pos) - pos++; - } else { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: required challenge field " - "was not present in failure message"); - } - - if (pos && strncmp(pos, "V=", 2) == 0) { - pos += 2; - data->passwd_change_version = atoi(pos); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: password changing " - "protocol version %d", data->passwd_change_version); - pos = strchr(pos, ' '); - if (pos) - pos++; - } - - if (pos && strncmp(pos, "M=", 2) == 0) { - pos += 2; - msg = pos; - } - wpa_msg(sm->msg_ctx, MSG_WARNING, - "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error " - "%d)", - msg, retry == 1 ? "" : "not ", data->prev_error); - if (retry == 1 && config) { - /* TODO: could prevent the current password from being used - * again at least for some period of time */ - eap_sm_request_identity(sm, config); - eap_sm_request_password(sm, config); - } else if (config) { - /* TODO: prevent retries using same username/password */ - } - - return retry == 1; -} - - -static u8 * eap_mschapv2_failure(struct eap_sm *sm, - struct eap_mschapv2_data *data, - struct eap_method_ret *ret, - struct eap_mschapv2_hdr *req, - size_t *respDataLen) -{ - struct eap_mschapv2_hdr *resp; - u8 *msdata = (u8 *) (req + 1); - char *buf; - int len = be_to_host16(req->length) - sizeof(*req); - int retry = 0; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data", - msdata, len); - buf = malloc(len + 1); - if (buf) { - memcpy(buf, msdata, len); - buf[len] = '\0'; - retry = eap_mschapv2_failure_txt(sm, data, buf); - free(buf); - } - - ret->ignore = FALSE; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - - if (retry) { - /* TODO: could try to retry authentication, e.g, after having - * changed the username/password. In this case, EAP MS-CHAP-v2 - * Failure Response would not be sent here. */ - } - - *respDataLen = 6; - resp = malloc(6); - if (resp == NULL) { - return NULL; - } - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(6); - resp->type = EAP_TYPE_MSCHAPV2; - resp->op_code = MSCHAPV2_OP_FAILURE; - - return (u8 *) resp; -} - - -static u8 * eap_mschapv2_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_mschapv2_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_mschapv2_hdr *req; - int ms_len, len; - - if (config == NULL || config->identity == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Identity not configured"); - eap_sm_request_identity(sm, config); - ret->ignore = TRUE; - return NULL; - } - - if (config->password == NULL) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured"); - eap_sm_request_password(sm, config); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_mschapv2_hdr *) reqData; - len = be_to_host16(req->length); - if (len < sizeof(*req) + 2 || req->type != EAP_TYPE_MSCHAPV2 || - len > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ms_len = ((int) req->ms_length[0] << 8) | req->ms_length[1]; - if (ms_len != len - 5) { - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid header: len=%d " - "ms_len=%d", len, ms_len); - if (sm->workaround) { - /* Some authentication servers use invalid ms_len, - * ignore it for interoperability. */ - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: workaround, ignore" - " invalid ms_len"); - } else { - ret->ignore = TRUE; - return NULL; - } - } - - switch (req->op_code) { - case MSCHAPV2_OP_CHALLENGE: - return eap_mschapv2_challenge(sm, data, ret, req, respDataLen); - case MSCHAPV2_OP_SUCCESS: - return eap_mschapv2_success(sm, data, ret, req, respDataLen); - case MSCHAPV2_OP_FAILURE: - return eap_mschapv2_failure(sm, data, ret, req, respDataLen); - default: - wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", - req->op_code); - ret->ignore = TRUE; - return NULL; - } -} - - -static Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - return data->success && data->master_key_valid; -} - - -static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_mschapv2_data *data = priv; - u8 *key; - int key_len; - - if (!data->master_key_valid || !data->success) - return NULL; - - if (data->peer_challenge) { - /* EAP-FAST needs both send and receive keys */ - key_len = 2 * MSCHAPV2_KEY_LEN; - } else { - key_len = MSCHAPV2_KEY_LEN; - } - - key = malloc(key_len); - if (key == NULL) - return NULL; - - if (data->peer_challenge) { - get_asymetric_start_key(data->master_key, key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(data->master_key, - key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - } else { - get_asymetric_start_key(data->master_key, key, - MSCHAPV2_KEY_LEN, 1, 0); - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-MSCHAPV2: Derived key", - key, key_len); - - *len = key_len; - return key; -} - - -const struct eap_method eap_method_mschapv2 = -{ - .method = EAP_TYPE_MSCHAPV2, - .name = "MSCHAPV2", - .init = eap_mschapv2_init, - .deinit = eap_mschapv2_deinit, - .process = eap_mschapv2_process, - .isKeyAvailable = eap_mschapv2_isKeyAvailable, - .getKey = eap_mschapv2_getKey, -}; diff --git a/contrib/wpa_supplicant/eap_otp.c b/contrib/wpa_supplicant/eap_otp.c deleted file mode 100644 index e50de636accd..000000000000 --- a/contrib/wpa_supplicant/eap_otp.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * WPA Supplicant / EAP-OTP (RFC 3748) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" - - -static void * eap_otp_init(struct eap_sm *sm) -{ - return (void *) 1; -} - - -static void eap_otp_deinit(struct eap_sm *sm, void *priv) -{ -} - - -static u8 * eap_otp_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req, *resp; - u8 *pos, *password; - size_t password_len, len; - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 1 || *pos != EAP_TYPE_OTP || - (len = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-OTP: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message", - pos, len - sizeof(*req) - 1); - - if (config == NULL || - (config->password == NULL && config->otp == NULL)) { - wpa_printf(MSG_INFO, "EAP-OTP: Password not configured"); - eap_sm_request_otp(sm, config, (char *) pos, - len - sizeof(*req) - 1); - ret->ignore = TRUE; - return NULL; - } - - if (config->otp) { - password = config->otp; - password_len = config->otp_len; - } else { - password = config->password; - password_len = config->password_len; - } - - ret->ignore = FALSE; - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; - - *respDataLen = sizeof(struct eap_hdr) + 1 + password_len; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_OTP; - memcpy(pos, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-OTP: Response", - password, password_len); - - if (config->otp) { - wpa_printf(MSG_DEBUG, "EAP-OTP: Forgetting used password"); - memset(config->otp, 0, config->otp_len); - free(config->otp); - config->otp = NULL; - config->otp_len = 0; - } - - return (u8 *) resp; -} - - -const struct eap_method eap_method_otp = -{ - .method = EAP_TYPE_OTP, - .name = "OTP", - .init = eap_otp_init, - .deinit = eap_otp_deinit, - .process = eap_otp_process, -}; diff --git a/contrib/wpa_supplicant/eap_peap.c b/contrib/wpa_supplicant/eap_peap.c deleted file mode 100644 index 8ca8ab260321..000000000000 --- a/contrib/wpa_supplicant/eap_peap.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * WPA Supplicant / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "tls.h" -#include "eap_tlv.h" - - -/* Maximum supported PEAP version - * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt - * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt - * 2 = draft-josefsson-ppext-eap-tls-eap-07.txt - */ -#define EAP_PEAP_VERSION 1 - - -static void eap_peap_deinit(struct eap_sm *sm, void *priv); - - -struct eap_peap_data { - struct eap_ssl_data ssl; - - int peap_version, force_peap_version, force_new_label; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - - u8 phase2_type; - u8 *phase2_types; - size_t num_phase2_types; - - int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner - * EAP-Success - * 1 = reply with tunneled EAP-Success to inner - * EAP-Success and expect AS to send outer - * (unencrypted) EAP-Success after this - * 2 = reply with PEAP/TLS ACK to inner - * EAP-Success and expect AS to send outer - * (unencrypted) EAP-Success after this */ - int resuming; /* starting a resumed session */ - u8 *key_data; - - u8 *pending_phase2_req; - size_t pending_phase2_req_len; -}; - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - struct wpa_ssid *config = eap_get_config(sm); - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - sm->peap_done = FALSE; - memset(data, 0, sizeof(*data)); - data->peap_version = EAP_PEAP_VERSION; - data->force_peap_version = -1; - data->peap_outer_success = 2; - - if (config && config->phase1) { - char *pos = strstr(config->phase1, "peapver="); - if (pos) { - data->force_peap_version = atoi(pos + 8); - data->peap_version = data->force_peap_version; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version " - "%d", data->force_peap_version); - } - - if (strstr(config->phase1, "peaplabel=1")) { - data->force_new_label = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for " - "key derivation"); - } - - if (strstr(config->phase1, "peap_outer_success=0")) { - data->peap_outer_success = 0; - wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate " - "authentication on tunneled EAP-Success"); - } else if (strstr(config->phase1, "peap_outer_success=1")) { - data->peap_outer_success = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled " - "EAP-Success after receiving tunneled " - "EAP-Success"); - } else if (strstr(config->phase1, "peap_outer_success=2")) { - data->peap_outer_success = 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK " - "after receiving tunneled EAP-Success"); - } - } - - if (config && config->phase2) { - char *start, *pos, *buf; - u8 method, *methods = NULL, *_methods; - size_t num_methods = 0; - start = buf = strdup(config->phase2); - if (buf == NULL) { - eap_peap_deinit(sm, data); - return NULL; - } - while (start && *start != '\0') { - pos = strstr(start, "auth="); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + 5; - continue; - } - - start = pos + 5; - pos = strchr(start, ' '); - if (pos) - *pos++ = '\0'; - method = eap_get_phase2_type(start); - if (method == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "EAP-PEAP: Unsupported " - "Phase2 method '%s'", start); - } else { - num_methods++; - _methods = realloc(methods, num_methods); - if (_methods == NULL) { - free(methods); - eap_peap_deinit(sm, data); - return NULL; - } - methods = _methods; - methods[num_methods - 1] = method; - } - - start = pos; - } - free(buf); - data->phase2_types = methods; - data->num_phase2_types = num_methods; - } - if (data->phase2_types == NULL) { - data->phase2_types = - eap_get_phase2_types(config, &data->num_phase2_types); - } - if (data->phase2_types == NULL) { - wpa_printf(MSG_ERROR, "EAP-PEAP: No Phase2 method available"); - eap_peap_deinit(sm, data); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 EAP types", - data->phase2_types, data->num_phase2_types); - data->phase2_type = EAP_TYPE_NONE; - - if (eap_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); - eap_peap_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_peap_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - free(data->phase2_types); - eap_tls_ssl_deinit(sm, &data->ssl); - free(data->key_data); - free(data->pending_phase2_req); - free(data); -} - - -static int eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data, - int id, u8 *plain, size_t plain_len, - u8 **out_data, size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *resp; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. - * Note: Microsoft IAS did not seem to like TLS Message Length with - * PEAP/MSCHAPv2. */ - resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (resp == NULL) - return -1; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_PEAP; - *pos++ = data->peap_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 " - "data"); - free(resp); - return -1; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - return 0; -} - - -static int eap_peap_phase2_nak(struct eap_sm *sm, - struct eap_peap_data *data, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct eap_hdr *resp_hdr; - u8 *pos = (u8 *) (hdr + 1); - - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Allowed Phase2 EAP types", - data->phase2_types, data->num_phase2_types); - *resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_types; - *resp = malloc(*resp_len); - if (*resp == NULL) - return -1; - - resp_hdr = (struct eap_hdr *) (*resp); - resp_hdr->code = EAP_CODE_RESPONSE; - resp_hdr->identifier = hdr->identifier; - resp_hdr->length = host_to_be16(*resp_len); - pos = (u8 *) (resp_hdr + 1); - *pos++ = EAP_TYPE_NAK; - memcpy(pos, data->phase2_types, data->num_phase2_types); - - return 0; -} - - -static int eap_peap_phase2_request(struct eap_sm *sm, - struct eap_peap_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct wpa_ssid *config = eap_get_config(sm); - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-PEAP: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1); - break; - case EAP_TYPE_TLV: - memset(&iret, 0, sizeof(iret)); - if (eap_tlv_process(sm, &iret, hdr, resp, resp_len)) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - if (iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) { - ret->methodState = iret.methodState; - ret->decision = iret.decision; - data->phase2_success = 1; - } - break; - default: - if (data->phase2_type == EAP_TYPE_NONE) { - int i; - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i] != *pos) - continue; - - data->phase2_type = *pos; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " - "Phase 2 EAP method %d", - data->phase2_type); - break; - } - } - if (*pos != data->phase2_type || *pos == EAP_TYPE_NONE) { - if (eap_peap_phase2_nak(sm, data, hdr, resp, resp_len)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_sm_get_eap_methods(*pos); - if (data->phase2_method) { - sm->init_phase2 = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize " - "Phase 2 EAP method %d", *pos); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return -1; - } - memset(&iret, 0, sizeof(iret)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, (u8 *) hdr, len, - resp_len); - if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC)) { - data->phase2_success = 1; - } - break; - } - - if (*resp == NULL && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp)) { - free(data->pending_phase2_req); - data->pending_phase2_req = malloc(len); - if (data->pending_phase2_req) { - memcpy(data->pending_phase2_req, hdr, len); - data->pending_phase2_req_len = len; - } - } - - return 0; -} - - -static int eap_peap_decrypt(struct eap_sm *sm, - struct eap_peap_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - u8 *in_decrypted; - int buf_len, len_decrypted, len, skip_change = 0, res; - struct eap_hdr *hdr, *rhdr; - u8 *resp = NULL; - size_t resp_len; - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - data->ssl.tls_in_left = 0; - data->ssl.tls_in_total = 0; - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - len_decrypted = data->pending_phase2_req_len; - skip_change = 1; - goto continue_req; - } - - res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len); - if (res < 0 || res == 1) - return res; - - if (in_len == 0 && sm->workaround && data->phase2_success) { - /* - * Cisco ACS seems to be using TLS ACK to terminate - * EAP-PEAPv0/GTC. Try to reply with TLS ACK. - */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " - "expected data - acknowledge with TLS ACK since " - "Phase 2 has been completed"); - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_DONE; - return 1; - } - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = malloc(buf_len); - if (in_decrypted == NULL) { - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory " - "for decryption"); - return -1; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " - "data"); - free(in_decrypted); - return 0; - } - -continue_req: - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted, - len_decrypted); - - hdr = (struct eap_hdr *) in_decrypted; - if (len_decrypted == 5 && hdr->code == EAP_CODE_REQUEST && - be_to_host16(hdr->length) == 5 && - in_decrypted[4] == EAP_TYPE_IDENTITY) { - /* At least FreeRADIUS seems to send full EAP header with - * EAP Request Identity */ - skip_change = 1; - } - if (len_decrypted >= 5 && hdr->code == EAP_CODE_REQUEST && - in_decrypted[4] == EAP_TYPE_TLV) { - skip_change = 1; - } - - if (data->peap_version == 0 && !skip_change) { - struct eap_hdr *nhdr = malloc(sizeof(struct eap_hdr) + - len_decrypted); - if (nhdr == NULL) { - free(in_decrypted); - return 0; - } - memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted); - free(in_decrypted); - nhdr->code = req->code; - nhdr->identifier = req->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - len_decrypted); - - len_decrypted += sizeof(struct eap_hdr); - in_decrypted = (u8 *) nhdr; - } - hdr = (struct eap_hdr *) in_decrypted; - if (len_decrypted < sizeof(*hdr)) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%d)", len_decrypted); - return 0; - } - len = be_to_host16(hdr->length); - if (len > len_decrypted) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%d hdr->length=%d)", - len_decrypted, len); - return 0; - } - if (len < len_decrypted) { - wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " - "shorter length than full decrypted data (%d < %d)", - len, len_decrypted); - if (sm->workaround && len == 4 && len_decrypted == 5 && - in_decrypted[4] == EAP_TYPE_IDENTITY) { - /* Radiator 3.9 seems to set Phase 2 EAP header to use - * incorrect length for the EAP-Request Identity - * packet, so fix the inner header to interoperate.. - * This was fixed in 2004-06-23 patch for Radiator and - * this workaround can be removed at some point. */ - wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace " - "Phase 2 EAP header len (%d) with real " - "decrypted len (%d)", len, len_decrypted); - len = len_decrypted; - hdr->length = host_to_be16(len); - } - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " - "identifier=%d length=%d", hdr->code, hdr->identifier, len); - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_peap_phase2_request(sm, data, ret, req, hdr, - &resp, &resp_len)) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request " - "processing failed"); - return 0; - } - break; - case EAP_CODE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success"); - if (data->peap_version == 1) { - /* EAP-Success within TLS tunnel is used to indicate - * shutdown of the TLS channel. The authentication has - * been completed. */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " - "EAP-Success within TLS tunnel - " - "authentication completed"); - ret->decision = DECISION_UNCOND_SUCC; - ret->methodState = METHOD_DONE; - data->phase2_success = 1; - if (data->peap_outer_success == 2) { - free(in_decrypted); - wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " - "to finish authentication"); - return 1; - } else if (data->peap_outer_success == 1) { - /* Reply with EAP-Success within the TLS - * channel to complete the authentication. */ - resp_len = sizeof(struct eap_hdr); - resp = malloc(resp_len); - if (resp) { - memset(resp, 0, resp_len); - rhdr = (struct eap_hdr *) resp; - rhdr->code = EAP_CODE_SUCCESS; - rhdr->identifier = hdr->identifier; - rhdr->length = host_to_be16(resp_len); - } - } else { - /* No EAP-Success expected for Phase 1 (outer, - * unencrypted auth), so force EAP state - * machine to SUCCESS state. */ - sm->peap_done = TRUE; - } - } else { - /* FIX: ? */ - } - break; - case EAP_CODE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_MAY_CONT; - ret->allowNotifications = FALSE; - /* Reply with EAP-Failure within the TLS channel to complete - * failure reporting. */ - resp_len = sizeof(struct eap_hdr); - resp = malloc(resp_len); - if (resp) { - memset(resp, 0, resp_len); - rhdr = (struct eap_hdr *) resp; - rhdr->code = EAP_CODE_FAILURE; - rhdr->identifier = hdr->identifier; - rhdr->length = host_to_be16(resp_len); - } - break; - default: - wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } - - free(in_decrypted); - - if (resp) { - u8 *resp_pos; - size_t resp_send_len; - int skip_change = 0; - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - resp, resp_len); - /* PEAP version changes */ - if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE && - resp[4] == EAP_TYPE_TLV) - skip_change = 1; - if (data->peap_version == 0 && !skip_change) { - resp_pos = resp + sizeof(struct eap_hdr); - resp_send_len = resp_len - sizeof(struct eap_hdr); - } else { - resp_pos = resp; - resp_send_len = resp_len; - } - - if (eap_peap_encrypt(sm, data, req->identifier, - resp_pos, resp_send_len, - out_data, out_len)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " - "a Phase 2 frame"); - } - free(resp); - } - - return 0; -} - - -static u8 * eap_peap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_hdr *req; - int left, res; - unsigned int tls_msg_len; - u8 flags, *pos, *resp, id; - struct eap_peap_data *data = priv; - - if (tls_get_errors(sm->ssl_ctx)) { - wpa_printf(MSG_INFO, "EAP-PEAP: TLS errors detected"); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 2 || *pos != EAP_TYPE_PEAP || - (left = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - left -= sizeof(struct eap_hdr); - id = req->identifier; - pos++; - flags = *pos++; - left -= 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) reqDataLen, flags); - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS " - "length"); - ret->ignore = TRUE; - return NULL; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " - "ver=%d)", flags & EAP_PEAP_VERSION_MASK, - data->peap_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version) - data->peap_version = flags & EAP_PEAP_VERSION_MASK; - if (data->force_peap_version >= 0 && - data->force_peap_version != data->peap_version) { - wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " - "forced PEAP version %d", - data->force_peap_version); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", - data->peap_version); - left = 0; /* make sure that this frame is empty, even though it - * should always be, anyway */ - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - res = eap_peap_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - } else { - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, id, pos, left, - &resp, respDataLen); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - char *label; - wpa_printf(MSG_DEBUG, - "EAP-PEAP: TLS done, proceed to Phase 2"); - free(data->key_data); - /* draft-josefsson-ppext-eap-tls-eap-05.txt - * specifies that PEAPv1 would use "client PEAP - * encryption" as the label. However, most existing - * PEAPv1 implementations seem to be using the old - * label, "client EAP encryption", instead. Use the old - * label by default, but allow it to be configured with - * phase1 parameter peaplabel=1. */ - if (data->peap_version > 1 || data->force_new_label) - label = "client PEAP encryption"; - else - label = "client EAP encryption"; - wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " - "key derivation", label); - data->key_data = - eap_tls_derive_key(sm, &data->ssl, label, - EAP_TLS_KEY_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, - "EAP-PEAP: Derived key", - data->key_data, - EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " - "derive key"); - } - - if (sm->workaround && data->peap_version == 1 && - data->resuming) { - /* - * At least one RADIUS server (Aegis v1.1.6; - * but not v1.1.4) seems to be terminating - * PEAPv1 session resumption with outer - * EAP-Success. This does not seem to follow - * draft-josefsson-pppext-eap-tls-eap-05.txt - * section 4.2, so only allow this if EAP - * workarounds are enabled. - */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " - "allow outer EAP-Success to " - "terminate PEAPv1 resumption"); - ret->decision = DECISION_COND_SUCC; - data->phase2_success = 1; - } - - data->resuming = 0; - } - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - if (res == 1) { - return eap_tls_build_ack(&data->ssl, respDataLen, id, - EAP_TYPE_PEAP, data->peap_version); - } - - return resp; -} - - -static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; -} - - -static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -} - - -static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - free(data->key_data); - data->key_data = NULL; - if (eap_tls_reauth_init(sm, &data->ssl)) { - free(data); - return NULL; - } - data->phase2_success = 0; - data->resuming = 1; - sm->peap_done = FALSE; - return priv; -} - - -static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_peap_data *data = priv; - int len; - - len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose); - if (data->phase2_method) { - len += snprintf(buf + len, buflen - len, - "EAP-PEAPv%d Phase2 method=%s\n", - data->peap_version, data->phase2_method->name); - } - return len; -} - - -static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_peap_data *data = priv; - return data->key_data != NULL && data->phase2_success; -} - - -static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_peap_data *data = priv; - u8 *key; - - if (data->key_data == NULL || !data->phase2_success) - return NULL; - - key = malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -const struct eap_method eap_method_peap = -{ - .method = EAP_TYPE_PEAP, - .name = "PEAP", - .init = eap_peap_init, - .deinit = eap_peap_deinit, - .process = eap_peap_process, - .isKeyAvailable = eap_peap_isKeyAvailable, - .getKey = eap_peap_getKey, - .get_status = eap_peap_get_status, - .has_reauth_data = eap_peap_has_reauth_data, - .deinit_for_reauth = eap_peap_deinit_for_reauth, - .init_for_reauth = eap_peap_init_for_reauth, -}; diff --git a/contrib/wpa_supplicant/eap_psk.c b/contrib/wpa_supplicant/eap_psk.c deleted file mode 100644 index 3b325b59dd91..000000000000 --- a/contrib/wpa_supplicant/eap_psk.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * WPA Supplicant / EAP-PSK (draft-bersani-eap-psk-05.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "md5.h" -#include "aes_wrap.h" - - -/* draft-bersani-eap-psk-03.txt mode. This is retained for interop testing and - * will be removed once an AS that supports draft5 becomes available. */ -#define EAP_PSK_DRAFT3 - -#define EAP_PSK_RAND_LEN 16 -#define EAP_PSK_MAC_LEN 16 -#define EAP_PSK_TEK_LEN 16 -#define EAP_PSK_MSK_LEN 64 - -#define EAP_PSK_R_FLAG_CONT 1 -#define EAP_PSK_R_FLAG_DONE_SUCCESS 2 -#define EAP_PSK_R_FLAG_DONE_FAILURE 3 - -/* EAP-PSK First Message (AS -> Supplicant) */ -struct eap_psk_hdr_1 { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ -#ifndef EAP_PSK_DRAFT3 - u8 flags; -#endif /* EAP_PSK_DRAFT3 */ - u8 rand_s[EAP_PSK_RAND_LEN]; -#ifndef EAP_PSK_DRAFT3 - /* Followed by variable length ID_S */ -#endif /* EAP_PSK_DRAFT3 */ -} __attribute__ ((packed)); - -/* EAP-PSK Second Message (Supplicant -> AS) */ -struct eap_psk_hdr_2 { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ -#ifndef EAP_PSK_DRAFT3 - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; -#endif /* EAP_PSK_DRAFT3 */ - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 mac_p[EAP_PSK_MAC_LEN]; - /* Followed by variable length ID_P */ -} __attribute__ ((packed)); - -/* EAP-PSK Third Message (AS -> Supplicant) */ -struct eap_psk_hdr_3 { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ -#ifndef EAP_PSK_DRAFT3 - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; -#endif /* EAP_PSK_DRAFT3 */ - u8 mac_s[EAP_PSK_MAC_LEN]; - /* Followed by variable length PCHANNEL */ -} __attribute__ ((packed)); - -/* EAP-PSK Fourth Message (Supplicant -> AS) */ -struct eap_psk_hdr_4 { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ -#ifndef EAP_PSK_DRAFT3 - u8 flags; - u8 rand_s[EAP_PSK_RAND_LEN]; -#endif /* EAP_PSK_DRAFT3 */ - /* Followed by variable length PCHANNEL */ -} __attribute__ ((packed)); - - - -struct eap_psk_data { - enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state; - u8 rand_s[EAP_PSK_RAND_LEN]; - u8 rand_p[EAP_PSK_RAND_LEN]; - u8 ak[16], kdk[16], tek[EAP_PSK_TEK_LEN]; - u8 *id_s, *id_p; - size_t id_s_len, id_p_len; - u8 key_data[EAP_PSK_MSK_LEN]; -}; - - -#define aes_block_size 16 - - -static void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk) -{ - memset(ak, 0, aes_block_size); - aes_128_encrypt_block(psk, ak, ak); - memcpy(kdk, ak, aes_block_size); - ak[aes_block_size - 1] ^= 0x01; - kdk[aes_block_size - 1] ^= 0x02; - aes_128_encrypt_block(psk, ak, ak); - aes_128_encrypt_block(psk, kdk, kdk); -} - - -static void eap_psk_derive_keys(const u8 *kdk, const u8 *rb, u8 *tek, u8 *msk) -{ - u8 hash[aes_block_size]; - u8 counter = 1; - int i; - - aes_128_encrypt_block(kdk, rb, hash); - - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, tek); - hash[aes_block_size - 1] ^= counter; - counter++; - - for (i = 0; i < EAP_PSK_MSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]); - hash[aes_block_size - 1] ^= counter; - counter++; - } -} - - -static void * eap_psk_init(struct eap_sm *sm) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_psk_data *data; - - if (config == NULL || !config->eappsk) { - wpa_printf(MSG_INFO, "EAP-PSK: pre-shared key not configured"); - return NULL; - } - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - eap_psk_key_setup(config->eappsk, data->ak, data->kdk); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, 16); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, 16); - data->state = PSK_INIT; - - if (config->nai) { - data->id_p = malloc(config->nai_len); - if (data->id_p) - memcpy(data->id_p, config->nai, config->nai_len); - data->id_p_len = config->nai_len; - } - if (data->id_p == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity"); - free(data); - return NULL; - } - -#ifdef EAP_PSK_DRAFT3 - if (config->server_nai) { - data->id_s = malloc(config->server_nai_len); - if (data->id_s) - memcpy(data->id_s, config->server_nai, - config->server_nai_len); - data->id_s_len = config->server_nai_len; - } - if (data->id_s == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: could not get server identity"); - free(data->id_p); - free(data); - return NULL; - } -#endif /* EAP_PSK_DRAFT3 */ - - return data; -} - - -static void eap_psk_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - free(data->id_s); - free(data->id_p); - free(data); -} - - -static u8 * eap_psk_process_1(struct eap_sm *sm, struct eap_psk_data *data, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_psk_hdr_1 *hdr1; - struct eap_psk_hdr_2 *hdr2; - u8 *resp, *buf, *pos; - size_t buflen; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); - - hdr1 = (struct eap_psk_hdr_1 *) reqData; - if (reqDataLen < sizeof(*hdr1) || - be_to_host16(hdr1->length) < sizeof(*hdr1) || - be_to_host16(hdr1->length) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " - "length (%lu %d; expected %lu or more)", - (unsigned long) reqDataLen, - be_to_host16(hdr1->length), - (unsigned long) sizeof(*hdr1)); - ret->ignore = TRUE; - return NULL; - } -#ifndef EAP_PSK_DRAFT3 - wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); - if ((hdr1->flags & 0x03) != 0) { - wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)", - hdr1->flags & 0x03); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } -#endif /* EAP_PSK_DRAFT3 */ - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s, - EAP_PSK_RAND_LEN); - memcpy(data->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); -#ifndef EAP_PSK_DRAFT3 - free(data->id_s); - data->id_s_len = be_to_host16(hdr1->length) - sizeof(*hdr1); - data->id_s = malloc(data->id_s_len); - if (data->id_s == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " - "ID_S (len=%d)", data->id_s_len); - ret->ignore = TRUE; - return NULL; - } - memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", - data->id_s, data->id_s_len); -#endif /* EAP_PSK_DRAFT3 */ - - if (hostapd_get_rand(data->rand_p, EAP_PSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - ret->ignore = TRUE; - return NULL; - } - - *respDataLen = sizeof(*hdr2) + data->id_p_len; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - hdr2 = (struct eap_psk_hdr_2 *) resp; - hdr2->code = EAP_CODE_RESPONSE; - hdr2->identifier = hdr1->identifier; - hdr2->length = host_to_be16(*respDataLen); - hdr2->type = EAP_TYPE_PSK; -#ifndef EAP_PSK_DRAFT3 - hdr2->flags = 1; /* T=1 */ - memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN); -#endif /* EAP_PSK_DRAFT3 */ - memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN); - memcpy((u8 *) (hdr2 + 1), data->id_p, data->id_p_len); - /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ - buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; - buf = malloc(buflen); - if (buf == NULL) { - free(resp); - return NULL; - } - memcpy(buf, data->id_p, data->id_p_len); - pos = buf + data->id_p_len; - memcpy(pos, data->id_s, data->id_s_len); - pos += data->id_s_len; - memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); - pos += EAP_PSK_RAND_LEN; - memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); - omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p); - free(buf); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p, - EAP_PSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P", - (u8 *) (hdr2 + 1), data->id_p_len); - - data->state = PSK_MAC_SENT; - - return resp; -} - - -static u8 * eap_psk_process_3(struct eap_sm *sm, struct eap_psk_data *data, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_psk_hdr_3 *hdr3; - struct eap_psk_hdr_4 *hdr4; - u8 *resp, *buf, *pchannel, *tag, *msg, nonce[16]; - u8 mac[EAP_PSK_MAC_LEN]; - size_t buflen, left; - int failed = 0; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); - - hdr3 = (struct eap_psk_hdr_3 *) reqData; - left = be_to_host16(hdr3->length); - if (left < sizeof(*hdr3) || reqDataLen < left) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " - "length (%lu %d; expected %lu)", - (unsigned long) reqDataLen, - be_to_host16(hdr3->length), - (unsigned long) sizeof(*hdr3)); - ret->ignore = TRUE; - return NULL; - } - left -= sizeof(*hdr3); - pchannel = (u8 *) (hdr3 + 1); -#ifndef EAP_PSK_DRAFT3 - wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags); - if ((hdr3->flags & 0x03) != 2) { - wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)", - hdr3->flags & 0x03); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s, - EAP_PSK_RAND_LEN); - /* TODO: would not need to store RAND_S since it is available in this - * message. For now, since we store this anyway, verify that it matches - * with whatever the server is sending. */ - if (memcmp(hdr3->rand_s, data->rand_s, EAP_PSK_RAND_LEN) != 0) { - wpa_printf(MSG_ERROR, "EAP-PSK: RAND_S did not match"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } -#endif /* EAP_PSK_DRAFT3 */ - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left); - - if (left < 4 + 16 + 1) { - wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " - "third message (len=%lu, expected 21)", - (unsigned long) left); - ret->ignore = TRUE; - return NULL; - } - - /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ - buflen = data->id_s_len + EAP_PSK_RAND_LEN; - buf = malloc(buflen); - if (buf == NULL) - return NULL; - memcpy(buf, data->id_s, data->id_s_len); - memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); - omac1_aes_128(data->ak, buf, buflen, mac); - free(buf); - if (memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) { - wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third " - "message"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully"); - - eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, - data->key_data); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->key_data, - EAP_PSK_MSK_LEN); - - memset(nonce, 0, 12); - memcpy(nonce + 12, pchannel, 4); - pchannel += 4; - left -= 4; - - tag = pchannel; - pchannel += 16; - left -= 16; - - msg = pchannel; - - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce", - nonce, sizeof(nonce)); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr", reqData, 5); - wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left); - -#ifdef EAP_PSK_DRAFT3 - if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), - reqData, 5, msg, left, tag)) -#else /* EAP_PSK_DRAFT3 */ - if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), - reqData, 22, msg, left, tag)) -#endif /* EAP_PSK_DRAFT3 */ - { - wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", - msg, left); - - /* Verify R flag */ - switch (msg[0] >> 6) { - case EAP_PSK_R_FLAG_CONT: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); - return NULL; - case EAP_PSK_R_FLAG_DONE_SUCCESS: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); - break; - case EAP_PSK_R_FLAG_DONE_FAILURE: - wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); - wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected " - "authentication"); - failed = 1; - break; - } - - *respDataLen = sizeof(*hdr4) + 4 + 16 + 1; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - hdr4 = (struct eap_psk_hdr_4 *) resp; - hdr4->code = EAP_CODE_RESPONSE; - hdr4->identifier = hdr3->identifier; - hdr4->length = host_to_be16(*respDataLen); - hdr4->type = EAP_TYPE_PSK; -#ifndef EAP_PSK_DRAFT3 - hdr4->flags = 3; /* T=3 */ - memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); -#endif /* EAP_PSK_DRAFT3 */ - pchannel = (u8 *) (hdr4 + 1); - - /* nonce++ */ - inc_byte_array(nonce, sizeof(nonce)); - memcpy(pchannel, nonce + 12, 4); - - pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; - - wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)", - pchannel + 4 + 16, 1); -#ifdef EAP_PSK_DRAFT3 - aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 5, - pchannel + 4 + 16, 1, pchannel + 4); -#else /* EAP_PSK_DRAFT3 */ - aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 22, - pchannel + 4 + 16, 1, pchannel + 4); -#endif /* EAP_PSK_DRAFT3 */ - wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)", - pchannel, 4 + 16 + 1); - - wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully", - failed ? "un" : ""); - data->state = PSK_DONE; - ret->methodState = METHOD_DONE; - ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC; - - return resp; -} - - -static u8 * eap_psk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_psk_data *data = priv; - struct eap_hdr *req; - u8 *pos, *resp = NULL; - size_t len; - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 1 || *pos != EAP_TYPE_PSK || - (len = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - switch (data->state) { - case PSK_INIT: - resp = eap_psk_process_1(sm, data, ret, reqData, len, - respDataLen); - break; - case PSK_MAC_SENT: - resp = eap_psk_process_3(sm, data, ret, reqData, len, - respDataLen); - break; - case PSK_DONE: - wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " - "unexpected message"); - ret->ignore = TRUE; - return NULL; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return resp; -} - - -static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_psk_data *data = priv; - return data->state == PSK_DONE; -} - - -static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_psk_data *data = priv; - u8 *key; - - if (data->state != PSK_DONE) - return NULL; - - key = malloc(EAP_PSK_MSK_LEN); - if (key == NULL) - return NULL; - - *len = EAP_PSK_MSK_LEN; - memcpy(key, data->key_data, EAP_PSK_MSK_LEN); - - return key; -} - - -const struct eap_method eap_method_psk = -{ - .method = EAP_TYPE_PSK, - .name = "PSK", - .init = eap_psk_init, - .deinit = eap_psk_deinit, - .process = eap_psk_process, - .isKeyAvailable = eap_psk_isKeyAvailable, - .getKey = eap_psk_getKey, -}; diff --git a/contrib/wpa_supplicant/eap_sim.c b/contrib/wpa_supplicant/eap_sim.c deleted file mode 100644 index f7ce191a6dda..000000000000 --- a/contrib/wpa_supplicant/eap_sim.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * WPA Supplicant / EAP-SIM (draft-haverinen-pppext-eap-sim-13.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "sha1.h" -#include "pcsc_funcs.h" -#include "eap_sim_common.h" - -#define EAP_SIM_VERSION 1 - -/* EAP-SIM Subtypes */ -#define EAP_SIM_SUBTYPE_START 10 -#define EAP_SIM_SUBTYPE_CHALLENGE 11 -#define EAP_SIM_SUBTYPE_NOTIFICATION 12 -#define EAP_SIM_SUBTYPE_REAUTHENTICATION 13 -#define EAP_SIM_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_SIM_UNABLE_TO_PROCESS_PACKET 0 -#define EAP_SIM_UNSUPPORTED_VERSION 1 -#define EAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2 -#define EAP_SIM_RAND_NOT_FRESH 3 - -#define KC_LEN 8 -#define SRES_LEN 4 -#define EAP_SIM_MAX_FAST_REAUTHS 1000 - -struct eap_sim_data { - u8 *ver_list; - size_t ver_list_len; - int selected_version; - int min_num_chal, num_chal; - - u8 kc[3][KC_LEN]; - u8 sres[3][SRES_LEN]; - u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN]; - u8 mk[EAP_SIM_MK_LEN]; - u8 k_aut[EAP_SIM_K_AUT_LEN]; - u8 k_encr[EAP_SIM_K_ENCR_LEN]; - u8 msk[EAP_SIM_KEYING_DATA_LEN]; - u8 rand[3][GSM_RAND_LEN]; - - int num_id_req, num_notification; - u8 *pseudonym; - size_t pseudonym_len; - u8 *reauth_id; - size_t reauth_id_len; - int reauth; - unsigned int counter, counter_too_small; - u8 *last_eap_identity; - size_t last_eap_identity_len; - enum { CONTINUE, SUCCESS, FAILURE } state; -}; - - -static void * eap_sim_init(struct eap_sm *sm) -{ - struct eap_sim_data *data; - struct wpa_ssid *config = eap_get_config(sm); - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - - if (hostapd_get_rand(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " - "for NONCE_MT"); - free(data); - return NULL; - } - - data->min_num_chal = 2; - if (config && config->phase1) { - char *pos = strstr(config->phase1, "sim_min_num_chal="); - if (pos) { - data->min_num_chal = atoi(pos + 17); - if (data->min_num_chal < 2 || data->min_num_chal > 3) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " - "sim_min_num_chal configuration " - "(%d, expected 2 or 3)", - data->min_num_chal); - free(data); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of " - "challenges to %d", data->min_num_chal); - } - } - - data->state = CONTINUE; - - return data; -} - - -static void eap_sim_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (data) { - free(data->ver_list); - free(data->pseudonym); - free(data->reauth_id); - free(data->last_eap_identity); - free(data); - } -} - - -static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm"); -#ifdef PCSC_FUNCS - if (scard_gsm_auth(sm->scard_ctx, data->rand[0], - data->sres[0], data->kc[0]) || - scard_gsm_auth(sm->scard_ctx, data->rand[1], - data->sres[1], data->kc[1]) || - (data->num_chal > 2 && - scard_gsm_auth(sm->scard_ctx, data->rand[2], - data->sres[2], data->kc[2]))) { - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM authentication could " - "not be completed"); - return -1; - } -#else /* PCSC_FUNCS */ - /* These hardcoded Kc and SRES values are used for testing. RAND to - * KC/SREC mapping is very bogus as far as real authentication is - * concerned, but it is quite useful for cases where the AS is rotating - * the order of pre-configured values. */ - { - int i; - for (i = 0; i < data->num_chal; i++) { - if (data->rand[i][0] == 0xaa) { - memcpy(data->kc[i], - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", - KC_LEN); - memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", - SRES_LEN); - } else if (data->rand[i][0] == 0xbb) { - memcpy(data->kc[i], - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", - KC_LEN); - memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", - SRES_LEN); - } else { - memcpy(data->kc[i], - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", - KC_LEN); - memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", - SRES_LEN); - } - } - } -#endif /* PCSC_FUNCS */ - return 0; -} - - -static int eap_sim_supported_ver(struct eap_sim_data *data, int version) -{ - return version == EAP_SIM_VERSION; -} - - -static void eap_sim_derive_mk(struct eap_sim_data *data, - const u8 *identity, size_t identity_len) -{ - u8 sel_ver[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = (u8 *) data->kc; - len[1] = data->num_chal * KC_LEN; - addr[2] = data->nonce_mt; - len[2] = EAP_SIM_NONCE_MT_LEN; - addr[3] = data->ver_list; - len[3] = data->ver_list_len; - addr[4] = sel_ver; - len[4] = 2; - - sel_ver[0] = data->selected_version >> 8; - sel_ver[1] = data->selected_version & 0xff; - - /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ - sha1_vector(5, addr, len, data->mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", data->mk, EAP_SIM_MK_LEN); -} - - -#define CLEAR_PSEUDONYM 0x01 -#define CLEAR_REAUTH_ID 0x02 -#define CLEAR_EAP_ID 0x04 - -static void eap_sim_clear_identities(struct eap_sim_data *data, int id) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: forgetting old%s%s%s", - id & CLEAR_PSEUDONYM ? " pseudonym" : "", - id & CLEAR_REAUTH_ID ? " reauth_id" : "", - id & CLEAR_EAP_ID ? " eap_id" : ""); - if (id & CLEAR_PSEUDONYM) { - free(data->pseudonym); - data->pseudonym = NULL; - data->pseudonym_len = 0; - } - if (id & CLEAR_REAUTH_ID) { - free(data->reauth_id); - data->reauth_id = NULL; - data->reauth_id_len = 0; - } - if (id & CLEAR_EAP_ID) { - free(data->last_eap_identity); - data->last_eap_identity = NULL; - data->last_eap_identity_len = 0; - } -} - - -static int eap_sim_learn_ids(struct eap_sim_data *data, - struct eap_sim_attrs *attr) -{ - if (attr->next_pseudonym) { - free(data->pseudonym); - data->pseudonym = malloc(attr->next_pseudonym_len); - if (data->pseudonym == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " - "next pseudonym"); - return -1; - } - memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); - data->pseudonym_len = attr->next_pseudonym_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", - data->pseudonym, - data->pseudonym_len); - } - - if (attr->next_reauth_id) { - free(data->reauth_id); - data->reauth_id = malloc(attr->next_reauth_id_len); - if (data->reauth_id == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " - "next reauth_id"); - return -1; - } - memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); - data->reauth_id_len = attr->next_reauth_id_len; - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-SIM: (encr) AT_NEXT_REAUTH_ID", - data->reauth_id, - data->reauth_id_len); - } - - return 0; -} - - -static u8 * eap_sim_client_error(struct eap_sm *sm, struct eap_sim_data *data, - struct eap_hdr *req, - size_t *respDataLen, int err) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CLIENT_ERROR); - eap_sim_msg_add(msg, EAP_SIM_AT_CLIENT_ERROR_CODE, err, NULL, 0); - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_sim_response_start(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, - size_t *respDataLen, - enum eap_sim_id_req id_req) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *identity = NULL; - size_t identity_len = 0; - struct eap_sim_msg *msg; - - data->reauth = 0; - if (id_req == ANY_ID && data->reauth_id) { - identity = data->reauth_id; - identity_len = data->reauth_id_len; - data->reauth = 1; - } else if ((id_req == ANY_ID || id_req == FULLAUTH_ID) && - data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - eap_sim_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ && config && config->identity) { - identity = config->identity; - identity_len = config->identity_len; - eap_sim_clear_identities(data, - CLEAR_PSEUDONYM | CLEAR_REAUTH_ID); - } - if (id_req != NO_ID_REQ) - eap_sim_clear_identities(data, CLEAR_EAP_ID); - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); - wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", - data->selected_version); - eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, - data->selected_version, NULL, 0); - - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_sim_response_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, - (u8 *) data->sres, - data->num_chal * SRES_LEN); -} - - -static u8 * eap_sim_response_reauth(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, - size_t *respDataLen, int counter_too_small) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, - EAP_SIM_SUBTYPE_REAUTHENTICATION); - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, EAP_SIM_AT_ENCR_DATA); - - if (counter_too_small) { - wpa_printf(MSG_DEBUG, " *AT_COUNTER_TOO_SMALL"); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER_TOO_SMALL, 0, NULL, 0); - counter = data->counter_too_small; - } else - counter = data->counter; - - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, counter, NULL, 0); - - if (eap_sim_msg_add_encr_end(msg, data->k_encr, EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, data->nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static u8 * eap_sim_response_notification(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, - size_t *respDataLen, - u16 notification) -{ - struct eap_sim_msg *msg; - u8 *k_aut = (notification & 0x4000) == 0 ? data->k_aut : NULL; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Notification (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION"); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0); - if (k_aut && data->reauth) { - wpa_printf(MSG_DEBUG, " AT_IV"); - wpa_printf(MSG_DEBUG, " AT_ENCR_DATA"); - eap_sim_msg_add_encr_start(msg, EAP_SIM_AT_IV, - EAP_SIM_AT_ENCR_DATA); - wpa_printf(MSG_DEBUG, " *AT_COUNTER %d", data->counter); - eap_sim_msg_add(msg, EAP_SIM_AT_COUNTER, data->counter, - NULL, 0); - if (eap_sim_msg_add_encr_end(msg, data->k_encr, - EAP_SIM_AT_PADDING)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to encrypt " - "AT_ENCR_DATA"); - eap_sim_msg_free(msg); - return NULL; - } - } - if (k_aut) { - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - } - return eap_sim_msg_finish(msg, respDataLen, k_aut, (u8 *) "", 0); -} - - -static u8 * eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data, - struct eap_hdr *req, size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - int i, selected_version = -1, id_error; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start"); - if (attr->version_list == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in " - "SIM/Start"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNSUPPORTED_VERSION); - } - - free(data->ver_list); - data->ver_list = malloc(attr->version_list_len); - if (data->ver_list == NULL) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate " - "memory for version list"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - memcpy(data->ver_list, attr->version_list, attr->version_list_len); - data->ver_list_len = attr->version_list_len; - pos = data->ver_list; - for (i = 0; i < data->ver_list_len / 2; i++) { - int ver = pos[0] * 256 + pos[1]; - pos += 2; - if (eap_sim_supported_ver(data, ver)) { - selected_version = ver; - break; - } - } - if (selected_version < 0) { - wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported " - "version"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNSUPPORTED_VERSION); - } - wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d", - selected_version); - data->selected_version = selected_version; - - id_error = 0; - switch (attr->id_req) { - case NO_ID_REQ: - break; - case ANY_ID: - if (data->num_id_req > 0) - id_error++; - data->num_id_req++; - break; - case FULLAUTH_ID: - if (data->num_id_req > 1) - id_error++; - data->num_id_req++; - break; - case PERMANENT_ID: - if (data->num_id_req > 2) - id_error++; - data->num_id_req++; - break; - } - if (id_error) { - wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests " - "used within one authentication"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - return eap_sim_response_start(sm, data, req, respDataLen, - attr->id_req); -} - - -static u8 * eap_sim_process_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *identity; - size_t identity_len; - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Challenge"); - data->reauth = 0; - if (!attr->mac || !attr->rand) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "did not include%s%s", - !attr->mac ? " AT_MAC" : "", - !attr->rand ? " AT_RAND" : ""); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: %lu challenges", - (unsigned long) attr->num_chal); - if (attr->num_chal < data->min_num_chal) { - wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of " - "challenges (%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_INSUFFICIENT_NUM_OF_CHAL); - } - if (attr->num_chal > 3) { - wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges " - "(%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - /* Verify that RANDs are different */ - if (memcmp(attr->rand, attr->rand + GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - (attr->num_chal > 2 && - (memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - memcmp(attr->rand + GSM_RAND_LEN, - attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0))) { - wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_RAND_NOT_FRESH); - } - - memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); - data->num_chal = attr->num_chal; - - if (eap_sim_gsm_auth(sm, data)) { - wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - if (data->last_eap_identity) { - identity = data->last_eap_identity; - identity_len = data->last_eap_identity_len; - } else if (data->pseudonym) { - identity = data->pseudonym; - identity_len = data->pseudonym_len; - } else { - identity = config->identity; - identity_len = config->identity_len; - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK " - "derivation", identity, identity_len); - eap_sim_derive_mk(data, identity, identity_len); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk); - if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac, - data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " - "used invalid AT_MAC"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - /* Old reauthentication and pseudonym identities must not be used - * anymore. In other words, if no new identities are received, full - * authentication will be used on next reauthentication. */ - eap_sim_clear_identities(data, CLEAR_PSEUDONYM | CLEAR_REAUTH_ID | - CLEAR_EAP_ID); - - if (attr->encr_data) { - if (eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, - 0)) { - return eap_sim_client_error( - sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - eap_sim_learn_ids(data, &eattr); - } - - if (data->state != FAILURE) - data->state = SUCCESS; - - data->num_id_req = 0; - data->num_notification = 0; - /* draft-haverinen-pppext-eap-sim-13.txt specifies that counter - * is initialized to one after fullauth, but initializing it to - * zero makes it easier to implement reauth verification. */ - data->counter = 0; - return eap_sim_response_challenge(sm, data, req, respDataLen); -} - - -static int eap_sim_process_notification_reauth(struct eap_sim_data *data, - struct eap_hdr *req, - size_t reqDataLen, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Notification message after " - "reauth did not include encrypted data"); - return -1; - } - - if (eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, 0)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from notification message"); - return -1; - } - - if (eattr.counter != data->counter) { - wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification " - "message does not match with counter in reauth " - "message"); - return -1; - } - - return 0; -} - - -static int eap_sim_process_notification_auth(struct eap_sim_data *data, - struct eap_hdr *req, - size_t reqDataLen, - struct eap_sim_attrs *attr) -{ - if (attr->mac == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: no AT_MAC in after_auth " - "Notification message"); - return -1; - } - - if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, attr->mac, - (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Notification message " - "used invalid AT_MAC"); - return -1; - } - - if (data->reauth && - eap_sim_process_notification_reauth(data, req, reqDataLen, attr)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification " - "message after reauth"); - return -1; - } - - return 0; -} - - -static u8 * eap_sim_process_notification(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Notification"); - if (data->num_notification > 0) { - wpa_printf(MSG_INFO, "EAP-SIM: too many notification " - "rounds (only one allowed)"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - data->num_notification++; - if (attr->notification == -1) { - wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in " - "Notification message"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_sim_process_notification_auth(data, req, reqDataLen, attr)) { - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 0); - if (attr->notification >= 0 && attr->notification < 32768) { - data->state = FAILURE; - } - return eap_sim_response_notification(sm, data, req, respDataLen, - attr->notification); -} - - -static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, - struct eap_sim_data *data, - struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Reauthentication"); - - if (data->reauth_id == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " - "reauthentication, but no reauth_id available"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_sim_verify_mac(data->k_aut, (u8 *) req, reqDataLen, - attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "did not have valid AT_MAC"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (attr->encr_data == NULL || attr->iv == NULL) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "message did not include encrypted data"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eap_sim_parse_encr(data->k_encr, attr->encr_data, - attr->encr_data_len, attr->iv, &eattr, 0)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " - "data from reauthentication message"); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.nonce_s == NULL || eattr.counter < 0) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", - !eattr.nonce_s ? " AT_NONCE_S" : "", - eattr.counter < 0 ? " AT_COUNTER" : ""); - return eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter <= data->counter) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - /* Reply using Re-auth w/ AT_COUNTER_TOO_SMALL. The current - * reauth_id must not be used to start a new reauthentication. - * However, since it was used in the last EAP-Response-Identity - * packet, it has to saved for the following fullauth to be - * used in MK derivation. */ - free(data->last_eap_identity); - data->last_eap_identity = data->reauth_id; - data->last_eap_identity_len = data->reauth_id_len; - data->reauth_id = NULL; - data->reauth_id_len = 0; - return eap_sim_response_reauth(sm, data, req, respDataLen, 1); - } - data->counter = eattr.counter; - - memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", - data->nonce_s, EAP_SIM_NONCE_S_LEN); - - eap_sim_derive_keys_reauth(data->counter, - data->reauth_id, data->reauth_id_len, - data->nonce_s, data->mk, data->msk); - eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - eap_sim_learn_ids(data, &eattr); - - if (data->state != FAILURE) - data->state = SUCCESS; - - data->num_id_req = 0; - data->num_notification = 0; - if (data->counter > EAP_SIM_MAX_FAST_REAUTHS) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Maximum number of " - "fast reauths performed - force fullauth"); - eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); - } - return eap_sim_response_reauth(sm, data, req, respDataLen, 0); -} - - -static u8 * eap_sim_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_sim_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *req; - u8 *pos, subtype, *res; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump(MSG_DEBUG, "EAP-SIM: EAP data", reqData, reqDataLen); - if (config == NULL || config->identity == NULL) { - wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); - eap_sm_request_identity(sm, config); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_SIM || - (len = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - pos++; - subtype = *pos++; - wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); - pos += 2; /* Reserved */ - - if (eap_sim_parse_attr(pos, reqData + len, &attr, 0, 0)) { - res = eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_SIM_SUBTYPE_START: - res = eap_sim_process_start(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_CHALLENGE: - res = eap_sim_process_challenge(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_NOTIFICATION: - res = eap_sim_process_notification(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_REAUTHENTICATION: - res = eap_sim_process_reauthentication(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); - res = eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); - res = eap_sim_client_error(sm, data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - } - -done: - if (data->state == FAILURE) { - ret->decision = DECISION_FAIL; - ret->methodState = METHOD_DONE; - } else if (data->state == SUCCESS) { - ret->decision = DECISION_UNCOND_SUCC; - ret->methodState = METHOD_DONE; - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - return res; -} - - -static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->pseudonym || data->reauth_id; -} - - -static void eap_sim_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - eap_sim_clear_identities(data, CLEAR_EAP_ID); -} - - -static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (hostapd_get_rand(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " - "for NONCE_MT"); - free(data); - return NULL; - } - data->num_id_req = 0; - data->num_notification = 0; - data->state = CONTINUE; - return priv; -} - - -static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, - size_t *len) -{ - struct eap_sim_data *data = priv; - - if (data->reauth_id) { - *len = data->reauth_id_len; - return data->reauth_id; - } - - if (data->pseudonym) { - *len = data->pseudonym_len; - return data->pseudonym; - } - - return NULL; -} - - -static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - return data->state == SUCCESS; -} - - -static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_sim_data *data = priv; - u8 *key; - - if (data->state != SUCCESS) - return NULL; - - key = malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - - *len = EAP_SIM_KEYING_DATA_LEN; - memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); - - return key; -} - - -const struct eap_method eap_method_sim = -{ - .method = EAP_TYPE_SIM, - .name = "SIM", - .init = eap_sim_init, - .deinit = eap_sim_deinit, - .process = eap_sim_process, - .isKeyAvailable = eap_sim_isKeyAvailable, - .getKey = eap_sim_getKey, - .has_reauth_data = eap_sim_has_reauth_data, - .deinit_for_reauth = eap_sim_deinit_for_reauth, - .init_for_reauth = eap_sim_init_for_reauth, - .get_identity = eap_sim_get_identity, -}; diff --git a/contrib/wpa_supplicant/eap_sim_common.c b/contrib/wpa_supplicant/eap_sim_common.c deleted file mode 100644 index 98f4fb7d3014..000000000000 --- a/contrib/wpa_supplicant/eap_sim_common.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * WPA Supplicant / EAP-SIM/AKA shared routines - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "sha1.h" -#include "aes_wrap.h" -#include "eap_sim_common.h" - - -#define MSK_LEN 8 -#define EMSK_LEN 8 - - -static void eap_sim_prf(const u8 *key, u8 *x, size_t xlen) -{ - u8 xkey[64]; - u32 t[5], _t[5]; - int i, j, m, k; - u8 *xpos = x; - u32 carry; - - /* FIPS 186-2 + change notice 1 */ - - memcpy(xkey, key, EAP_SIM_MK_LEN); - memset(xkey + EAP_SIM_MK_LEN, 0, 64 - EAP_SIM_MK_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) */ - 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]); - 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 */ - } -} - - -void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk) -{ - u8 buf[120], *pos; - eap_sim_prf(mk, buf, 120); - pos = buf; - memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN); - pos += EAP_SIM_K_ENCR_LEN; - memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN); - pos += EAP_SIM_K_AUT_LEN; - memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN); - pos += MSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr", - k_encr, EAP_SIM_K_ENCR_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut", - k_aut, EAP_SIM_K_ENCR_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MSK", - msk, MSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Ext. MSK", - msk + MSK_LEN, EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material", - msk, EAP_SIM_KEYING_DATA_LEN); -} - - -void eap_sim_derive_keys_reauth(unsigned int _counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, const u8 *mk, u8 *msk) -{ - u8 xkey[SHA1_MAC_LEN]; - u8 counter[2]; - const u8 *addr[4]; - size_t len[4]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = counter; - len[1] = 2; - addr[2] = nonce_s; - len[2] = EAP_SIM_NONCE_S_LEN; - addr[3] = mk; - len[3] = EAP_SIM_MK_LEN; - - counter[0] = _counter >> 8; - counter[1] = _counter & 0xff; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth"); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity", - identity, identity_len); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: counter", counter, 2); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: NONCE_S", nonce_s, - EAP_SIM_NONCE_S_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN); - - /* XKEY' = SHA1(Identity|counter|NONCE_S|MK) */ - sha1_vector(4, addr, len, xkey); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN); - - eap_sim_prf(xkey, msk, EAP_SIM_KEYING_DATA_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: MSK", msk, MSK_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: Ext. MSK", msk + MSK_LEN, EMSK_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material", - msk, EAP_SIM_KEYING_DATA_LEN); -} - - -int eap_sim_verify_mac(const u8 *k_aut, u8 *req, size_t req_len, u8 *mac, - u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA1_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - u8 rx_mac[EAP_SIM_MAC_LEN]; - - if (mac == NULL) - return -1; - - addr[0] = req; - len[0] = req_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - memcpy(rx_mac, mac, EAP_SIM_MAC_LEN); - memset(mac, 0, EAP_SIM_MAC_LEN); - hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); - memcpy(mac, rx_mac, EAP_SIM_MAC_LEN); - - return (memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1; -} - - -void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len) -{ - unsigned char hmac[SHA1_MAC_LEN]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = msg; - len[0] = msg_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - memset(mac, 0, EAP_SIM_MAC_LEN); - hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac); - memcpy(mac, hmac, EAP_SIM_MAC_LEN); -} - - -int eap_sim_parse_attr(u8 *start, u8 *end, struct eap_sim_attrs *attr, int aka, - int encr) -{ - u8 *pos = start, *apos; - size_t alen, plen; - int list_len, i; - - memset(attr, 0, sizeof(*attr)); - attr->id_req = NO_ID_REQ; - attr->notification = -1; - attr->counter = -1; - attr->selected_version = -1; - attr->client_error_code = -1; - - while (pos < end) { - if (pos + 2 > end) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow(1)"); - return -1; - } - wpa_printf(MSG_MSGDUMP, "EAP-SIM: Attribute: Type=%d Len=%d", - pos[0], pos[1] * 4); - if (pos + pos[1] * 4 > end) { - wpa_printf(MSG_INFO, "EAP-SIM: Attribute overflow " - "(pos=%p len=%d end=%p)", - pos, pos[1] * 4, end); - return -1; - } - apos = pos + 2; - alen = pos[1] * 4 - 2; - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data", - apos, alen); - - switch (pos[0]) { - case EAP_SIM_AT_RAND: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RAND"); - apos += 2; - alen -= 2; - if ((!aka && (alen % GSM_RAND_LEN)) || - (aka && alen != AKA_RAND_LEN)) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->rand = apos; - attr->num_chal = alen / GSM_RAND_LEN; - break; - case EAP_SIM_AT_AUTN: - wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTN"); - if (!aka) { - wpa_printf(MSG_DEBUG, "EAP-SIM: " - "Unexpected AT_AUTN"); - return -1; - } - apos += 2; - alen -= 2; - if (alen != AKA_AUTN_LEN) { - wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN" - " (len %lu)", - (unsigned long) alen); - return -1; - } - attr->autn = apos; - break; - case EAP_SIM_AT_PADDING: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_PADDING"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_PADDING"); - for (i = 2; i < alen; i++) { - if (apos[i] != 0) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) " - "AT_PADDING used a non-zero" - " padding byte"); - wpa_hexdump(MSG_DEBUG, "EAP-SIM: " - "(encr) padding bytes", - apos + 2, alen - 2); - return -1; - } - } - break; - case EAP_SIM_AT_NONCE_MT: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NONCE_MT"); - if (alen != 2 + EAP_SIM_NONCE_MT_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_NONCE_MT length"); - return -1; - } - attr->nonce_mt = apos + 2; - break; - case EAP_SIM_AT_PERMANENT_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_PERMANENT_ID_REQ"); - attr->id_req = PERMANENT_ID; - break; - case EAP_SIM_AT_MAC: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_MAC"); - if (alen != 2 + EAP_SIM_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_MAC " - "length"); - return -1; - } - attr->mac = apos + 2; - break; - case EAP_SIM_AT_NOTIFICATION: - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_NOTIFICATION length %lu", - (unsigned long) alen); - return -1; - } - attr->notification = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_NOTIFICATION %d", - attr->notification); - break; - case EAP_SIM_AT_ANY_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ANY_ID_REQ"); - attr->id_req = ANY_ID; - break; - case EAP_SIM_AT_IDENTITY: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IDENTITY"); - attr->identity = apos + 2; - attr->identity_len = alen - 2; - break; - case EAP_SIM_AT_VERSION_LIST: - if (aka) { - wpa_printf(MSG_DEBUG, "EAP-AKA: " - "Unexpected AT_VERSION_LIST"); - return -1; - } - list_len = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST"); - if (list_len < 2 || list_len > alen - 2) { - wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " - "AT_VERSION_LIST (list_len=%d " - "attr_len=%lu)", list_len, - (unsigned long) alen); - return -1; - } - attr->version_list = apos + 2; - attr->version_list_len = list_len; - break; - case EAP_SIM_AT_SELECTED_VERSION: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION"); - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_SELECTED_VERSION length %lu", - (unsigned long) alen); - return -1; - } - attr->selected_version = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_SELECTED_VERSION " - "%d", attr->selected_version); - break; - case EAP_SIM_AT_FULLAUTH_ID_REQ: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_FULLAUTH_ID_REQ"); - attr->id_req = FULLAUTH_ID; - break; - case EAP_SIM_AT_COUNTER: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_COUNTER"); - return -1; - } - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_COUNTER (alen=%lu)", - (unsigned long) alen); - return -1; - } - attr->counter = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) AT_COUNTER %d", - attr->counter); - break; - case EAP_SIM_AT_NONCE_S: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NONCE_S"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NONCE_S"); - if (alen != 2 + EAP_SIM_NONCE_S_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid " - "AT_NONCE_S (alen=%lu)", - (unsigned long) alen); - return -1; - } - attr->nonce_s = apos + 2; - break; - case EAP_SIM_AT_CLIENT_ERROR_CODE: - if (alen != 2) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_CLIENT_ERROR_CODE length %lu", - (unsigned long) alen); - return -1; - } - attr->client_error_code = apos[0] * 256 + apos[1]; - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_CLIENT_ERROR_CODE " - "%d", attr->client_error_code); - break; - case EAP_SIM_AT_IV: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_IV"); - if (alen != 2 + EAP_SIM_MAC_LEN) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_IV " - "length %lu", (unsigned long) alen); - return -1; - } - attr->iv = apos + 2; - break; - case EAP_SIM_AT_ENCR_DATA: - wpa_printf(MSG_DEBUG, "EAP-SIM: AT_ENCR_DATA"); - attr->encr_data = apos + 2; - attr->encr_data_len = alen - 2; - if (attr->encr_data_len % 16) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid " - "AT_ENCR_DATA length %lu", - (unsigned long) - attr->encr_data_len); - return -1; - } - break; - case EAP_SIM_AT_NEXT_PSEUDONYM: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NEXT_PSEUDONYM"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NEXT_PSEUDONYM"); - plen = apos[0] * 256 + apos[1]; - if (plen > alen - 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" - " AT_NEXT_PSEUDONYM (actual" - " len %lu, attr len %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->next_pseudonym = pos + 4; - attr->next_pseudonym_len = plen; - break; - case EAP_SIM_AT_NEXT_REAUTH_ID: - if (!encr) { - wpa_printf(MSG_ERROR, "EAP-SIM: Unencrypted " - "AT_NEXT_REAUTH_ID"); - return -1; - } - wpa_printf(MSG_DEBUG, "EAP-SIM: (encr) " - "AT_NEXT_REAUTH_ID"); - plen = apos[0] * 256 + apos[1]; - if (plen > alen - 2) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid" - " AT_NEXT_REAUTH_ID (actual" - " len %lu, attr len %lu)", - (unsigned long) plen, - (unsigned long) alen); - return -1; - } - attr->next_reauth_id = pos + 4; - attr->next_reauth_id_len = plen; - break; - default: - if (pos[0] < 128) { - wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized " - "non-skippable attribute %d", - pos[0]); - return -1; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Unrecognized skippable" - " attribute %d ignored", pos[0]); - break; - } - - pos += pos[1] * 4; - } - - wpa_printf(MSG_DEBUG, "EAP-SIM: Attributes parsed successfully " - "(aka=%d encr=%d)", aka, encr); - - return 0; -} - - -int eap_sim_parse_encr(const u8 *k_encr, u8 *encr_data, size_t encr_data_len, - const u8 *iv, struct eap_sim_attrs *attr, int aka) -{ - if (!iv) { - wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV"); - return -1; - } - aes_128_cbc_decrypt(k_encr, iv, encr_data, encr_data_len); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA", - encr_data, encr_data_len); - - if (eap_sim_parse_attr(encr_data, encr_data + encr_data_len, attr, - aka, 1)) { - wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse " - "decrypted AT_ENCR_DATA"); - return -1; - } - - return 0; -} - - -#define EAP_SIM_INIT_LEN 128 - -struct eap_sim_msg { - u8 *buf; - size_t buf_len, used; - size_t mac, iv, encr; /* index from buf */ -}; - - -struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype) -{ - struct eap_sim_msg *msg; - struct eap_hdr *eap; - u8 *pos; - - msg = malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - memset(msg, 0, sizeof(*msg)); - - msg->buf = malloc(EAP_SIM_INIT_LEN); - if (msg->buf == NULL) { - free(msg); - return NULL; - } - memset(msg->buf, 0, EAP_SIM_INIT_LEN); - msg->buf_len = EAP_SIM_INIT_LEN; - eap = (struct eap_hdr *) msg->buf; - eap->code = code; - eap->identifier = id; - msg->used = sizeof(*eap); - - pos = (u8 *) (eap + 1); - *pos++ = type; - *pos++ = subtype; - *pos++ = 0; /* Reserved */ - *pos++ = 0; /* Reserved */ - msg->used += 4; - - return msg; -} - - -u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut, - const u8 *extra, size_t extra_len) -{ - struct eap_hdr *eap; - u8 *buf; - - if (msg == NULL) - return NULL; - - eap = (struct eap_hdr *) msg->buf; - eap->length = host_to_be16(msg->used); - - if (k_aut && msg->mac) { - eap_sim_add_mac(k_aut, msg->buf, msg->used, - msg->buf + msg->mac, extra, extra_len); - } - - *len = msg->used; - buf = msg->buf; - free(msg); - return buf; -} - - -void eap_sim_msg_free(struct eap_sim_msg *msg) -{ - if (msg) { - free(msg->buf); - free(msg); - } -} - - -static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len) -{ - if (msg->used + add_len > msg->buf_len) { - u8 *nbuf = realloc(msg->buf, msg->used + add_len); - if (nbuf == NULL) - return -1; - msg->buf = nbuf; - msg->buf_len = msg->used + add_len; - } - return 0; -} - - -u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, - const u8 *data, size_t len) -{ - int attr_len = 2 + len; - int pad_len; - u8 *start, *pos; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (eap_sim_msg_resize(msg, attr_len)) - return NULL; - start = pos = msg->buf + msg->used; - *pos++ = attr; - *pos++ = attr_len / 4; - memcpy(pos, data, len); - if (pad_len) { - pos += len; - memset(pos, 0, pad_len); - } - msg->used += attr_len; - return start; -} - - -u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, u16 value, - const u8 *data, size_t len) -{ - int attr_len = 4 + len; - int pad_len; - u8 *start, *pos; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (eap_sim_msg_resize(msg, attr_len)) - return NULL; - start = pos = msg->buf + msg->used; - *pos++ = attr; - *pos++ = attr_len / 4; - *pos++ = value >> 8; - *pos++ = value & 0xff; - if (data) - memcpy(pos, data, len); - if (pad_len) { - pos += len; - memset(pos, 0, pad_len); - } - msg->used += attr_len; - return start; -} - - -u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr) -{ - u8 *pos = eap_sim_msg_add(msg, attr, 0, NULL, EAP_SIM_MAC_LEN); - if (pos) - msg->mac = (pos - msg->buf) + 4; - return pos; -} - - -int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, - u8 attr_encr) -{ - u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN); - if (pos == NULL) - return -1; - msg->iv = (pos - msg->buf) + 4; - if (hostapd_get_rand(msg->buf + msg->iv, EAP_SIM_IV_LEN)) { - msg->iv = 0; - return -1; - } - - pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0); - if (pos == NULL) { - msg->iv = 0; - return -1; - } - msg->encr = pos - msg->buf; - - return 0; -} - - -int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad) -{ - size_t encr_len; - - if (k_encr == NULL || msg->iv == 0 || msg->encr == 0) - return -1; - - encr_len = msg->used - msg->encr - 4; - if (encr_len % 16) { - u8 *pos; - int pad_len = 16 - (encr_len % 16); - if (pad_len < 4) { - wpa_printf(MSG_WARNING, "EAP-SIM: " - "eap_sim_msg_add_encr_end - invalid pad_len" - " %d", pad_len); - return -1; - } - wpa_printf(MSG_DEBUG, " *AT_PADDING"); - pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4); - if (pos == NULL) - return -1; - memset(pos + 4, 0, pad_len - 4); - encr_len += pad_len; - } - wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)", - (unsigned long) encr_len); - msg->buf[msg->encr + 1] = encr_len / 4 + 1; - aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv, - msg->buf + msg->encr + 4, encr_len); - - return 0; -} - - -void eap_sim_report_notification(void *msg_ctx, int notification, int aka) -{ - const char *type = aka ? "AKA" : "SIM"; - - switch (notification) { - case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH: - wpa_printf(MSG_WARNING, "EAP-%s: General failure " - "notification (after authentication)", type); - break; - case EAP_SIM_TEMPORARILY_DENIED: - wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " - "User has been temporarily denied access to the " - "requested service", type); - break; - case EAP_SIM_NOT_SUBSCRIBED: - wpa_printf(MSG_WARNING, "EAP-%s: Failure notification: " - "User has not subscribed to the requested service", - type); - break; - case EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH: - wpa_printf(MSG_WARNING, "EAP-%s: General failure " - "notification (before authentication)", type); - break; - case EAP_SIM_SUCCESS: - wpa_printf(MSG_INFO, "EAP-%s: Successful authentication " - "notification", type); - break; - default: - if (notification >= 32768) { - wpa_printf(MSG_INFO, "EAP-%s: Unrecognized " - "non-failure notification %d", - type, notification); - } else { - wpa_printf(MSG_WARNING, "EAP-%s: Unrecognized " - "failure notification %d", - type, notification); - } - } -} - - -#ifdef TEST_MAIN_EAP_SIM_COMMON -static int test_eap_sim_prf(void) -{ - /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */ - u8 xkey[] = { - 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b, - 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f, - 0xeb, 0x5a, 0x38, 0xb6 - }; - u8 w[] = { - 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, - 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49, - 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba, - 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78, - 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16 - }; - u8 buf[40]; - - printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n"); - eap_sim_prf(xkey, buf, sizeof(buf)); - if (memcmp(w, buf, sizeof(w) != 0)) { - printf("eap_sim_prf failed\n"); - return 1; - } - - return 0; -} - - -int main(int argc, char *argv[]) -{ - int errors = 0; - - errors += test_eap_sim_prf(); - - return errors; -} -#endif /* TEST_MAIN_EAP_SIM_COMMON */ diff --git a/contrib/wpa_supplicant/eap_sim_common.h b/contrib/wpa_supplicant/eap_sim_common.h deleted file mode 100644 index c89e04e410b9..000000000000 --- a/contrib/wpa_supplicant/eap_sim_common.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef EAP_SIM_COMMON_H -#define EAP_SIM_COMMON_H - -#define EAP_SIM_NONCE_S_LEN 16 -#define EAP_SIM_NONCE_MT_LEN 16 -#define EAP_SIM_MAC_LEN 16 -#define EAP_SIM_MK_LEN 20 -#define EAP_SIM_K_AUT_LEN 16 -#define EAP_SIM_K_ENCR_LEN 16 -#define EAP_SIM_KEYING_DATA_LEN 64 -#define EAP_SIM_IV_LEN 16 - -#define GSM_RAND_LEN 16 - -#define AKA_RAND_LEN 16 -#define AKA_AUTN_LEN 16 - -void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk); -void eap_sim_derive_keys_reauth(unsigned int _counter, - const u8 *identity, size_t identity_len, - const u8 *nonce_s, const u8 *mk, u8 *msk); -int eap_sim_verify_mac(const u8 *k_aut, u8 *req, size_t req_len, u8 *mac, - u8 *extra, size_t extra_len); -void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len); - - -/* EAP-SIM/AKA Attributes (0..127 non-skippable) */ -#define EAP_SIM_AT_RAND 1 -#define EAP_SIM_AT_AUTN 2 /* only AKA */ -#define EAP_SIM_AT_RES 3 /* only AKA, only send */ -#define EAP_SIM_AT_AUTS 4 /* only AKA, only send */ -#define EAP_SIM_AT_PADDING 6 /* only encrypted */ -#define EAP_SIM_AT_NONCE_MT 7 /* only SIM, only send */ -#define EAP_SIM_AT_PERMANENT_ID_REQ 10 -#define EAP_SIM_AT_MAC 11 -#define EAP_SIM_AT_NOTIFICATION 12 -#define EAP_SIM_AT_ANY_ID_REQ 13 -#define EAP_SIM_AT_IDENTITY 14 /* only send */ -#define EAP_SIM_AT_VERSION_LIST 15 /* only SIM */ -#define EAP_SIM_AT_SELECTED_VERSION 16 /* only SIM */ -#define EAP_SIM_AT_FULLAUTH_ID_REQ 17 -#define EAP_SIM_AT_COUNTER 19 /* only encrypted */ -#define EAP_SIM_AT_COUNTER_TOO_SMALL 20 /* only encrypted */ -#define EAP_SIM_AT_NONCE_S 21 /* only encrypted */ -#define EAP_SIM_AT_CLIENT_ERROR_CODE 22 /* only send */ -#define EAP_SIM_AT_IV 129 -#define EAP_SIM_AT_ENCR_DATA 130 -#define EAP_SIM_AT_NEXT_PSEUDONYM 132 /* only encrypted */ -#define EAP_SIM_AT_NEXT_REAUTH_ID 133 /* only encrypted */ -#define EAP_SIM_AT_CHECKCODE 134 /* only AKA */ -#define EAP_SIM_AT_RESULT_IND 135 - -/* AT_NOTIFICATION notification code values */ -#define EAP_SIM_GENERAL_FAILURE_AFTER_AUTH 0 -#define EAP_SIM_TEMPORARILY_DENIED 1026 -#define EAP_SIM_NOT_SUBSCRIBED 1031 -#define EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH 16384 -#define EAP_SIM_SUCCESS 32768 - - -enum eap_sim_id_req { - NO_ID_REQ, ANY_ID, FULLAUTH_ID, PERMANENT_ID -}; - - -struct eap_sim_attrs { - u8 *rand, *autn, *mac, *iv, *encr_data, *version_list, *nonce_s; - u8 *next_pseudonym, *next_reauth_id; - u8 *nonce_mt, *identity; - size_t num_chal, version_list_len, encr_data_len; - size_t next_pseudonym_len, next_reauth_id_len, identity_len; - enum eap_sim_id_req id_req; - int notification, counter, selected_version, client_error_code; -}; - -int eap_sim_parse_attr(u8 *start, u8 *end, struct eap_sim_attrs *attr, - int aka, int encr); -int eap_sim_parse_encr(const u8 *k_encr, u8 *encr_data, size_t encr_data_len, - const u8 *iv, struct eap_sim_attrs *attr, int aka); - - -struct eap_sim_msg; - -struct eap_sim_msg * eap_sim_msg_init(int code, int id, int type, int subtype); -u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut, - const u8 *extra, size_t extra_len); -void eap_sim_msg_free(struct eap_sim_msg *msg); -u8 * eap_sim_msg_add_full(struct eap_sim_msg *msg, u8 attr, - const u8 *data, size_t len); -u8 * eap_sim_msg_add(struct eap_sim_msg *msg, u8 attr, - u16 value, const u8 *data, size_t len); -u8 * eap_sim_msg_add_mac(struct eap_sim_msg *msg, u8 attr); -int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, - u8 attr_encr); -int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, - int attr_pad); - -void eap_sim_report_notification(void *msg_ctx, int notification, int aka); - -#endif /* EAP_SIM_COMMON_H */ diff --git a/contrib/wpa_supplicant/eap_testing.txt b/contrib/wpa_supplicant/eap_testing.txt deleted file mode 100644 index 03ef2858e425..000000000000 --- a/contrib/wpa_supplicant/eap_testing.txt +++ /dev/null @@ -1,349 +0,0 @@ -Automatic regression and interoperability testing of wpa_supplicant's -IEEE 802.1X/EAPOL authentication - -Test program: -- Linked some parts of IEEE 802.1X Authenticator implementation from - hostapd (RADIUS client and RADIUS processing, EAP<->RADIUS - encapsulation/decapsulation) into wpa_supplicant. -- Replaced wpa_supplicant.c and wpa.c with test code that trigger - IEEE 802.1X authentication automatically without need for wireless - client card or AP. -- For EAP methods that generate keying material, the key derived by the - Supplicant is verified to match with the one received by the (now - integrated) Authenticator. - -The full automated test suite can now be run in couple of seconds, but -I'm more than willing to add new RADIUS authentication servers to make -this take a bit more time.. ;-) As an extra bonus, this can also be -seen as automatic regression/interoperability testing for the RADIUS -server, too. - -In order for me to be able to use a new authentication server, the -server need to be available from Internet (at least from one static IP -address) and I will need to get suitable user name/password pairs, -certificates, and private keys for testing use. Other alternative -would be to get an evaluation version of the server so that I can -install it on my own test setup. If you are interested in providing -either server access or evaluation version, please contact me -(jkmaline@cc.hut.fi). - - -Test matrix - -+) tested successfully -F) failed --) server did not support -?) not tested - -hostapd --------------------------------------------------------. -Cisco Aironet 1200 AP (local RADIUS server) ----------------. | -Corriente Elektron -------------------------------------. | | -Lucent NavisRadiator -------------------------------. | | | -Interlink RAD-Series ---------------------------. | | | | -Radiator -----------------------------------. | | | | | -Meetinghouse Aegis ---------------------. | | | | | | -Funk Steel-Belted ------------------. | | | | | | | -Funk Odyssey -------------------. | | | | | | | | -Microsoft IAS --------------. | | | | | | | | | -FreeRADIUS -------------. | | | | | | | | | | - | | | | | | | | | | | - -EAP-MD5 + - - + + + + + - - + -EAP-GTC + - - ? + + + + - - + -EAP-OTP - - - - - + - - - - - -EAP-MSCHAPv2 + - - + + + + + - - + -EAP-TLS + + + + + + + + - - + -EAP-PEAPv0/MSCHAPv2 + + + + + + + + + - + -EAP-PEAPv0/GTC + - + - + + + + - - + -EAP-PEAPv0/OTP - - - - - + - - - - - -EAP-PEAPv0/MD5 + - - + + + + + - - + -EAP-PEAPv0/TLS - + - + + + F + - - - -EAP-PEAPv1/MSCHAPv2 - - + + + +1 + +5 +8 - + -EAP-PEAPv1/GTC - - + + + +1 + +5 - - + -EAP-PEAPv1/OTP - - - - - +1 - - - - - -EAP-PEAPv1/MD5 - - - + + +1 + +5 - - + -EAP-PEAPv1/TLS - - - + + +1 F +5 - - - -EAP-TTLS/CHAP + - +2 + + + + + + - + -EAP-TTLS/MSCHAP + - + + + + + + + - + -EAP-TTLS/MSCHAPv2 + - + + + + + + + - + -EAP-TTLS/PAP + - + + + + + + + - + -EAP-TTLS/EAP-MD5 + - +2 + + + + + - - + -EAP-TTLS/EAP-GTC + - +2 ? + + + + - - + -EAP-TTLS/EAP-OTP - - - - - + - - - - - -EAP-TTLS/EAP-MSCHAPv2 + - +2 + + + + + + - + -EAP-TTLS/EAP-TLS - - +2 + F + + + - - - -EAP-SIM +3 - - ? - + - ? - - + -EAP-AKA - - - - - + - - - - - -EAP-PSK +7 - - - - - - - - - - -EAP-FAST - - - - - - - - - + - -LEAP + - + + + + F +6 - + - - -1) PEAPv1 required new label, "client PEAP encryption" instead of "client EAP - encryption", during key derivation (requires phase1="peaplabel=1" in the - network configuration in wpa_supplicant.conf) -2) used FreeRADIUS as inner auth server -3) required a patch to FreeRADIUS to fix EAP-SIM -5) PEAPv1 required termination of negotiation on tunneled EAP-Success and new - label in key deriviation - (phase1="peap_outer_success=0 peaplabel=1") (in "IETF Draft 5" mode) -6) Authenticator simulator required patching for handling Access-Accept within - negotiation (for the first EAP-Success of LEAP) -7) EAP-PSK is not included in FreeRADIUS distribution; used external - rlm_eap_psk implementation from - http://perso.rd.francetelecom.fr/bersani/EAP_PSK/ - EAP-PSKWindowsimplementations.html -8) PEAPv1 used non-standard version negotiation (client had to force v1 even - though server reported v0 as the highest supported version) - - -Automated tests: - -FreeRADIUS (1.0pre and CVS snapshot) -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / CHAP -- EAP-TTLS / PAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-SIM -* not supported in FreeRADIUS - - EAP-PEAP / TLS (Unable to tunnel TLS inside of TLS) - - EAP-TTLS / EAP-TLS (Unable to tunnel TLS inside of TLS) - -Microsoft Windows Server 2003 / IAS -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / TLS -- EAP-MD5 -* IAS does not seem to support other EAP methods - -Funk Odyssey 2.01.00.653 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP (using FreeRADIUS as inner auth srv) -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge (using FreeRADIUS as inner auth srv) -- EAP-TTLS / EAP-GTC (using FreeRADIUS as inner auth srv) -- EAP-TTLS / EAP-MSCHAPv2 (using FreeRADIUS as inner auth srv) -- EAP-TTLS / EAP-TLS (using FreeRADIUS as inner auth srv) -* not supported in Odyssey: - - EAP-MD5-Challenge - - EAP-GTC - - EAP-MSCHAPv2 - - EAP-PEAP / MD5-Challenge - - EAP-PEAP / TLS - -Funk Steel-Belted Radius Enterprise Edition v4.71.739 -- EAP-MD5-Challenge -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / MD5 -- EAP-PEAPv0 / TLS -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / MD5 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / TLS - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-TLS - -Meetinghouse Aegis 1.1.4 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / TLS -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / TLS -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / MD5-Challenge - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -* did not work - - EAP-TTLS / EAP-TLS - (Server rejects authentication without any reason in debug log. It - looks like the inner TLS negotiation starts properly and the last - packet from Supplicant looks like the one sent in the Phase 1. The - server generates a valid looking reply in the same way as in Phase - 1, but then ends up sending Access-Reject. Maybe an issue with TTLS - fragmentation in the Aegis server(?) The packet seems to include - 1328 bytes of EAP-Message and this may go beyond the fragmentation - limit with AVP encapsulation and TLS tunneling. Note: EAP-PEAP/TLS - did work, so this issue seems to be with something TTLS specific.) - -Radiator 3.9 (eval, with all patches up to and including 2004-08-30) -- EAP-MD5-Challenge -- EAP-GTC -- EAP-OTP -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / OTP -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv0 / TLS - Note: Needed to use unknown identity in outer auth and some times the server - seems to get confused and fails to send proper Phase 2 data. -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / OTP -- EAP-PEAPv1 / MD5-Challenge -- EAP-PEAPv1 / TLS - Note: This has some additional requirements for EAPTLS_MaxFragmentSize. - Using 1300 for outer auth and 500 for inner auth seemed to work. - Note: Needed to use unknown identity in outer auth and some times the server - seems to get confused and fails to send proper Phase 2 data. -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-OTP -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-TLS - Note: This has some additional requirements for EAPTLS_MaxFragmentSize. - Using 1300 for outer auth and 500 for inner auth seemed to work. -- EAP-SIM -- EAP-AKA - -Interlink Networks RAD-Series 6.1.2.7 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / MD5-Challenge - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-TLS -* did not work - - EAP-PEAPv0 / TLS - - EAP-PEAPv1 / TLS - (Failed to decrypt Phase 2 data) - -Lucent NavisRadius 4.4.0 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / TLS -- EAP-PEAPv1 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / TLS - "IETF Draft 5" mode requires phase1="peap_outer_success=0 peaplabel=1" - 'Cisco ACU 5.05' mode works without phase1 configuration -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-TLS - -Note: user certificate from NavisRadius had private key in a format -that wpa_supplicant could not use. Converting this to PKCS#12 and then -back to PEM allowed wpa_supplicant to use the key. - - -hostapd v0.3.3 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / MD5-Challenge -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-SIM - - - -PEAPv1: - -Funk Odyssey 2.01.00.653: -- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE - keys with outer EAP-Success message after this -- uses label "client EAP encryption" -- (peap_outer_success 1 and 2 work) - -Funk Steel-Belted Radius Enterprise Edition v4.71.739 -- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE - keys with outer EAP-Success message after this -- uses label "client EAP encryption" -- (peap_outer_success 1 and 2 work) - -Radiator 3.9: -- uses TLV Success and Reply, sends MPPE keys with outer EAP-Success message - after this -- uses label "client PEAP encryption" - -Lucent NavisRadius 4.4.0 (in "IETF Draft 5" mode): -- sends tunneled EAP-Success with MPPE keys and expects the authentication to - terminate at this point (gets somewhat confused with reply to this) -- uses label "client PEAP encryption" -- phase1="peap_outer_success=0 peaplabel=1" - -Lucent NavisRadius 4.4.0 (in "Cisco ACU 5.05" mode): -- sends tunneled EAP-Success with MPPE keys and expects to receive TLS ACK - as a reply -- uses label "client EAP encryption" - -Meetinghouse Aegis 1.1.4 -- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE - keys with outer EAP-Success message after this -- uses label "client EAP encryption" -- peap_outer_success 1 and 2 work diff --git a/contrib/wpa_supplicant/eap_tls.c b/contrib/wpa_supplicant/eap_tls.c deleted file mode 100644 index 4b02cca14e1f..000000000000 --- a/contrib/wpa_supplicant/eap_tls.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * WPA Supplicant / EAP-TLS (RFC 2716) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "tls.h" - - -static void eap_tls_deinit(struct eap_sm *sm, void *priv); - - -struct eap_tls_data { - struct eap_ssl_data ssl; - u8 *key_data; -}; - - -static void * eap_tls_init(struct eap_sm *sm) -{ - struct eap_tls_data *data; - struct wpa_ssid *config = eap_get_config(sm); - if (config == NULL || - (sm->init_phase2 ? config->private_key2 : config->private_key) - == NULL) { - wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); - return NULL; - } - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - - if (eap_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); - eap_tls_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_tls_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - if (data == NULL) - return; - eap_tls_ssl_deinit(sm, &data->ssl); - free(data->key_data); - free(data); -} - - -static u8 * eap_tls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_hdr *req; - int left, res; - unsigned int tls_msg_len; - u8 flags, *pos, *resp, id; - struct eap_tls_data *data = priv; - - if (tls_get_errors(sm->ssl_ctx)) { - wpa_printf(MSG_INFO, "EAP-TLS: TLS errors detected"); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 2 || *pos != EAP_TYPE_TLS) { - wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - id = req->identifier; - pos++; - flags = *pos++; - left = be_to_host16(req->length) - sizeof(struct eap_hdr) - 2; - wpa_printf(MSG_DEBUG, "EAP-TLS: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) reqDataLen, flags); - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-TLS: Short frame with TLS " - "length"); - ret->ignore = TRUE; - return NULL; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - - ret->methodState = METHOD_CONT; - ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); - left = 0; /* make sure that this frame is empty, even though it - * should always be, anyway */ - } - - resp = NULL; - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, pos, - left, &resp, respDataLen); - - if (res < 0) { - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - return eap_tls_build_ack(&data->ssl, respDataLen, id, - EAP_TYPE_TLS, 0); - } - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - free(data->key_data); - data->key_data = eap_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", - data->key_data, EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key"); - } - } - - if (res == 1) { - return eap_tls_build_ack(&data->ssl, respDataLen, id, - EAP_TYPE_TLS, 0); - } - return resp; -} - - -static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn); -} - - -static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ -} - - -static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - free(data->key_data); - data->key_data = NULL; - if (eap_tls_reauth_init(sm, &data->ssl)) { - free(data); - return NULL; - } - return priv; -} - - -static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_tls_data *data = priv; - return eap_tls_status(sm, &data->ssl, buf, buflen, verbose); -} - - -static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_tls_data *data = priv; - return data->key_data != NULL; -} - - -static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_tls_data *data = priv; - u8 *key; - - if (data->key_data == NULL) - return NULL; - - key = malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -const struct eap_method eap_method_tls = -{ - .method = EAP_TYPE_TLS, - .name = "TLS", - .init = eap_tls_init, - .deinit = eap_tls_deinit, - .process = eap_tls_process, - .isKeyAvailable = eap_tls_isKeyAvailable, - .getKey = eap_tls_getKey, - .get_status = eap_tls_get_status, - .has_reauth_data = eap_tls_has_reauth_data, - .deinit_for_reauth = eap_tls_deinit_for_reauth, - .init_for_reauth = eap_tls_init_for_reauth, -}; diff --git a/contrib/wpa_supplicant/eap_tls_common.c b/contrib/wpa_supplicant/eap_tls_common.c deleted file mode 100644 index a56538c8aa65..000000000000 --- a/contrib/wpa_supplicant/eap_tls_common.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * WPA Supplicant / EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "md5.h" -#include "sha1.h" -#include "tls.h" - - -int eap_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpa_ssid *config) -{ - int ret = -1; - char *ca_cert, *client_cert, *private_key, *private_key_passwd, - *dh_file, *subject_match; - - data->eap = sm; - data->phase2 = sm->init_phase2; - if (config == NULL) { - ca_cert = NULL; - client_cert = NULL; - private_key = NULL; - private_key_passwd = NULL; - dh_file = NULL; - subject_match = NULL; - } else if (data->phase2) { - ca_cert = (char *) config->ca_cert2; - client_cert = (char *) config->client_cert2; - private_key = (char *) config->private_key2; - private_key_passwd = (char *) config->private_key2_passwd; - dh_file = (char *) config->dh_file2; - subject_match = (char *) config->subject_match2; - } else { - ca_cert = (char *) config->ca_cert; - client_cert = (char *) config->client_cert; - private_key = (char *) config->private_key; - private_key_passwd = (char *) config->private_key_passwd; - dh_file = (char *) config->dh_file; - subject_match = (char *) config->subject_match; - } - data->conn = tls_connection_init(sm->ssl_ctx); - if (data->conn == NULL) { - wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " - "connection"); - goto done; - } - - if (tls_connection_ca_cert(sm->ssl_ctx, data->conn, ca_cert, - subject_match)) { - wpa_printf(MSG_INFO, "TLS: Failed to load root certificate " - "'%s'", ca_cert); - goto done; - } - - if (tls_connection_client_cert(sm->ssl_ctx, data->conn, client_cert)) { - wpa_printf(MSG_INFO, "TLS: Failed to load client certificate " - "'%s'", client_cert); - goto done; - } - - if (tls_connection_private_key(sm->ssl_ctx, data->conn, private_key, - private_key_passwd)) { - wpa_printf(MSG_INFO, "TLS: Failed to load private key '%s'", - private_key); - goto done; - } - - if (dh_file && tls_connection_dh(sm->ssl_ctx, data->conn, dh_file)) { - wpa_printf(MSG_INFO, "TLS: Failed to load DH file '%s'", - dh_file); - goto done; - } - - /* TODO: make this configurable */ - data->tls_out_limit = 1398; - if (data->phase2) { - /* Limit the fragment size in the inner TLS authentication - * since the outer authentication with EAP-PEAP does not yet - * support fragmentation */ - if (data->tls_out_limit > 100) - data->tls_out_limit -= 100; - } - - if (config && config->phase1 && - strstr(config->phase1, "include_tls_length=1")) { - wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in " - "unfragmented packets"); - data->include_tls_length = 1; - } - - ret = 0; - -done: - return ret; -} - - -void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - free(data->tls_in); - free(data->tls_out); -} - - -u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *random; - u8 *out; - - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - return NULL; - out = malloc(len); - random = malloc(keys.client_random_len + keys.server_random_len); - if (out == NULL || random == NULL) { - free(out); - free(random); - return NULL; - } - memcpy(random, keys.client_random, keys.client_random_len); - memcpy(random + keys.client_random_len, keys.server_random, - keys.server_random_len); - - if (tls_prf(keys.master_key, keys.master_key_len, - label, random, keys.client_random_len + - keys.server_random_len, out, len)) { - free(random); - free(out); - return NULL; - } - free(random); - return out; -} - - -int eap_tls_data_reassemble(struct eap_sm *sm, struct eap_ssl_data *data, - u8 **in_data, size_t *in_len) -{ - u8 *buf; - - if (data->tls_in_left > *in_len || data->tls_in) { - if (data->tls_in_len + *in_len == 0) { - free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - wpa_printf(MSG_WARNING, "SSL: Invalid reassembly " - "state: tls_in_left=%d tls_in_len=%d " - "*in_len=%d", - data->tls_in_left, data->tls_in_len, - *in_len); - return -1; - } - buf = realloc(data->tls_in, data->tls_in_len + *in_len); - if (buf == NULL) { - free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - wpa_printf(MSG_INFO, "SSL: Could not allocate memory " - "for TLS data"); - return -1; - } - memcpy(buf + data->tls_in_len, *in_data, *in_len); - data->tls_in = buf; - data->tls_in_len += *in_len; - if (*in_len > data->tls_in_left) { - wpa_printf(MSG_INFO, "SSL: more data than TLS message " - "length indicated"); - data->tls_in_left = 0; - return -1; - } - data->tls_in_left -= *in_len; - if (data->tls_in_left > 0) { - wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input " - "data", (unsigned long) data->tls_in_left); - return 1; - } - - *in_data = data->tls_in; - *in_len = data->tls_in_len; - } else - data->tls_in_left = 0; - - return 0; -} - - -int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - int eap_type, int peap_version, - u8 id, u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - size_t len; - u8 *pos, *flags; - struct eap_hdr *resp; - - WPA_ASSERT(data->tls_out_len == 0 || in_len == 0); - *out_len = 0; - - if (data->tls_out_len == 0) { - /* No more data to send out - expect to receive more data from - * the AS. */ - int res = eap_tls_data_reassemble(sm, data, &in_data, &in_len); - if (res < 0 || res == 1) - return res; - /* Full TLS message reassembled - continue handshake processing - */ - if (data->tls_out) { - /* This should not happen.. */ - wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - " - "pending tls_out data even though " - "tls_out_len = 0"); - free(data->tls_out); - WPA_ASSERT(data->tls_out == NULL); - } - data->tls_out = tls_connection_handshake(sm->ssl_ctx, - data->conn, - in_data, in_len, - &data->tls_out_len); - - /* Clear reassembled input data (if the buffer was needed). */ - data->tls_in_left = data->tls_in_total = data->tls_in_len = 0; - free(data->tls_in); - data->tls_in = NULL; - } - - if (data->tls_out == NULL) { - data->tls_out_len = 0; - return -1; - } - if (data->tls_out_len == 0) { - /* TLS negotiation should now be complete since all other cases - * needing more that should have been catched above based on - * the TLS Message Length field. */ - wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); - free(data->tls_out); - data->tls_out = NULL; - return 1; - } - - wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " - "%lu bytes)", - (unsigned long) data->tls_out_len - data->tls_out_pos, - (unsigned long) data->tls_out_len); - resp = malloc(sizeof(struct eap_hdr) + 2 + 4 + data->tls_out_limit); - if (resp == NULL) { - *out_data = NULL; - return -1; - } - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - pos = (u8 *) (resp + 1); - *pos++ = eap_type; - flags = pos++; - *flags = peap_version; - if (data->tls_out_pos == 0 && - (data->tls_out_len > data->tls_out_limit || - data->include_tls_length)) { - *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - *pos++ = (data->tls_out_len >> 24) & 0xff; - *pos++ = (data->tls_out_len >> 16) & 0xff; - *pos++ = (data->tls_out_len >> 8) & 0xff; - *pos++ = data->tls_out_len & 0xff; - } - - len = data->tls_out_len - data->tls_out_pos; - if (len > data->tls_out_limit) { - *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - len = data->tls_out_limit; - wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " - "will follow", (unsigned long) len); - } - memcpy(pos, &data->tls_out[data->tls_out_pos], len); - data->tls_out_pos += len; - *out_len = (pos - (u8 *) resp) + len; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - - if (!(*flags & EAP_TLS_FLAGS_MORE_FRAGMENTS)) { - data->tls_out_len = 0; - data->tls_out_pos = 0; - free(data->tls_out); - data->tls_out = NULL; - } - - return 0; -} - - -u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id, - int eap_type, int peap_version) -{ - struct eap_hdr *resp; - u8 *pos; - - *respDataLen = sizeof(struct eap_hdr) + 2; - resp = malloc(*respDataLen); - if (resp == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK"); - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - resp->length = host_to_be16(*respDataLen); - pos = (u8 *) (resp + 1); - *pos++ = eap_type; /* Type */ - *pos = peap_version; /* Flags */ - return (u8 *) resp; -} - - -int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) -{ - return tls_connection_shutdown(sm->ssl_ctx, data->conn); -} - - -int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf, - size_t buflen, int verbose) -{ - char name[128]; - int len = 0; - - if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) { - len += snprintf(buf + len, buflen - len, - "EAP TLS cipher=%s\n", name); - } - - return len; -} diff --git a/contrib/wpa_supplicant/eap_tls_common.h b/contrib/wpa_supplicant/eap_tls_common.h deleted file mode 100644 index 499cae4c0e10..000000000000 --- a/contrib/wpa_supplicant/eap_tls_common.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef EAP_TLS_COMMON_H -#define EAP_TLS_COMMON_H - -struct eap_ssl_data { - struct tls_connection *conn; - - u8 *tls_out; - size_t tls_out_len; - size_t tls_out_pos; - size_t tls_out_limit; - u8 *tls_in; - size_t tls_in_len; - size_t tls_in_left; - size_t tls_in_total; - - int phase2; - int include_tls_length; /* include TLS length field even if the TLS - * data is not fragmented */ - - struct eap_sm *eap; -}; - - -/* EAP TLS Flags */ -#define EAP_TLS_FLAGS_LENGTH_INCLUDED 0x80 -#define EAP_TLS_FLAGS_MORE_FRAGMENTS 0x40 -#define EAP_TLS_FLAGS_START 0x20 -#define EAP_PEAP_VERSION_MASK 0x07 - - /* could be up to 128 bytes, but only the first 64 bytes are used */ -#define EAP_TLS_KEY_LEN 64 - - -int eap_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpa_ssid *config); -void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); -u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len); -int eap_tls_data_reassemble(struct eap_sm *sm, struct eap_ssl_data *data, - u8 **in_data, size_t *in_len); -int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - int eap_type, int peap_version, - u8 id, u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len); -u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id, - int eap_type, int peap_version); -int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data); -int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf, - size_t buflen, int verbose); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/contrib/wpa_supplicant/eap_tlv.c b/contrib/wpa_supplicant/eap_tlv.c deleted file mode 100644 index 5571d8bdf2cb..000000000000 --- a/contrib/wpa_supplicant/eap_tlv.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * WPA Supplicant / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "wpa_supplicant.h" -#include "eap_i.h" -#include "eap_tlv.h" - - -u8 * eap_tlv_build_nak(int id, int nak_type, size_t *resp_len) -{ - struct eap_hdr *hdr; - u8 *pos; - - *resp_len = sizeof(struct eap_hdr) + 1 + 10; - hdr = malloc(*resp_len); - if (hdr == NULL) - return NULL; - - hdr->code = EAP_CODE_RESPONSE; - hdr->identifier = id; - hdr->length = host_to_be16(*resp_len); - pos = (u8 *) (hdr + 1); - *pos++ = EAP_TYPE_TLV; - *pos++ = 0x80; /* Mandatory */ - *pos++ = EAP_TLV_NAK_TLV; - /* Length */ - *pos++ = 0; - *pos++ = 6; - /* Vendor-Id */ - *pos++ = 0; - *pos++ = 0; - *pos++ = 0; - *pos++ = 0; - /* NAK-Type */ - *pos++ = nak_type >> 8; - *pos++ = nak_type & 0xff; - - return (u8 *) hdr; -} - - -u8 * eap_tlv_build_result(int id, int status, size_t *resp_len) -{ - struct eap_hdr *hdr; - u8 *pos; - - *resp_len = sizeof(struct eap_hdr) + 1 + 6; - hdr = malloc(*resp_len); - if (hdr == NULL) - return NULL; - - hdr->code = EAP_CODE_RESPONSE; - hdr->identifier = id; - hdr->length = host_to_be16(*resp_len); - pos = (u8 *) (hdr + 1); - *pos++ = EAP_TYPE_TLV; - *pos++ = 0x80; /* Mandatory */ - *pos++ = EAP_TLV_RESULT_TLV; - /* Length */ - *pos++ = 0; - *pos++ = 2; - /* Status */ - *pos++ = status >> 8; - *pos++ = status & 0xff; - - return (u8 *) hdr; -} - - -int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - struct eap_hdr *hdr, u8 **resp, size_t *resp_len) -{ - size_t left; - u8 *pos; - u8 *result_tlv = NULL; - size_t result_tlv_len = 0; - int tlv_type, mandatory, tlv_len; - - /* Parse TLVs */ - left = be_to_host16(hdr->length) - sizeof(struct eap_hdr) - 1; - pos = (u8 *) (hdr + 1); - pos++; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); - while (left >= 4) { - mandatory = !!(pos[0] & 0x80); - tlv_type = pos[0] & 0x3f; - tlv_type = (tlv_type << 8) | pos[1]; - tlv_len = ((int) pos[2] << 8) | pos[3]; - pos += 4; - left -= 4; - if (tlv_len > left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " - "(tlv_len=%d left=%lu)", tlv_len, - (unsigned long) left); - return -1; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - /* NAK TLV and ignore all TLVs in this packet. - */ - *resp = eap_tlv_build_nak(hdr->identifier, - tlv_type, resp_len); - return *resp == NULL ? -1 : 0; - } - /* Ignore this TLV, but process other TLVs */ - break; - } - - pos += tlv_len; - left -= tlv_len; - } - if (left) { - wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " - "Request (left=%lu)", (unsigned long) left); - return -1; - } - - /* Process supported TLVs */ - if (result_tlv) { - int status, resp_status; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", - result_tlv, result_tlv_len); - if (result_tlv_len < 2) { - wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " - "(len=%lu)", - (unsigned long) result_tlv_len); - return -1; - } - status = ((int) result_tlv[0] << 8) | result_tlv[1]; - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " - "- EAP-TLV/Phase2 Completed"); - resp_status = EAP_TLV_RESULT_SUCCESS; - ret->decision = DECISION_UNCOND_SUCC; - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } else { - wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " - "Status %d", status); - resp_status = EAP_TLV_RESULT_FAILURE; - ret->decision = DECISION_FAIL; - } - ret->methodState = METHOD_DONE; - - *resp = eap_tlv_build_result(hdr->identifier, resp_status, - resp_len); - } - - return 0; -} diff --git a/contrib/wpa_supplicant/eap_tlv.h b/contrib/wpa_supplicant/eap_tlv.h deleted file mode 100644 index 439155263716..000000000000 --- a/contrib/wpa_supplicant/eap_tlv.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef EAP_TLV_H -#define EAP_TLV_H - -/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */ -#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */ -#define EAP_TLV_NAK_TLV 4 -#define EAP_TLV_CRYPTO_BINDING_TLV 5 -#define EAP_TLV_CONNECTION_BINDING_TLV 6 -#define EAP_TLV_VENDOR_SPECIFIC_TLV 7 -#define EAP_TLV_URI_TLV 8 -#define EAP_TLV_EAP_PAYLOAD_TLV 9 -#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10 -#define EAP_TLV_PAC_TLV 11 /* draft-cam-winget-eap-fast-01.txt */ -#define EAP_TLV_CRYPTO_BINDING_TLV_ 12 /* draft-cam-winget-eap-fast-01.txt */ - -#define EAP_TLV_RESULT_SUCCESS 1 -#define EAP_TLV_RESULT_FAILURE 2 - -#define EAP_TLV_TYPE_MANDATORY 0x8000 - -struct eap_tlv_hdr { - u16 tlv_type; - u16 length; -}; - -struct eap_tlv_nak_tlv { - u16 tlv_type; - u16 length; - u32 vendor_id; - u16 nak_type; -} __attribute__((packed)); - -struct eap_tlv_result_tlv { - u16 tlv_type; - u16 length; - u16 status; -} __attribute__((packed)); - -struct eap_tlv_intermediate_result_tlv { - u16 tlv_type; - u16 length; - u16 status; -} __attribute__((packed)); - -struct eap_tlv_crypto_binding__tlv { - u16 tlv_type; - u16 length; - u8 reserved; - u8 version; - u8 received_version; - u8 subtype; - u8 nonce[32]; - u8 compound_mac[20]; -} __attribute__((packed)); - -struct eap_tlv_pac_ack_tlv { - u16 tlv_type; - u16 length; - u16 pac_type; - u16 pac_len; - u16 result; -} __attribute__((packed)); - -#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST 0 -#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE 1 - - -u8 * eap_tlv_build_nak(int id, int nak_type, size_t *resp_len); -u8 * eap_tlv_build_result(int id, int status, size_t *resp_len); -int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - struct eap_hdr *hdr, u8 **resp, size_t *resp_len); - -#endif /* EAP_TLV_H */ diff --git a/contrib/wpa_supplicant/eap_ttls.c b/contrib/wpa_supplicant/eap_ttls.c deleted file mode 100644 index 733f136997e4..000000000000 --- a/contrib/wpa_supplicant/eap_ttls.c +++ /dev/null @@ -1,1392 +0,0 @@ -/* - * WPA Supplicant / EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "wpa_supplicant.h" -#include "config_ssid.h" -#include "ms_funcs.h" -#include "md5.h" -#include "tls.h" -#include "eap_ttls.h" - - -static void eap_ttls_deinit(struct eap_sm *sm, void *priv); - - -struct eap_ttls_data { - struct eap_ssl_data ssl; - - const struct eap_method *phase2_method; - void *phase2_priv; - int phase2_success; - int phase2_start; - - enum { - EAP_TTLS_PHASE2_EAP, - EAP_TTLS_PHASE2_MSCHAPV2, - EAP_TTLS_PHASE2_MSCHAP, - EAP_TTLS_PHASE2_PAP, - EAP_TTLS_PHASE2_CHAP - } phase2_type; - u8 phase2_eap_type; - u8 *phase2_eap_types; - size_t num_phase2_eap_types; - - u8 auth_response[20]; - int auth_response_valid; - u8 ident; - int resuming; /* starting a resumed session */ - int reauth; /* reauthentication */ - u8 *key_data; - - u8 *pending_phase2_req; - size_t pending_phase2_req_len; -}; - - -static void * eap_ttls_init(struct eap_sm *sm) -{ - struct eap_ttls_data *data; - struct wpa_ssid *config = eap_get_config(sm); - char *selected; - - data = malloc(sizeof(*data)); - if (data == NULL) - return NULL; - memset(data, 0, sizeof(*data)); - selected = "EAP"; - data->phase2_type = EAP_TTLS_PHASE2_EAP; - if (config && config->phase2) { - if (strstr(config->phase2, "autheap=")) { - selected = "EAP"; - data->phase2_type = EAP_TTLS_PHASE2_EAP; - } else if (strstr(config->phase2, "auth=MSCHAPV2")) { - selected = "MSCHAPV2"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; - } else if (strstr(config->phase2, "auth=MSCHAP")) { - selected = "MSCHAP"; - data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; - } else if (strstr(config->phase2, "auth=PAP")) { - selected = "PAP"; - data->phase2_type = EAP_TTLS_PHASE2_PAP; - } else if (strstr(config->phase2, "auth=CHAP")) { - selected = "CHAP"; - data->phase2_type = EAP_TTLS_PHASE2_CHAP; - } - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected); - - if (data->phase2_type == EAP_TTLS_PHASE2_EAP) { - if (config && config->phase2) { - char *start, *pos, *buf; - u8 method, *methods = NULL, *_methods; - size_t num_methods = 0; - start = buf = strdup(config->phase2); - if (buf == NULL) { - eap_ttls_deinit(sm, data); - return NULL; - } - while (start && *start != '\0') { - pos = strstr(start, "autheap="); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + 8; - continue; - } - - start = pos + 8; - pos = strchr(start, ' '); - if (pos) - *pos++ = '\0'; - method = eap_get_phase2_type(start); - if (method == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "EAP-TTLS: " - "Unsupported Phase2 EAP " - "method '%s'", start); - } else { - num_methods++; - _methods = realloc(methods, - num_methods); - if (_methods == NULL) { - free(methods); - eap_ttls_deinit(sm, data); - return NULL; - } - methods = _methods; - methods[num_methods - 1] = method; - } - - start = pos; - } - free(buf); - data->phase2_eap_types = methods; - data->num_phase2_eap_types = num_methods; - } - if (data->phase2_eap_types == NULL) { - data->phase2_eap_types = eap_get_phase2_types( - config, &data->num_phase2_eap_types); - } - if (data->phase2_eap_types == NULL) { - wpa_printf(MSG_ERROR, "EAP-TTLS: No Phase2 EAP method " - "available"); - eap_ttls_deinit(sm, data); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase2 EAP types", - data->phase2_eap_types, - data->num_phase2_eap_types); - data->phase2_eap_type = EAP_TYPE_NONE; - } - - - if (eap_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL."); - eap_ttls_deinit(sm, data); - return NULL; - } - - return data; -} - - -static void eap_ttls_deinit(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - if (data == NULL) - return; - if (data->phase2_priv && data->phase2_method) - data->phase2_method->deinit(sm, data->phase2_priv); - free(data->phase2_eap_types); - eap_tls_ssl_deinit(sm, &data->ssl); - free(data->key_data); - free(data->pending_phase2_req); - free(data); -} - - -static int eap_ttls_encrypt(struct eap_sm *sm, struct eap_ttls_data *data, - int id, u8 *plain, size_t plain_len, - u8 **out_data, size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *resp; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (resp == NULL) - return -1; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_TTLS; - *pos++ = 0; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 " - "data"); - free(resp); - return -1; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - return 0; -} - - -static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, - int mandatory, size_t len) -{ - struct ttls_avp_vendor *avp; - u8 flags; - size_t hdrlen; - - avp = (struct ttls_avp_vendor *) avphdr; - flags = mandatory ? AVP_FLAGS_MANDATORY : 0; - if (vendor_id) { - flags |= AVP_FLAGS_VENDOR; - hdrlen = sizeof(*avp); - avp->vendor_id = host_to_be32(vendor_id); - } else { - hdrlen = sizeof(struct ttls_avp); - } - - avp->avp_code = host_to_be32(avp_code); - avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len)); - - return avphdr + hdrlen; -} - - -static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code, - u32 vendor_id, int mandatory, - u8 *data, size_t len) -{ - u8 *pos; - pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len); - memcpy(pos, data, len); - pos += len; - AVP_PAD(start, pos); - return pos; -} - - -static int eap_ttls_avp_encapsulate(u8 **resp, size_t *resp_len, u32 avp_code, - int mandatory) -{ - u8 *avp, *pos; - - avp = malloc(sizeof(struct ttls_avp) + *resp_len + 4); - if (avp == NULL) { - free(*resp); - *resp = NULL; - *resp_len = 0; - return -1; - } - - pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, *resp_len); - memcpy(pos, *resp, *resp_len); - pos += *resp_len; - AVP_PAD(avp, pos); - free(*resp); - *resp = avp; - *resp_len = pos - avp; - return 0; -} - - -static int eap_ttls_phase2_nak(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct eap_hdr *resp_hdr; - u8 *pos = (u8 *) (hdr + 1); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Allowed Phase2 EAP types", - data->phase2_eap_types, data->num_phase2_eap_types); - *resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_eap_types; - *resp = malloc(*resp_len); - if (*resp == NULL) - return -1; - - resp_hdr = (struct eap_hdr *) (*resp); - resp_hdr->code = EAP_CODE_RESPONSE; - resp_hdr->identifier = hdr->identifier; - resp_hdr->length = host_to_be16(*resp_len); - pos = (u8 *) (resp_hdr + 1); - *pos++ = EAP_TYPE_NAK; - memcpy(pos, data->phase2_eap_types, data->num_phase2_eap_types); - - return 0; -} - - -static int eap_ttls_phase2_request_eap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct wpa_ssid *config = eap_get_config(sm); - - if (len <= sizeof(struct eap_hdr)) { - wpa_printf(MSG_INFO, "EAP-TTLS: too short " - "Phase 2 request (len=%lu)", (unsigned long) len); - return -1; - } - pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1); - break; - default: - if (data->phase2_eap_type == EAP_TYPE_NONE) { - int i; - for (i = 0; i < data->num_phase2_eap_types; i++) { - if (data->phase2_eap_types[i] != *pos) - continue; - - data->phase2_eap_type = *pos; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " - "Phase 2 EAP method %d", - data->phase2_eap_type); - break; - } - } - if (*pos != data->phase2_eap_type || *pos == EAP_TYPE_NONE) { - if (eap_ttls_phase2_nak(sm, data, hdr, resp, resp_len)) - return -1; - break; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_sm_get_eap_methods(*pos); - if (data->phase2_method) { - sm->init_phase2 = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " - "Phase 2 EAP method %d", *pos); - return -1; - } - memset(&iret, 0, sizeof(iret)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, (u8 *) hdr, len, - resp_len); - if ((iret.methodState == METHOD_DONE || - iret.methodState == METHOD_MAY_CONT) && - (iret.decision == DECISION_UNCOND_SUCC || - iret.decision == DECISION_COND_SUCC || - iret.decision == DECISION_FAIL)) { - ret->methodState = iret.methodState; - ret->decision = iret.decision; - } - break; - } - - if (*resp == NULL && - (config->pending_req_identity || config->pending_req_password || - config->pending_req_otp)) { - return 0; - } - - if (*resp == NULL) - return -1; - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response", - *resp, *resp_len); - return eap_ttls_avp_encapsulate(resp, resp_len, - RADIUS_ATTR_EAP_MESSAGE, 1); -} - - -static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos, *challenge, *username, *peer_challenge; - size_t username_len; - int i; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request"); - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = config->identity; - username_len = config->identity_len; - pos = username; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - pos = buf = malloc(config->identity_len + 1000); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAPV2: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge", - EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 + - 1); - if (challenge == NULL) { - free(buf); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " - "implicit challenge"); - return -1; - } - peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - - /* MS-CHAP2-Response */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - EAP_TTLS_MSCHAPV2_RESPONSE_LEN); - data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; - *pos++ = data->ident; - *pos++ = 0; /* Flags */ - memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; - memset(pos, 0, 8); /* Reserved, must be zero */ - pos += 8; - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: implicit auth_challenge", - challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: peer_challenge", - peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 username", - username, username_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password", - config->password, config->password_len); - generate_nt_response(challenge, peer_challenge, - username, username_len, - config->password, config->password_len, - pos); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24); - generate_authenticator_response(config->password, config->password_len, - peer_challenge, challenge, - username, username_len, - pos, data->auth_response); - data->auth_response_valid = 1; - - pos += 24; - free(challenge); - AVP_PAD(buf, pos); - - *resp = buf; - *resp_len = pos - buf; - - if (sm->workaround) { - /* At least FreeRADIUS seems to be terminating - * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success - * packet. */ - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - " - "allow success without tunneled response"); - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_COND_SUCC; - } - - return 0; -} - - -static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos, *challenge; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); - - pos = buf = malloc(config->identity_len + 1000); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAP: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge", - EAP_TLS_KEY_LEN); - if (challenge == NULL) { - free(buf); - wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " - "implicit challenge"); - return -1; - } - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); - - /* MS-CHAP-Response */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, - RADIUS_VENDOR_ID_MICROSOFT, 1, - EAP_TTLS_MSCHAP_RESPONSE_LEN); - data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; - *pos++ = data->ident; - *pos++ = 1; /* Flags: Use NT style passwords */ - memset(pos, 0, 24); /* LM-Response */ - pos += 24; - nt_challenge_response(challenge, - config->password, config->password_len, - pos); /* NT-Response */ - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", - config->password, config->password_len); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge", - challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24); - pos += 24; - free(challenge); - AVP_PAD(buf, pos); - - *resp = buf; - *resp_len = pos - buf; - - /* EAP-TTLS/MSCHAP does not provide tunneled success notification, so - * assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - - return 0; -} - - -static int eap_ttls_phase2_request_pap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos; - size_t pad; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request"); - - pos = buf = malloc(config->identity_len + config->password_len + 100); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/PAP: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts - * the data, so no separate encryption is used in the AVP itself. - * However, the password is padded to obfuscate its length. */ - pad = (16 - (config->password_len & 15)) & 15; - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1, - config->password_len + pad); - memcpy(pos, config->password, config->password_len); - pos += config->password_len; - memset(pos, 0, pad); - pos += pad; - AVP_PAD(buf, pos); - - *resp = buf; - *resp_len = pos - buf; - - /* EAP-TTLS/PAP does not provide tunneled success notification, so - * assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - - return 0; -} - - -static int eap_ttls_phase2_request_chap(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos, *challenge; - MD5_CTX context; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request"); - - pos = buf = malloc(config->identity_len + 1000); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/CHAP: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* CHAP-Challenge */ - challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge", - EAP_TLS_KEY_LEN); - if (challenge == NULL) { - free(buf); - wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " - "implicit challenge"); - return -1; - } - - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1, - challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - - /* CHAP-Password */ - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1, - 1 + EAP_TTLS_CHAP_PASSWORD_LEN); - data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN]; - *pos++ = data->ident; - - /* MD5(Ident + Password + Challenge) */ - MD5Init(&context); - MD5Update(&context, &data->ident, 1); - MD5Update(&context, config->password, config->password_len); - MD5Update(&context, challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - MD5Final(pos, &context); - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username", - config->identity, config->identity_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password", - config->password, config->password_len); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge", - challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password", - pos, EAP_TTLS_CHAP_PASSWORD_LEN); - pos += EAP_TTLS_CHAP_PASSWORD_LEN; - free(challenge); - AVP_PAD(buf, pos); - - *resp = buf; - *resp_len = pos - buf; - - /* EAP-TTLS/CHAP does not provide tunneled success notification, so - * assume that Phase2 succeeds. */ - ret->methodState = METHOD_DONE; - ret->decision = DECISION_COND_SUCC; - - return 0; -} - - -static int eap_ttls_phase2_request(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - int res = 0; - - if (data->phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 || - data->phase2_type == EAP_TTLS_PHASE2_MSCHAP || - data->phase2_type == EAP_TTLS_PHASE2_PAP || - data->phase2_type == EAP_TTLS_PHASE2_CHAP) { - if (config == NULL || config->identity == NULL) { - wpa_printf(MSG_INFO, - "EAP-TTLS: Identity not configured"); - eap_sm_request_identity(sm, config); - if (config->password == NULL) - eap_sm_request_password(sm, config); - return 0; - } - - if (config->password == NULL) { - wpa_printf(MSG_INFO, - "EAP-TTLS: Password not configured"); - eap_sm_request_password(sm, config); - return 0; - } - } - - switch (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - res = eap_ttls_phase2_request_eap(sm, data, ret, req, hdr, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - res = eap_ttls_phase2_request_mschapv2(sm, data, ret, req, hdr, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_MSCHAP: - res = eap_ttls_phase2_request_mschap(sm, data, ret, req, hdr, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_PAP: - res = eap_ttls_phase2_request_pap(sm, data, ret, req, hdr, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_CHAP: - res = eap_ttls_phase2_request_chap(sm, data, ret, req, hdr, - resp, resp_len); - break; - default: - wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown"); - res = -1; - break; - } - - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return res; -} - - -static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, - struct eap_method_ret *ret, struct eap_hdr *req, - u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - u8 *in_decrypted = NULL, *pos; - int buf_len, len_decrypted = 0, len, left, retval = 0, res; - struct eap_hdr *hdr = NULL; - u8 *resp = NULL, *mschapv2 = NULL, *eapdata = NULL; - size_t resp_len, eap_len = 0; - struct ttls_avp *avp; - u8 recv_response[20]; - int mschapv2_error = 0; - struct wpa_ssid *config = eap_get_config(sm); - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - if (data->pending_phase2_req) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - " - "skip decryption and use old data"); - /* Clear TLS reassembly state. */ - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - data->ssl.tls_in_left = 0; - data->ssl.tls_in_total = 0; - - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - len_decrypted = data->pending_phase2_req_len; - if (data->pending_phase2_req_len == 0) { - free(in_decrypted); - in_decrypted = NULL; - goto fake_req_identity; - } - goto continue_req; - } - - if (in_len == 0 && data->phase2_start) { - data->phase2_start = 0; - /* EAP-TTLS does not use Phase2 on fast re-auth; this must be - * done only if TLS part was indeed resuming a previous - * session. Most Authentication Servers terminate EAP-TTLS - * before reaching this point, but some do not. Make - * wpa_supplicant stop phase 2 here, if needed. */ - if (data->reauth && - tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - " - "skip phase 2"); - *out_data = eap_tls_build_ack(&data->ssl, out_len, - req->identifier, - EAP_TYPE_TTLS, 0); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - return 0; - } - fake_req_identity: - wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of " - "Phase 2 - use fake EAP-Request Identity"); - buf_len = sizeof(*hdr) + 1; - in_decrypted = malloc(buf_len); - if (in_decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate " - "memory for fake EAP-Identity Request"); - retval = -1; - goto done; - } - hdr = (struct eap_hdr *) in_decrypted; - hdr->code = EAP_CODE_REQUEST; - hdr->identifier = 0; - hdr->length = host_to_be16(sizeof(*hdr) + 1); - in_decrypted[sizeof(*hdr)] = EAP_TYPE_IDENTITY; - goto process_eap; - } - - res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len); - if (res < 0 || res == 1) { - retval = res; - goto done; - } - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = malloc(buf_len); - if (in_decrypted == NULL) { - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory " - "for decryption"); - retval = -1; - goto done; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " - "data"); - retval = -1; - goto done; - } - -continue_req: - data->phase2_start = 0; - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", - in_decrypted, len_decrypted); - if (len_decrypted < sizeof(struct ttls_avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame" - " len=%d expected %lu or more - dropped", - len_decrypted, - (unsigned long) sizeof(struct ttls_avp)); - retval = -1; - goto done; - } - - /* Parse AVPs */ - pos = in_decrypted; - left = len_decrypted; - mschapv2 = NULL; - - while (left > 0) { - u32 avp_code, avp_length, vendor_id = 0; - u8 avp_flags, *dpos; - size_t pad, dlen; - avp = (struct ttls_avp *) pos; - avp_code = be_to_host32(avp->avp_code); - avp_length = be_to_host32(avp->avp_length); - avp_flags = (avp_length >> 24) & 0xff; - avp_length &= 0xffffff; - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " - "length=%d", (int) avp_code, avp_flags, - (int) avp_length); - if (avp_length > left) { - wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " - "(len=%d, left=%d) - dropped", - (int) avp_length, left); - retval = -1; - goto done; - } - dpos = (u8 *) (avp + 1); - dlen = avp_length - sizeof(*avp); - if (avp_flags & AVP_FLAGS_VENDOR) { - if (dlen < 4) { - wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP " - "underflow"); - retval = -1; - goto done; - } - vendor_id = be_to_host32(* (u32 *) dpos); - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d", - (int) vendor_id); - dpos += 4; - dlen -= 4; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen); - - if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message"); - if (eapdata == NULL) { - eapdata = malloc(dlen); - if (eapdata == NULL) { - retval = -1; - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto done; - } - memcpy(eapdata, dpos, dlen); - eap_len = dlen; - } else { - u8 *neweap = realloc(eapdata, eap_len + dlen); - if (neweap == NULL) { - retval = -1; - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto done; - } - memcpy(neweap + eap_len, dpos, dlen); - eapdata = neweap; - eap_len += dlen; - } - } else if (vendor_id == 0 && - avp_code == RADIUS_ATTR_REPLY_MESSAGE) { - /* This is an optional message that can be displayed to - * the user. */ - wpa_hexdump_ascii(MSG_DEBUG, - "EAP-TTLS: AVP - Reply-Message", - dpos, dlen); - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: " - "MS-CHAP2-Success", dpos, dlen); - if (dlen != 43) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected " - "MS-CHAP2-Success length " - "(len=%lu, expected 43)", - (unsigned long) dlen); - retval = -1; - break; - } - mschapv2 = dpos; - } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && - avp_code == RADIUS_ATTR_MS_CHAP_ERROR) { - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: " - "MS-CHAP-Error", dpos, dlen); - mschapv2_error = 1; - } else if (avp_flags & AVP_FLAGS_MANDATORY) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported " - "mandatory AVP code %d vendor_id %d - " - "dropped", (int) avp_code, (int) vendor_id); - retval = -1; - goto done; - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported " - "AVP code %d vendor_id %d", - (int) avp_code, (int) vendor_id); - } - - pad = (4 - (avp_length & 3)) & 3; - pos += avp_length + pad; - left -= avp_length + pad; - } - - switch (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - if (eapdata == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in " - "the packet - dropped"); - retval = -1; - goto done; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP", - eapdata, eap_len); - hdr = (struct eap_hdr *) eapdata; - - if (eap_len < sizeof(*hdr)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 " - "EAP frame (len=%lu, expected %lu or more) " - "- dropped", (unsigned long) eap_len, - (unsigned long) sizeof(*hdr)); - retval = -1; - goto done; - } - len = be_to_host16(hdr->length); - if (len > eap_len) { - wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in " - "Phase 2 EAP frame (EAP hdr len=%d, EAP " - "data len in AVP=%lu)", len, - (unsigned long) eap_len); - retval = -1; - goto done; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d " - "identifier=%d length=%d", - hdr->code, hdr->identifier, len); - process_eap: - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_ttls_phase2_request(sm, data, ret, req, hdr, - &resp, &resp_len)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 " - "Request processing failed"); - retval = -1; - goto done; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - retval = -1; - break; - } - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - if (mschapv2_error) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received " - "MS-CHAP-Error - failed"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - *out_data = eap_tls_build_ack(&data->ssl, out_len, - req->identifier, - EAP_TYPE_TTLS, 0); - break; - } - - if (mschapv2 == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success" - " AVP received for Phase2 MSCHAPV2"); - retval = -1; - break; - } - if (mschapv2[0] != data->ident) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch " - "for Phase 2 MSCHAPV2 (received Ident " - "0x%02x, expected 0x%02x)", - mschapv2[0], data->ident); - retval = -1; - break; - } - if (!data->auth_response_valid || - mschapv2[1] != 'S' || mschapv2[2] != '=' || - hexstr2bin((char *) (mschapv2 + 3), recv_response, 20) || - memcmp(data->auth_response, recv_response, 20) != 0) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid " - "authenticator response in Phase 2 " - "MSCHAPV2 success request"); - retval = -1; - break; - } - - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 " - "authentication succeeded"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - - /* Reply with empty data; authentication server will reply - * with EAP-Success after this. */ - retval = 1; - goto done; - case EAP_TTLS_PHASE2_MSCHAP: - case EAP_TTLS_PHASE2_PAP: - case EAP_TTLS_PHASE2_CHAP: - /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled - * requests to the supplicant */ - wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected " - "tunneled data"); - retval = -1; - break; - } - - if (resp) { - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data", - resp, resp_len); - - if (eap_ttls_encrypt(sm, data, req->identifier, - resp, resp_len, out_data, out_len)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt " - "a Phase 2 frame"); - } - free(resp); - } else if (config->pending_req_identity || - config->pending_req_password || - config->pending_req_otp) { - free(data->pending_phase2_req); - data->pending_phase2_req = malloc(len_decrypted); - if (data->pending_phase2_req) { - memcpy(data->pending_phase2_req, in_decrypted, - len_decrypted); - data->pending_phase2_req_len = len_decrypted; - } - } - -done: - free(in_decrypted); - free(eapdata); - - if (retval < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return retval; -} - - -static u8 * eap_ttls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_hdr *req; - int left, res; - unsigned int tls_msg_len; - u8 flags, *pos, *resp, id; - struct eap_ttls_data *data = priv; - - if (tls_get_errors(sm->ssl_ctx)) { - wpa_printf(MSG_INFO, "EAP-TTLS: TLS errors detected"); - ret->ignore = TRUE; - return NULL; - } - - req = (struct eap_hdr *) reqData; - pos = (u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 2 || *pos != EAP_TYPE_TTLS || - (left = be_to_host16(req->length)) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); - ret->ignore = TRUE; - return NULL; - } - left -= sizeof(struct eap_hdr); - id = req->identifier; - pos++; - flags = *pos++; - left -= 2; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) reqDataLen, flags); - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS " - "length"); - ret->ignore = TRUE; - return NULL; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start"); - /* draft-ietf-pppext-eap-ttls-03.txt, Ch. 8.1: - * EAP-TTLS Start packet may, in a future specification, be - * allowed to contain data. Client based on this draft version - * must ignore such data but must not reject the Start packet. - */ - left = 0; - } - - resp = NULL; - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - !data->resuming) { - res = eap_ttls_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - } else { - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, 0, - id, pos, left, - &resp, respDataLen); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, - "EAP-TTLS: TLS done, proceed to Phase 2"); - if (data->resuming) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth -" - " may skip Phase 2"); - ret->decision = DECISION_COND_SUCC; - ret->methodState = METHOD_MAY_CONT; - } - data->phase2_start = 1; - free(data->key_data); - data->key_data = - eap_tls_derive_key(sm, &data->ssl, - "ttls keying material", - EAP_TLS_KEY_LEN); - if (data->key_data) { - wpa_hexdump_key(MSG_DEBUG, - "EAP-TTLS: Derived key", - data->key_data, - EAP_TLS_KEY_LEN); - } else { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to " - "derive key"); - } - - if (*respDataLen == 0) { - if (eap_ttls_decrypt(sm, data, ret, req, NULL, - 0, &resp, respDataLen)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to process early " - "start for Phase 2"); - } - res = 0; - } - data->resuming = 0; - } - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - if (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully"); - data->phase2_success = 1; - } - } else if (sm->workaround && ret->methodState == METHOD_MAY_CONT && - (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully (EAP workaround)"); - data->phase2_success = 1; - } - - if (res == 1) { - return eap_tls_build_ack(&data->ssl, respDataLen, id, - EAP_TYPE_TTLS, 0); - } - return resp; -} - - -static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && - data->phase2_success; -} - - -static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -} - - -static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - free(data->key_data); - data->key_data = NULL; - if (eap_tls_reauth_init(sm, &data->ssl)) { - free(data); - return NULL; - } - data->phase2_start = 0; - data->phase2_success = 0; - data->resuming = 1; - data->reauth = 1; - return priv; -} - - -static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, - size_t buflen, int verbose) -{ - struct eap_ttls_data *data = priv; - int len; - - len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose); - switch (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - len += snprintf(buf + len, buflen - len, - "EAP-TTLS Phase2 method=EAP-%s\n", - data->phase2_method ? data->phase2_method->name - : "?"); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - len += snprintf(buf + len, buflen - len, - "EAP-TTLS Phase2 method=MSCHAPV2\n"); - break; - case EAP_TTLS_PHASE2_MSCHAP: - len += snprintf(buf + len, buflen - len, - "EAP-TTLS Phase2 method=MSCHAP\n"); - break; - case EAP_TTLS_PHASE2_PAP: - len += snprintf(buf + len, buflen - len, - "EAP-TTLS Phase2 method=PAP\n"); - break; - case EAP_TTLS_PHASE2_CHAP: - len += snprintf(buf + len, buflen - len, - "EAP-TTLS Phase2 method=CHAP\n"); - break; - } - - return len; -} - - -static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) -{ - struct eap_ttls_data *data = priv; - return data->key_data != NULL && data->phase2_success; -} - - -static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) -{ - struct eap_ttls_data *data = priv; - u8 *key; - - if (data->key_data == NULL || !data->phase2_success) - return NULL; - - key = malloc(EAP_TLS_KEY_LEN); - if (key == NULL) - return NULL; - - *len = EAP_TLS_KEY_LEN; - memcpy(key, data->key_data, EAP_TLS_KEY_LEN); - - return key; -} - - -const struct eap_method eap_method_ttls = -{ - .method = EAP_TYPE_TTLS, - .name = "TTLS", - .init = eap_ttls_init, - .deinit = eap_ttls_deinit, - .process = eap_ttls_process, - .isKeyAvailable = eap_ttls_isKeyAvailable, - .getKey = eap_ttls_getKey, - .get_status = eap_ttls_get_status, - .has_reauth_data = eap_ttls_has_reauth_data, - .deinit_for_reauth = eap_ttls_deinit_for_reauth, - .init_for_reauth = eap_ttls_init_for_reauth, -}; diff --git a/contrib/wpa_supplicant/eap_ttls.h b/contrib/wpa_supplicant/eap_ttls.h deleted file mode 100644 index a187db4d34f7..000000000000 --- a/contrib/wpa_supplicant/eap_ttls.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef EAP_TTLS_H -#define EAP_TTLS_H - -struct ttls_avp { - u32 avp_code; - u32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - /* optional 32-bit Vendor-ID */ - /* Data */ -}; - -struct ttls_avp_vendor { - u32 avp_code; - u32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - u32 vendor_id; - /* Data */ -}; - -#define AVP_FLAGS_VENDOR 0x80 -#define AVP_FLAGS_MANDATORY 0x40 - -#define AVP_PAD(start, pos) \ -do { \ - int pad; \ - pad = (4 - (((pos) - (start)) & 3)) & 3; \ - memset((pos), 0, pad); \ - pos += pad; \ -} while(0) - - -/* RFC 2865 */ -#define RADIUS_ATTR_USER_NAME 1 -#define RADIUS_ATTR_USER_PASSWORD 2 -#define RADIUS_ATTR_CHAP_PASSWORD 3 -#define RADIUS_ATTR_REPLY_MESSAGE 18 -#define RADIUS_ATTR_CHAP_CHALLENGE 60 -#define RADIUS_ATTR_EAP_MESSAGE 79 - -/* RFC 2548 */ -#define RADIUS_VENDOR_ID_MICROSOFT 311 -#define RADIUS_ATTR_MS_CHAP_RESPONSE 1 -#define RADIUS_ATTR_MS_CHAP_ERROR 2 -#define RADIUS_ATTR_MS_CHAP_NT_ENC_PW 6 -#define RADIUS_ATTR_MS_CHAP_CHALLENGE 11 -#define RADIUS_ATTR_MS_CHAP2_RESPONSE 25 -#define RADIUS_ATTR_MS_CHAP2_SUCCESS 26 -#define RADIUS_ATTR_MS_CHAP2_CPW 27 - -#define EAP_TTLS_MSCHAPV2_CHALLENGE_LEN 16 -#define EAP_TTLS_MSCHAPV2_RESPONSE_LEN 50 -#define EAP_TTLS_MSCHAP_CHALLENGE_LEN 8 -#define EAP_TTLS_MSCHAP_RESPONSE_LEN 50 -#define EAP_TTLS_CHAP_CHALLENGE_LEN 16 -#define EAP_TTLS_CHAP_PASSWORD_LEN 16 - -#endif /* EAP_TTLS_H */ diff --git a/contrib/wpa_supplicant/eapol_sm.c b/contrib/wpa_supplicant/eapol_sm.c deleted file mode 100644 index 1424b7df06d5..000000000000 --- a/contrib/wpa_supplicant/eapol_sm.c +++ /dev/null @@ -1,1420 +0,0 @@ -/* - * WPA Supplicant / EAPOL state machines - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "eapol_sm.h" -#include "eap.h" -#include "eloop.h" -#include "wpa_supplicant.h" -#include "l2_packet.h" -#include "wpa.h" -#include "md5.h" -#include "rc4.h" - - -/* IEEE 802.1aa/D6.1 - Supplicant */ - -struct eapol_sm { - /* Timers */ - unsigned int authWhile; - unsigned int heldWhile; - unsigned int startWhen; - unsigned int idleWhile; /* for EAP state machine */ - - /* Global variables */ - Boolean eapFail; - Boolean eapolEap; - Boolean eapSuccess; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - PortControl portControl; - Boolean portEnabled; - PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ - Boolean portValid; - Boolean suppAbort; - Boolean suppFail; - Boolean suppStart; - Boolean suppSuccess; - Boolean suppTimeout; - - /* Supplicant PAE state machine */ - enum { - SUPP_PAE_UNKNOWN = 0, - SUPP_PAE_DISCONNECTED = 1, - SUPP_PAE_LOGOFF = 2, - SUPP_PAE_CONNECTING = 3, - SUPP_PAE_AUTHENTICATING = 4, - SUPP_PAE_AUTHENTICATED = 5, - /* unused(6) */ - SUPP_PAE_HELD = 7, - SUPP_PAE_RESTART = 8, - SUPP_PAE_S_FORCE_AUTH = 9, - SUPP_PAE_S_FORCE_UNAUTH = 10 - } SUPP_PAE_state; /* dot1xSuppPaeState */ - /* Variables */ - Boolean userLogoff; - Boolean logoffSent; - unsigned int startCount; - Boolean eapRestart; - PortControl sPortMode; - /* Constants */ - unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ - unsigned int startPeriod; /* dot1xSuppStartPeriod */ - unsigned int maxStart; /* dot1xSuppMaxStart */ - - /* Key Receive state machine */ - enum { - KEY_RX_UNKNOWN = 0, - KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE - } KEY_RX_state; - /* Variables */ - Boolean rxKey; - - /* Supplicant Backend state machine */ - enum { - SUPP_BE_UNKNOWN = 0, - SUPP_BE_INITIALIZE = 1, - SUPP_BE_IDLE = 2, - SUPP_BE_REQUEST = 3, - SUPP_BE_RECEIVE = 4, - SUPP_BE_RESPONSE = 5, - SUPP_BE_FAIL = 6, - SUPP_BE_TIMEOUT = 7, - SUPP_BE_SUCCESS = 8 - } SUPP_BE_state; /* dot1xSuppBackendPaeState */ - /* Variables */ - Boolean eapNoResp; - Boolean eapReq; - Boolean eapResp; - /* Constants */ - unsigned int authPeriod; /* dot1xSuppAuthPeriod */ - - /* Statistics */ - unsigned int dot1xSuppEapolFramesRx; - unsigned int dot1xSuppEapolFramesTx; - unsigned int dot1xSuppEapolStartFramesTx; - unsigned int dot1xSuppEapolLogoffFramesTx; - unsigned int dot1xSuppEapolRespFramesTx; - unsigned int dot1xSuppEapolReqIdFramesRx; - unsigned int dot1xSuppEapolReqFramesRx; - unsigned int dot1xSuppInvalidEapolFramesRx; - unsigned int dot1xSuppEapLengthErrorFramesRx; - unsigned int dot1xSuppLastEapolFrameVersion; - unsigned char dot1xSuppLastEapolFrameSource[6]; - - /* Miscellaneous variables (not defined in IEEE 802.1aa/D6.1) */ - Boolean changed; - struct eap_sm *eap; - struct wpa_ssid *config; - Boolean initial_req; - u8 *last_rx_key; - size_t last_rx_key_len; - u8 *eapReqData; /* for EAP */ - size_t eapReqDataLen; /* for EAP */ - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean replay_counter_valid; - u8 last_replay_counter[16]; - struct eapol_config conf; - struct eapol_ctx *ctx; - enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } - cb_status; - Boolean cached_pmk; - - Boolean unicast_key_received, broadcast_key_received; -}; - - -static void eapol_sm_txLogoff(struct eapol_sm *sm); -static void eapol_sm_txStart(struct eapol_sm *sm); -static void eapol_sm_processKey(struct eapol_sm *sm); -static void eapol_sm_getSuppRsp(struct eapol_sm *sm); -static void eapol_sm_txSuppRsp(struct eapol_sm *sm); -static void eapol_sm_abortSupp(struct eapol_sm *sm); -static void eapol_sm_abort_cached(struct eapol_sm *sm); -static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx); - -static struct eapol_callbacks eapol_cb; - - -/* Definitions for clarifying state machine implementation */ -#define SM_STATE(machine, state) \ -static void sm_ ## machine ## _ ## state ## _Enter(struct eapol_sm *sm, \ - int global) - -#define SM_ENTRY(machine, state) \ -if (!global || sm->machine ## _state != machine ## _ ## state) { \ - sm->changed = TRUE; \ - wpa_printf(MSG_DEBUG, "EAPOL: " #machine " entering state " #state); \ -} \ -sm->machine ## _state = machine ## _ ## state; - -#define SM_ENTER(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 0) -#define SM_ENTER_GLOBAL(machine, state) \ -sm_ ## machine ## _ ## state ## _Enter(sm, 1) - -#define SM_STEP(machine) \ -static void sm_ ## machine ## _Step(struct eapol_sm *sm) - -#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) - - -/* Port Timers state machine - implemented as a function that will be called - * once a second as a registered event loop timeout */ -static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_sm *sm = timeout_ctx; - - if (sm->authWhile > 0) - sm->authWhile--; - if (sm->heldWhile > 0) - sm->heldWhile--; - if (sm->startWhen > 0) - sm->startWhen--; - if (sm->idleWhile > 0) - sm->idleWhile--; - wpa_printf(MSG_MSGDUMP, "EAPOL: Port Timers tick - authWhile=%d " - "heldWhile=%d startWhen=%d idleWhile=%d", - sm->authWhile, sm->heldWhile, sm->startWhen, sm->idleWhile); - - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, sm); - eapol_sm_step(sm); -} - - -SM_STATE(SUPP_PAE, LOGOFF) -{ - SM_ENTRY(SUPP_PAE, LOGOFF); - eapol_sm_txLogoff(sm); - sm->logoffSent = TRUE; - sm->suppPortStatus = Unauthorized; -} - - -SM_STATE(SUPP_PAE, DISCONNECTED) -{ - SM_ENTRY(SUPP_PAE, DISCONNECTED); - sm->sPortMode = Auto; - sm->startCount = 0; - sm->logoffSent = FALSE; - sm->suppPortStatus = Unauthorized; - sm->suppAbort = TRUE; - - sm->unicast_key_received = FALSE; - sm->broadcast_key_received = FALSE; -} - - -SM_STATE(SUPP_PAE, CONNECTING) -{ - SM_ENTRY(SUPP_PAE, CONNECTING); - sm->startWhen = sm->startPeriod; - sm->startCount++; - sm->eapolEap = FALSE; - eapol_sm_txStart(sm); -} - - -SM_STATE(SUPP_PAE, AUTHENTICATING) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATING); - sm->startCount = 0; - sm->suppSuccess = FALSE; - sm->suppFail = FALSE; - sm->suppTimeout = FALSE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; - sm->suppStart = TRUE; -} - - -SM_STATE(SUPP_PAE, HELD) -{ - SM_ENTRY(SUPP_PAE, HELD); - sm->heldWhile = sm->heldPeriod; - sm->suppPortStatus = Unauthorized; - sm->cb_status = EAPOL_CB_FAILURE; -} - - -SM_STATE(SUPP_PAE, AUTHENTICATED) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATED); - sm->suppPortStatus = Authorized; - sm->cb_status = EAPOL_CB_SUCCESS; -} - - -SM_STATE(SUPP_PAE, RESTART) -{ - SM_ENTRY(SUPP_PAE, RESTART); - sm->eapRestart = TRUE; -} - - -SM_STATE(SUPP_PAE, S_FORCE_AUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_AUTH); - sm->suppPortStatus = Authorized; - sm->sPortMode = ForceAuthorized; -} - - -SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); - sm->suppPortStatus = Unauthorized; - sm->sPortMode = ForceUnauthorized; - eapol_sm_txLogoff(sm); -} - - -SM_STEP(SUPP_PAE) -{ - if ((sm->userLogoff && !sm->logoffSent) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, LOGOFF); - else if (((sm->portControl == Auto) && - (sm->sPortMode != sm->portControl)) || - sm->initialize || !sm->portEnabled) - SM_ENTER_GLOBAL(SUPP_PAE, DISCONNECTED); - else if ((sm->portControl == ForceAuthorized) && - (sm->sPortMode != sm->portControl) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_AUTH); - else if ((sm->portControl == ForceUnauthorized) && - (sm->sPortMode != sm->portControl) && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER_GLOBAL(SUPP_PAE, S_FORCE_UNAUTH); - else switch (sm->SUPP_PAE_state) { - case SUPP_PAE_UNKNOWN: - break; - case SUPP_PAE_LOGOFF: - if (!sm->userLogoff) - SM_ENTER(SUPP_PAE, DISCONNECTED); - break; - case SUPP_PAE_DISCONNECTED: - SM_ENTER(SUPP_PAE, CONNECTING); - break; - case SUPP_PAE_CONNECTING: - if (sm->startWhen == 0 && sm->startCount < sm->maxStart) - SM_ENTER(SUPP_PAE, CONNECTING); - else if (sm->startWhen == 0 && - sm->startCount >= sm->maxStart && - sm->portValid) - SM_ENTER(SUPP_PAE, AUTHENTICATED); - else if (sm->eapSuccess || sm->eapFail) - SM_ENTER(SUPP_PAE, AUTHENTICATING); - else if (sm->eapolEap) - SM_ENTER(SUPP_PAE, RESTART); - else if (sm->startWhen == 0 && - sm->startCount >= sm->maxStart && - !sm->portValid) - SM_ENTER(SUPP_PAE, HELD); - break; - case SUPP_PAE_AUTHENTICATING: - if (sm->eapSuccess && !sm->portValid && - sm->conf.accept_802_1x_keys && - sm->conf.required_keys == 0) { - wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " - "plaintext connection; no EAPOL-Key frames " - "required"); - sm->portValid = TRUE; - if (sm->ctx->eapol_done_cb) - sm->ctx->eapol_done_cb(sm->ctx->ctx); - } - if (sm->eapSuccess && sm->portValid) - SM_ENTER(SUPP_PAE, AUTHENTICATED); - else if (sm->eapFail || (sm->keyDone && !sm->portValid)) - SM_ENTER(SUPP_PAE, HELD); - else if (sm->suppTimeout) - SM_ENTER(SUPP_PAE, CONNECTING); - break; - case SUPP_PAE_HELD: - if (sm->heldWhile == 0) - SM_ENTER(SUPP_PAE, CONNECTING); - else if (sm->eapolEap) - SM_ENTER(SUPP_PAE, RESTART); - break; - case SUPP_PAE_AUTHENTICATED: - if (sm->eapolEap && sm->portValid) - SM_ENTER(SUPP_PAE, RESTART); - else if (!sm->portValid) - SM_ENTER(SUPP_PAE, DISCONNECTED); - break; - case SUPP_PAE_RESTART: - if (!sm->eapRestart) - SM_ENTER(SUPP_PAE, AUTHENTICATING); - break; - case SUPP_PAE_S_FORCE_AUTH: - break; - case SUPP_PAE_S_FORCE_UNAUTH: - break; - } -} - - -SM_STATE(KEY_RX, NO_KEY_RECEIVE) -{ - SM_ENTRY(KEY_RX, NO_KEY_RECEIVE); -} - - -SM_STATE(KEY_RX, KEY_RECEIVE) -{ - SM_ENTRY(KEY_RX, KEY_RECEIVE); - eapol_sm_processKey(sm); - sm->rxKey = FALSE; -} - - -SM_STEP(KEY_RX) -{ - if (sm->initialize || !sm->portEnabled) - SM_ENTER_GLOBAL(KEY_RX, NO_KEY_RECEIVE); - switch (sm->KEY_RX_state) { - case KEY_RX_UNKNOWN: - break; - case KEY_RX_NO_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - case KEY_RX_KEY_RECEIVE: - if (sm->rxKey) - SM_ENTER(KEY_RX, KEY_RECEIVE); - break; - } -} - - -SM_STATE(SUPP_BE, REQUEST) -{ - SM_ENTRY(SUPP_BE, REQUEST); - sm->authWhile = 0; - sm->eapReq = TRUE; - eapol_sm_getSuppRsp(sm); -} - - -SM_STATE(SUPP_BE, RESPONSE) -{ - SM_ENTRY(SUPP_BE, RESPONSE); - eapol_sm_txSuppRsp(sm); - sm->eapResp = FALSE; -} - - -SM_STATE(SUPP_BE, SUCCESS) -{ - SM_ENTRY(SUPP_BE, SUCCESS); - sm->keyRun = TRUE; - sm->suppSuccess = TRUE; - - if (eap_key_available(sm->eap)) { - /* New key received - clear IEEE 802.1X EAPOL-Key replay - * counter */ - sm->replay_counter_valid = FALSE; - } -} - - -SM_STATE(SUPP_BE, FAIL) -{ - SM_ENTRY(SUPP_BE, FAIL); - sm->suppFail = TRUE; -} - - -SM_STATE(SUPP_BE, TIMEOUT) -{ - SM_ENTRY(SUPP_BE, TIMEOUT); - sm->suppTimeout = TRUE; -} - - -SM_STATE(SUPP_BE, IDLE) -{ - SM_ENTRY(SUPP_BE, IDLE); - sm->suppStart = FALSE; - sm->initial_req = TRUE; -} - - -SM_STATE(SUPP_BE, INITIALIZE) -{ - SM_ENTRY(SUPP_BE, INITIALIZE); - eapol_sm_abortSupp(sm); - sm->suppAbort = FALSE; -} - - -SM_STATE(SUPP_BE, RECEIVE) -{ - SM_ENTRY(SUPP_BE, RECEIVE); - sm->authWhile = sm->authPeriod; - sm->eapolEap = FALSE; - sm->eapNoResp = FALSE; - sm->initial_req = FALSE; -} - - -SM_STEP(SUPP_BE) -{ - if (sm->initialize || sm->suppAbort) - SM_ENTER_GLOBAL(SUPP_BE, INITIALIZE); - else switch (sm->SUPP_BE_state) { - case SUPP_BE_UNKNOWN: - break; - case SUPP_BE_REQUEST: - if (sm->eapResp && sm->eapNoResp) { - wpa_printf(MSG_DEBUG, "EAPOL: SUPP_BE REQUEST: both " - "eapResp and eapNoResp set?!"); - } - if (sm->eapResp) - SM_ENTER(SUPP_BE, RESPONSE); - else if (sm->eapNoResp) - SM_ENTER(SUPP_BE, RECEIVE); - break; - case SUPP_BE_RESPONSE: - SM_ENTER(SUPP_BE, RECEIVE); - break; - case SUPP_BE_SUCCESS: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_FAIL: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_TIMEOUT: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_IDLE: - if (sm->eapFail && sm->suppStart) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->eapolEap && sm->suppStart) - SM_ENTER(SUPP_BE, REQUEST); - else if (sm->eapSuccess && sm->suppStart) - SM_ENTER(SUPP_BE, SUCCESS); - break; - case SUPP_BE_INITIALIZE: - SM_ENTER(SUPP_BE, IDLE); - break; - case SUPP_BE_RECEIVE: - if (sm->eapolEap) - SM_ENTER(SUPP_BE, REQUEST); - else if (sm->eapFail) - SM_ENTER(SUPP_BE, FAIL); - else if (sm->authWhile == 0) - SM_ENTER(SUPP_BE, TIMEOUT); - else if (sm->eapSuccess) - SM_ENTER(SUPP_BE, SUCCESS); - break; - } -} - - -static void eapol_sm_txLogoff(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: txLogoff"); - sm->ctx->eapol_send(sm->ctx->ctx, IEEE802_1X_TYPE_EAPOL_LOGOFF, - (u8 *) "", 0); - sm->dot1xSuppEapolLogoffFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -static void eapol_sm_txStart(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: txStart"); - sm->ctx->eapol_send(sm->ctx->ctx, IEEE802_1X_TYPE_EAPOL_START, - (u8 *) "", 0); - sm->dot1xSuppEapolStartFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -#define IEEE8021X_ENCR_KEY_LEN 32 -#define IEEE8021X_SIGN_KEY_LEN 32 - -struct eap_key_data { - u8 encr_key[IEEE8021X_ENCR_KEY_LEN]; - u8 sign_key[IEEE8021X_SIGN_KEY_LEN]; -}; - - -static void eapol_sm_processKey(struct eapol_sm *sm) -{ - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - struct eap_key_data keydata; - u8 orig_key_sign[IEEE8021X_KEY_SIGN_LEN], datakey[32]; - u8 ekey[IEEE8021X_KEY_IV_LEN + IEEE8021X_ENCR_KEY_LEN]; - int key_len, res, sign_key_len, encr_key_len; - - wpa_printf(MSG_DEBUG, "EAPOL: processKey"); - if (sm->last_rx_key == NULL) - return; - - if (!sm->conf.accept_802_1x_keys) { - wpa_printf(MSG_WARNING, "EAPOL: Received IEEE 802.1X EAPOL-Key" - " even though this was not accepted - " - "ignoring this packet"); - return; - } - - hdr = (struct ieee802_1x_hdr *) sm->last_rx_key; - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - if (sizeof(*hdr) + be_to_host16(hdr->length) > sm->last_rx_key_len) { - wpa_printf(MSG_WARNING, "EAPOL: Too short EAPOL-Key frame"); - return; - } - wpa_printf(MSG_DEBUG, "EAPOL: RX IEEE 802.1X ver=%d type=%d len=%d " - "EAPOL-Key: type=%d key_length=%d key_index=0x%x", - hdr->version, hdr->type, be_to_host16(hdr->length), - key->type, be_to_host16(key->key_length), key->key_index); - - sign_key_len = IEEE8021X_SIGN_KEY_LEN; - encr_key_len = IEEE8021X_ENCR_KEY_LEN; - res = eapol_sm_get_key(sm, (u8 *) &keydata, sizeof(keydata)); - if (res < 0) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get master key for " - "decrypting EAPOL-Key keys"); - return; - } - if (res == 16) { - /* LEAP derives only 16 bytes of keying material. */ - res = eapol_sm_get_key(sm, (u8 *) &keydata, 16); - if (res) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get LEAP " - "master key for decrypting EAPOL-Key keys"); - return; - } - sign_key_len = 16; - encr_key_len = 16; - memcpy(keydata.sign_key, keydata.encr_key, 16); - } else if (res) { - wpa_printf(MSG_DEBUG, "EAPOL: Could not get enough master key " - "data for decrypting EAPOL-Key keys (res=%d)", res); - return; - } - - /* The key replay_counter must increase when same master key */ - if (sm->replay_counter_valid && - memcmp(sm->last_replay_counter, key->replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN) >= 0) { - wpa_printf(MSG_WARNING, "EAPOL: EAPOL-Key replay counter did " - "not increase - ignoring key"); - wpa_hexdump(MSG_DEBUG, "EAPOL: last replay counter", - sm->last_replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN); - wpa_hexdump(MSG_DEBUG, "EAPOL: received replay counter", - key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); - return; - } - - /* Verify key signature (HMAC-MD5) */ - memcpy(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN); - memset(key->key_signature, 0, IEEE8021X_KEY_SIGN_LEN); - hmac_md5(keydata.sign_key, sign_key_len, - sm->last_rx_key, sizeof(*hdr) + be_to_host16(hdr->length), - key->key_signature); - if (memcmp(orig_key_sign, key->key_signature, IEEE8021X_KEY_SIGN_LEN) - != 0) { - wpa_printf(MSG_DEBUG, "EAPOL: Invalid key signature in " - "EAPOL-Key packet"); - memcpy(key->key_signature, orig_key_sign, - IEEE8021X_KEY_SIGN_LEN); - return; - } - wpa_printf(MSG_DEBUG, "EAPOL: EAPOL-Key key signature verified"); - - key_len = be_to_host16(hdr->length) - sizeof(*key); - if (key_len > 32 || be_to_host16(key->key_length) > 32) { - wpa_printf(MSG_WARNING, "EAPOL: Too long key data length %d", - key_len ? key_len : be_to_host16(key->key_length)); - return; - } - if (key_len == be_to_host16(key->key_length)) { - memcpy(ekey, key->key_iv, IEEE8021X_KEY_IV_LEN); - memcpy(ekey + IEEE8021X_KEY_IV_LEN, keydata.encr_key, - encr_key_len); - memcpy(datakey, key + 1, key_len); - rc4(datakey, key_len, ekey, - IEEE8021X_KEY_IV_LEN + encr_key_len); - wpa_hexdump_key(MSG_DEBUG, "EAPOL: Decrypted(RC4) key", - datakey, key_len); - } else if (key_len == 0) { - /* IEEE 802.1X-REV specifies that least significant Key Length - * octets from MS-MPPE-Send-Key are used as the key if the key - * data is not present. This seems to be meaning the beginning - * of the MS-MPPE-Send-Key. In addition, MS-MPPE-Send-Key in - * Supplicant corresponds to MS-MPPE-Recv-Key in Authenticator. - * Anyway, taking the beginning of the keying material from EAP - * seems to interoperate with Authenticators. */ - key_len = be_to_host16(key->key_length); - memcpy(datakey, keydata.encr_key, key_len); - wpa_hexdump_key(MSG_DEBUG, "EAPOL: using part of EAP keying " - "material data encryption key", - datakey, key_len); - } else { - wpa_printf(MSG_DEBUG, "EAPOL: Invalid key data length %d " - "(key_length=%d)", key_len, - be_to_host16(key->key_length)); - return; - } - - sm->replay_counter_valid = TRUE; - memcpy(sm->last_replay_counter, key->replay_counter, - IEEE8021X_REPLAY_COUNTER_LEN); - - wpa_printf(MSG_DEBUG, "EAPOL: Setting dynamic WEP key: %s keyidx %d " - "len %d", - key->key_index & IEEE8021X_KEY_INDEX_FLAG ? - "unicast" : "broadcast", - key->key_index & IEEE8021X_KEY_INDEX_MASK, key_len); - - if (sm->ctx->set_wep_key && - sm->ctx->set_wep_key(sm->ctx->ctx, - key->key_index & IEEE8021X_KEY_INDEX_FLAG, - key->key_index & IEEE8021X_KEY_INDEX_MASK, - datakey, key_len) < 0) { - wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " - " driver."); - } else { - if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) - sm->unicast_key_received = TRUE; - else - sm->broadcast_key_received = TRUE; - - if ((sm->unicast_key_received || - !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && - (sm->broadcast_key_received || - !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_BROADCAST))) - { - wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " - "frames received"); - sm->portValid = TRUE; - if (sm->ctx->eapol_done_cb) - sm->ctx->eapol_done_cb(sm->ctx->ctx); - } - } -} - - -static void eapol_sm_getSuppRsp(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "EAPOL: getSuppRsp"); - /* EAP layer processing; no special code is needed, since Supplicant - * Backend state machine is waiting for eapNoResp or eapResp to be set - * and these are only set in the EAP state machine when the processing - * has finished. */ -} - - -static void eapol_sm_txSuppRsp(struct eapol_sm *sm) -{ - u8 *resp; - size_t resp_len; - - wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp"); - resp = eap_get_eapRespData(sm->eap, &resp_len); - if (resp == NULL) { - wpa_printf(MSG_WARNING, "EAPOL: txSuppRsp - EAP response data " - "not available"); - return; - } - - /* Send EAP-Packet from the EAP layer to the Authenticator */ - sm->ctx->eapol_send(sm->ctx->ctx, IEEE802_1X_TYPE_EAP_PACKET, - resp, resp_len); - - /* eapRespData is not used anymore, so free it here */ - free(resp); - - if (sm->initial_req) - sm->dot1xSuppEapolReqIdFramesRx++; - else - sm->dot1xSuppEapolReqFramesRx++; - sm->dot1xSuppEapolRespFramesTx++; - sm->dot1xSuppEapolFramesTx++; -} - - -static void eapol_sm_abortSupp(struct eapol_sm *sm) -{ - /* release system resources that may have been allocated for the - * authentication session */ - free(sm->last_rx_key); - sm->last_rx_key = NULL; - free(sm->eapReqData); - sm->eapReqData = NULL; - eap_sm_abort(sm->eap); -} - - -struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) -{ - struct eapol_sm *sm; - sm = malloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - memset(sm, 0, sizeof(*sm)); - sm->ctx = ctx; - - sm->portControl = Auto; - - /* Supplicant PAE state machine */ - sm->heldPeriod = 60; - sm->startPeriod = 30; - sm->maxStart = 3; - - /* Supplicant Backend state machine */ - sm->authPeriod = 30; - - sm->eap = eap_sm_init(sm, &eapol_cb, sm->ctx->msg_ctx); - if (sm->eap == NULL) { - free(sm); - return NULL; - } - - /* Initialize EAPOL state machines */ - sm->initialize = TRUE; - eapol_sm_step(sm); - sm->initialize = FALSE; - eapol_sm_step(sm); - - eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm); - - return sm; -} - - -void eapol_sm_deinit(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); - eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); - eap_sm_deinit(sm->eap); - free(sm->last_rx_key); - free(sm->eapReqData); - free(sm->ctx); - free(sm); -} - - -static void eapol_sm_step_timeout(void *eloop_ctx, void *timeout_ctx) -{ - eapol_sm_step(timeout_ctx); -} - - -void eapol_sm_step(struct eapol_sm *sm) -{ - int i; - - /* In theory, it should be ok to run this in loop until !changed. - * However, it is better to use a limit on number of iterations to - * allow events (e.g., SIGTERM) to stop the program cleanly if the - * state machine were to generate a busy loop. */ - for (i = 0; i < 100; i++) { - sm->changed = FALSE; - SM_STEP_RUN(SUPP_PAE); - SM_STEP_RUN(KEY_RX); - SM_STEP_RUN(SUPP_BE); - if (eap_sm_step(sm->eap)) - sm->changed = TRUE; - } - - if (sm->changed) { - /* restart EAPOL state machine step from timeout call in order - * to allow other events to be processed. */ - eloop_cancel_timeout(eapol_sm_step_timeout, NULL, sm); - eloop_register_timeout(0, 0, eapol_sm_step_timeout, NULL, sm); - } - - if (sm->ctx->cb && sm->cb_status != EAPOL_CB_IN_PROGRESS) { - int success = sm->cb_status == EAPOL_CB_SUCCESS ? 1 : 0; - sm->cb_status = EAPOL_CB_IN_PROGRESS; - sm->ctx->cb(sm, success, sm->ctx->cb_ctx); - } -} - - -static const char *eapol_supp_pae_state(int state) -{ - switch (state) { - case SUPP_PAE_LOGOFF: - return "LOGOFF"; - case SUPP_PAE_DISCONNECTED: - return "DISCONNECTED"; - case SUPP_PAE_CONNECTING: - return "CONNECTING"; - case SUPP_PAE_AUTHENTICATING: - return "AUTHENTICATING"; - case SUPP_PAE_HELD: - return "HELD"; - case SUPP_PAE_AUTHENTICATED: - return "AUTHENTICATED"; - case SUPP_PAE_RESTART: - return "RESTART"; - default: - return "UNKNOWN"; - } -} - - -static const char *eapol_supp_be_state(int state) -{ - switch (state) { - case SUPP_BE_REQUEST: - return "REQUEST"; - case SUPP_BE_RESPONSE: - return "RESPONSE"; - case SUPP_BE_SUCCESS: - return "SUCCESS"; - case SUPP_BE_FAIL: - return "FAIL"; - case SUPP_BE_TIMEOUT: - return "TIMEOUT"; - case SUPP_BE_IDLE: - return "IDLE"; - case SUPP_BE_INITIALIZE: - return "INITIALIZE"; - case SUPP_BE_RECEIVE: - return "RECEIVE"; - default: - return "UNKNOWN"; - } -} - - -static const char * eapol_port_status(PortStatus status) -{ - if (status == Authorized) - return "Authorized"; - else - return "Unauthorized"; -} - - -static const char * eapol_port_control(PortControl ctrl) -{ - switch (ctrl) { - case Auto: - return "Auto"; - case ForceUnauthorized: - return "ForceUnauthorized"; - case ForceAuthorized: - return "ForceAuthorized"; - default: - return "Unknown"; - } -} - - -void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, - int startPeriod, int maxStart) -{ - if (sm == NULL) - return; - if (heldPeriod >= 0) - sm->heldPeriod = heldPeriod; - if (authPeriod >= 0) - sm->authPeriod = authPeriod; - if (startPeriod >= 0) - sm->startPeriod = startPeriod; - if (maxStart >= 0) - sm->maxStart = maxStart; -} - - -int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, - int verbose) -{ - int len; - if (sm == NULL) - return 0; - - len = snprintf(buf, buflen, - "Supplicant PAE state=%s\n" - "suppPortStatus=%s\n", - eapol_supp_pae_state(sm->SUPP_PAE_state), - eapol_port_status(sm->suppPortStatus)); - - if (verbose) { - len += snprintf(buf + len, buflen - len, - "heldPeriod=%d\n" - "authPeriod=%d\n" - "startPeriod=%d\n" - "maxStart=%d\n" - "portControl=%s\n" - "Supplicant Backend state=%s\n", - sm->heldPeriod, - sm->authPeriod, - sm->startPeriod, - sm->maxStart, - eapol_port_control(sm->portControl), - eapol_supp_be_state(sm->SUPP_BE_state)); - } - - len += eap_sm_get_status(sm->eap, buf + len, buflen - len, verbose); - - return len; -} - - -int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen) -{ - int len; - if (sm == NULL) - return 0; - len = snprintf(buf, buflen, - "dot1xSuppPaeState=%d\n" - "dot1xSuppHeldPeriod=%d\n" - "dot1xSuppAuthPeriod=%d\n" - "dot1xSuppStartPeriod=%d\n" - "dot1xSuppMaxStart=%d\n" - "dot1xSuppSuppControlledPortStatus=%s\n" - "dot1xSuppBackendPaeState=%d\n" - "dot1xSuppEapolFramesRx=%d\n" - "dot1xSuppEapolFramesTx=%d\n" - "dot1xSuppEapolStartFramesTx=%d\n" - "dot1xSuppEapolLogoffFramesTx=%d\n" - "dot1xSuppEapolRespFramesTx=%d\n" - "dot1xSuppEapolReqIdFramesRx=%d\n" - "dot1xSuppEapolReqFramesRx=%d\n" - "dot1xSuppInvalidEapolFramesRx=%d\n" - "dot1xSuppEapLengthErrorFramesRx=%d\n" - "dot1xSuppLastEapolFrameVersion=%d\n" - "dot1xSuppLastEapolFrameSource=" MACSTR "\n", - sm->SUPP_PAE_state, - sm->heldPeriod, - sm->authPeriod, - sm->startPeriod, - sm->maxStart, - sm->suppPortStatus == Authorized ? - "Authorized" : "Unauthorized", - sm->SUPP_BE_state, - sm->dot1xSuppEapolFramesRx, - sm->dot1xSuppEapolFramesTx, - sm->dot1xSuppEapolStartFramesTx, - sm->dot1xSuppEapolLogoffFramesTx, - sm->dot1xSuppEapolRespFramesTx, - sm->dot1xSuppEapolReqIdFramesRx, - sm->dot1xSuppEapolReqFramesRx, - sm->dot1xSuppInvalidEapolFramesRx, - sm->dot1xSuppEapLengthErrorFramesRx, - sm->dot1xSuppLastEapolFrameVersion, - MAC2STR(sm->dot1xSuppLastEapolFrameSource)); - return len; -} - - -void eapol_sm_rx_eapol(struct eapol_sm *sm, u8 *src, u8 *buf, size_t len) -{ - struct ieee802_1x_hdr *hdr; - struct ieee802_1x_eapol_key *key; - int plen, data_len; - - if (sm == NULL) - return; - sm->dot1xSuppEapolFramesRx++; - if (len < sizeof(*hdr)) { - sm->dot1xSuppInvalidEapolFramesRx++; - return; - } - hdr = (struct ieee802_1x_hdr *) buf; - sm->dot1xSuppLastEapolFrameVersion = hdr->version; - memcpy(sm->dot1xSuppLastEapolFrameSource, src, ETH_ALEN); - if (hdr->version < EAPOL_VERSION) { - /* TODO: backwards compatibility */ - } - plen = be_to_host16(hdr->length); - if (plen > len - sizeof(*hdr)) { - sm->dot1xSuppEapLengthErrorFramesRx++; - return; - } - data_len = plen + sizeof(*hdr); - - switch (hdr->type) { - case IEEE802_1X_TYPE_EAP_PACKET: - if (sm->cached_pmk) { - /* Trying to use PMKSA caching, but Authenticator did - * not seem to have a matching entry. Need to restart - * EAPOL state machines. - */ - eapol_sm_abort_cached(sm); - } - free(sm->eapReqData); - sm->eapReqDataLen = plen; - sm->eapReqData = malloc(sm->eapReqDataLen); - if (sm->eapReqData) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " - "frame"); - memcpy(sm->eapReqData, (u8 *) (hdr + 1), - sm->eapReqDataLen); - sm->eapolEap = TRUE; - eapol_sm_step(sm); - } - break; - case IEEE802_1X_TYPE_EAPOL_KEY: - if (plen < sizeof(*key)) { - wpa_printf(MSG_DEBUG, "EAPOL: Too short EAPOL-Key " - "frame received"); - break; - } - key = (struct ieee802_1x_eapol_key *) (hdr + 1); - if (key->type == EAPOL_KEY_TYPE_WPA || - key->type == EAPOL_KEY_TYPE_RSN) { - /* WPA Supplicant takes care of this frame. */ - wpa_printf(MSG_DEBUG, "EAPOL: Ignoring WPA EAPOL-Key " - "frame in EAPOL state machines"); - break; - } - if (key->type != EAPOL_KEY_TYPE_RC4) { - wpa_printf(MSG_DEBUG, "EAPOL: Ignored unknown " - "EAPOL-Key type %d", key->type); - break; - } - free(sm->last_rx_key); - sm->last_rx_key = malloc(data_len); - if (sm->last_rx_key) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAPOL-Key " - "frame"); - memcpy(sm->last_rx_key, buf, data_len); - sm->last_rx_key_len = data_len; - sm->rxKey = TRUE; - eapol_sm_step(sm); - } - break; - default: - wpa_printf(MSG_DEBUG, "EAPOL: Received unknown EAPOL type %d", - hdr->type); - sm->dot1xSuppInvalidEapolFramesRx++; - break; - } -} - - -void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) -{ - if (sm) - sm->dot1xSuppEapolFramesTx++; -} - - -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portEnabled=%d", enabled); - sm->portEnabled = enabled; - eapol_sm_step(sm); -} - - -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portValid=%d", valid); - sm->portValid = valid; - eapol_sm_step(sm); -} - - -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "EAP success=%d", success); - sm->eapSuccess = success; - sm->altAccept = success; - if (success) - eap_notify_success(sm->eap); - eapol_sm_step(sm); -} - - -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "EAP fail=%d", fail); - sm->eapFail = fail; - sm->altReject = fail; - eapol_sm_step(sm); -} - - -void eapol_sm_notify_config(struct eapol_sm *sm, struct wpa_ssid *config, - struct eapol_config *conf) -{ - if (sm == NULL) - return; - - sm->config = config; - - if (conf == NULL) - return; - - sm->conf.accept_802_1x_keys = conf->accept_802_1x_keys; - sm->conf.required_keys = conf->required_keys; - sm->conf.fast_reauth = conf->fast_reauth; - if (sm->eap) { - eap_set_fast_reauth(sm->eap, conf->fast_reauth); - eap_set_workaround(sm->eap, conf->workaround); - } -} - - -int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) -{ - u8 *eap_key; - size_t eap_len; - - if (sm == NULL || !eap_key_available(sm->eap)) - return -1; - eap_key = eap_get_eapKeyData(sm->eap, &eap_len); - if (eap_key == NULL) - return -1; - if (len > eap_len) - return eap_len; - memcpy(key, eap_key, len); - return 0; -} - - -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) -{ - if (sm) { - sm->userLogoff = logoff; - eapol_sm_step(sm); - } -} - - -void eapol_sm_notify_cached(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED; - sm->suppPortStatus = Authorized; - eap_notify_success(sm->eap); -} - - -void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt) -{ - if (sm == NULL) - return; - if (attempt) { - wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); - sm->cached_pmk = TRUE; - } else { - wpa_printf(MSG_DEBUG, "RSN: Do not try to use cached PMKSA"); - sm->cached_pmk = FALSE; - } -} - - -static void eapol_sm_abort_cached(struct eapol_sm *sm) -{ - wpa_printf(MSG_DEBUG, "RSN: Authenticator did not accept PMKID, " - "doing full EAP authentication"); - if (sm == NULL) - return; - sm->cached_pmk = FALSE; - sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; - sm->suppPortStatus = Unauthorized; - sm->eapRestart= TRUE; -} - - -void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx) -{ - if (sm) { - sm->ctx->scard_ctx = ctx; - eap_register_scard_ctx(sm->eap, ctx); - } -} - - -void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAPOL: External notification - " - "portControl=%s", eapol_port_control(portControl)); - sm->portControl = portControl; - eapol_sm_step(sm); -} - - -void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - eap_sm_notify_ctrl_attached(sm->eap); -} - - -void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) -{ - if (sm == NULL) - return; - if (sm->eapReqData && !sm->eapReq) { - wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " - "input) notification - retrying pending EAP " - "Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; - eapol_sm_step(sm); - } -} - - -static struct wpa_ssid * eapol_sm_get_config(void *ctx) -{ - struct eapol_sm *sm = ctx; - return sm ? sm->config : NULL; -} - - -static u8 * eapol_sm_get_eapReqData(void *ctx, size_t *len) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL || sm->eapReqData == NULL) { - *len = 0; - return NULL; - } - - *len = sm->eapReqDataLen; - return sm->eapReqData; -} - - -static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return FALSE; - switch (variable) { - case EAPOL_eapSuccess: - return sm->eapSuccess; - case EAPOL_eapRestart: - return sm->eapRestart; - case EAPOL_eapFail: - return sm->eapFail; - case EAPOL_eapResp: - return sm->eapResp; - case EAPOL_eapNoResp: - return sm->eapNoResp; - case EAPOL_eapReq: - return sm->eapReq; - case EAPOL_portEnabled: - return sm->portEnabled; - case EAPOL_altAccept: - return sm->altAccept; - case EAPOL_altReject: - return sm->altReject; - } - return FALSE; -} - - -static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - switch (variable) { - case EAPOL_eapSuccess: - sm->eapSuccess = value; - break; - case EAPOL_eapRestart: - sm->eapRestart = value; - break; - case EAPOL_eapFail: - sm->eapFail = value; - break; - case EAPOL_eapResp: - sm->eapResp = value; - break; - case EAPOL_eapNoResp: - sm->eapNoResp = value; - break; - case EAPOL_eapReq: - sm->eapReq = value; - break; - case EAPOL_portEnabled: - sm->portEnabled = value; - break; - case EAPOL_altAccept: - sm->altAccept = value; - break; - case EAPOL_altReject: - sm->altReject = value; - break; - } -} - - -static unsigned int eapol_sm_get_int(void *ctx, enum eapol_int_var variable) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return 0; - switch (variable) { - case EAPOL_idleWhile: - return sm->idleWhile; - } - return 0; -} - - -static void eapol_sm_set_int(void *ctx, enum eapol_int_var variable, - unsigned int value) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL) - return; - switch (variable) { - case EAPOL_idleWhile: - sm->idleWhile = value; - break; - } -} - - -static struct eapol_callbacks eapol_cb = -{ - .get_config = eapol_sm_get_config, - .get_bool = eapol_sm_get_bool, - .set_bool = eapol_sm_set_bool, - .get_int = eapol_sm_get_int, - .set_int = eapol_sm_set_int, - .get_eapReqData = eapol_sm_get_eapReqData, -}; diff --git a/contrib/wpa_supplicant/eapol_sm.h b/contrib/wpa_supplicant/eapol_sm.h deleted file mode 100644 index b9412030c1f3..000000000000 --- a/contrib/wpa_supplicant/eapol_sm.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef EAPOL_SM_H -#define EAPOL_SM_H - -#include "defs.h" - -typedef enum { Unauthorized, Authorized } PortStatus; -typedef enum { Auto, ForceUnauthorized, ForceAuthorized } PortControl; - -struct eapol_config { - int accept_802_1x_keys; -#define EAPOL_REQUIRE_KEY_UNICAST BIT(0) -#define EAPOL_REQUIRE_KEY_BROADCAST BIT(1) - int required_keys; /* which EAPOL-Key packets are required before - * marking connection authenticated */ - int fast_reauth; /* whether fast EAP reauthentication is enabled */ - int workaround; /* whether EAP workarounds are enabled */ -}; - -struct eapol_sm; - -struct eapol_ctx { - void *ctx; /* pointer to arbitrary upper level context */ - int preauth; /* This EAPOL state machine is used for IEEE 802.11i/RSN - * pre-authentication */ - void (*cb)(struct eapol_sm *eapol, int success, void *ctx); - void *cb_ctx, *msg_ctx, *scard_ctx; - void (*eapol_done_cb)(void *ctx); - int (*eapol_send)(void *ctx, int type, u8 *buf, size_t len); - int (*set_wep_key)(void *ctx, int unicast, int keyidx, - u8 *key, size_t keylen); -}; - - -struct wpa_ssid; - -#ifdef IEEE8021X_EAPOL -struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx); -void eapol_sm_deinit(struct eapol_sm *sm); -void eapol_sm_step(struct eapol_sm *sm); -int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, - int verbose); -int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen); -void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, - int startPeriod, int maxStart); -void eapol_sm_rx_eapol(struct eapol_sm *sm, u8 *src, u8 *buf, size_t len); -void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm); -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled); -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid); -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success); -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail); -void eapol_sm_notify_config(struct eapol_sm *sm, struct wpa_ssid *config, - struct eapol_config *conf); -int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len); -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff); -void eapol_sm_notify_cached(struct eapol_sm *sm); -void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm, int attempt); -void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx); -void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl); -void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm); -void eapol_sm_notify_ctrl_response(struct eapol_sm *sm); -#else /* IEEE8021X_EAPOL */ -static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) -{ - return (struct eapol_sm *) 1; -} -static inline void eapol_sm_deinit(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_step(struct eapol_sm *sm) -{ -} -static inline int eapol_sm_get_status(struct eapol_sm *sm, char *buf, - size_t buflen, int verbose) -{ - return 0; -} -static inline int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, - size_t buflen) -{ - return 0; -} -static inline void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, - int authPeriod, int startPeriod, - int maxStart) -{ -} -static inline void eapol_sm_rx_eapol(struct eapol_sm *sm, u8 *src, u8 *buf, - size_t len) -{ -} -static inline void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_portEnabled(struct eapol_sm *sm, - Boolean enabled) -{ -} -static inline void eapol_sm_notify_portValid(struct eapol_sm *sm, - Boolean valid) -{ -} -static inline void eapol_sm_notify_eap_success(struct eapol_sm *sm, - Boolean success) -{ -} -static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) -{ -} -static inline void eapol_sm_notify_config(struct eapol_sm *sm, - struct wpa_ssid *config, - struct eapol_config *conf) -{ -} -static inline int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) -{ - return -1; -} -static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) -{ -} -static inline void eapol_sm_notify_cached(struct eapol_sm *sm) -{ -} -#define eapol_sm_notify_pmkid_attempt(sm, attempt) do { } while (0) -#define eapol_sm_register_scard_ctx(sm, ctx) do { } while (0) -static inline void eapol_sm_notify_portControl(struct eapol_sm *sm, - PortControl portControl) -{ -} -static inline void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) -{ -} -static inline void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) -{ -} -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAPOL_SM_H */ diff --git a/contrib/wpa_supplicant/eapol_test.c b/contrib/wpa_supplicant/eapol_test.c deleted file mode 100644 index 061ae893d668..000000000000 --- a/contrib/wpa_supplicant/eapol_test.c +++ /dev/null @@ -1,1012 +0,0 @@ -/* - * WPA Supplicant - test code - * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c. - * Not used in production version. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <unistd.h> -#include <ctype.h> -#include <string.h> -#include <signal.h> -#include <netinet/in.h> -#include <assert.h> -#include <arpa/inet.h> - -#include "common.h" -#include "config.h" -#include "eapol_sm.h" -#include "eloop.h" -#include "wpa.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "wpa_supplicant_i.h" -#include "radius.h" -#include "radius_client.h" -#include "l2_packet.h" -#include "ctrl_iface.h" -#include "pcsc_funcs.h" - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -static int eapol_test_num_reauths = 0; -static int no_mppe_keys = 0; -static int num_mppe_ok = 0, num_mppe_mismatch = 0; - -static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx); - - -void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = malloc(buflen); - if (buf == NULL) { - printf("Failed to allocate message buffer for:\n"); - va_start(ap, fmt); - vprintf(fmt, ap); - printf("\n"); - va_end(ap); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s", buf); - wpa_supplicant_ctrl_iface_send(wpa_s, level, buf, len); - free(buf); -} - - -void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event, - union wpa_event_data *data) -{ -} - - -int rsn_preauth_init(struct wpa_supplicant *wpa_s, u8 *dst) -{ - return -1; -} - - -void rsn_preauth_deinit(struct wpa_supplicant *wpa_s) -{ -} - - -int pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len) -{ - return 0; -} - - -int wpa_get_mib(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) -{ - return 0; -} - - -void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) -{ -} - - -const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len) -{ - return NULL; -} - - -int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) -{ - return -1; -} - - -static void ieee802_1x_encapsulate_radius(struct wpa_supplicant *wpa_s, - u8 *eap, size_t len) -{ - struct radius_msg *msg; - char buf[128]; - struct eap_hdr *hdr; - u8 *pos; - - wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " - "packet"); - - wpa_s->radius_identifier = radius_client_get_id(wpa_s); - msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, - wpa_s->radius_identifier); - if (msg == NULL) { - printf("Could not create net RADIUS packet\n"); - return; - } - - radius_msg_make_authenticator(msg, (u8 *) wpa_s, sizeof(*wpa_s)); - - hdr = (struct eap_hdr *) eap; - pos = (u8 *) (hdr + 1); - if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE && - pos[0] == EAP_TYPE_IDENTITY) { - pos++; - free(wpa_s->eap_identity); - wpa_s->eap_identity_len = len - sizeof(*hdr) - 1; - wpa_s->eap_identity = malloc(wpa_s->eap_identity_len); - if (wpa_s->eap_identity) { - memcpy(wpa_s->eap_identity, pos, - wpa_s->eap_identity_len); - wpa_hexdump(MSG_DEBUG, "Learned identity from " - "EAP-Response-Identity", - wpa_s->eap_identity, - wpa_s->eap_identity_len); - } - } - - if (wpa_s->eap_identity && - !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, - wpa_s->eap_identity, - wpa_s->eap_identity_len)) { - printf("Could not add User-Name\n"); - goto fail; - } - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &wpa_s->own_ip_addr, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - - snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(wpa_s->own_addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, strlen(buf))) { - printf("Could not add Calling-Station-Id\n"); - goto fail; - } - - /* TODO: should probably check MTU from driver config; 2304 is max for - * IEEE 802.11, but use 1400 to avoid problems with too large packets - */ - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_FRAMED_MTU, 1400)) { - printf("Could not add Framed-MTU\n"); - goto fail; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_NAS_PORT_TYPE, - RADIUS_NAS_PORT_TYPE_IEEE_802_11)) { - printf("Could not add NAS-Port-Type\n"); - goto fail; - } - - snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - - if (eap && !radius_msg_add_eap(msg, eap, len)) { - printf("Could not add EAP-Message\n"); - goto fail; - } - - /* State attribute must be copied if and only if this packet is - * Access-Request reply to the previous Access-Challenge */ - if (wpa_s->last_recv_radius && wpa_s->last_recv_radius->hdr->code == - RADIUS_CODE_ACCESS_CHALLENGE) { - int res = radius_msg_copy_attr(msg, wpa_s->last_recv_radius, - RADIUS_ATTR_STATE); - if (res < 0) { - printf("Could not copy State attribute from previous " - "Access-Challenge\n"); - goto fail; - } - if (res > 0) { - wpa_printf(MSG_DEBUG, " Copied RADIUS State " - "Attribute"); - } - } - - radius_client_send(wpa_s, msg, RADIUS_AUTH, wpa_s->own_addr); - return; - - fail: - radius_msg_free(msg); - free(msg); -} - - -static int eapol_test_eapol_send(void *ctx, int type, u8 *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - printf("WPA: wpa_eapol_send(type=%d len=%d)\n", type, len); - if (type == IEEE802_1X_TYPE_EAP_PACKET) { - wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len); - ieee802_1x_encapsulate_radius(wpa_s, buf, len); - } - return 0; -} - - -static void eapol_test_eapol_done_cb(void *ctx) -{ - printf("WPA: EAPOL processing complete\n"); -} - - -static void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n"); - wpa_s->radius_access_accept_received = 0; - send_eap_request_identity(eloop_ctx, timeout_ctx); -} - - -static int eapol_test_compare_pmk(struct wpa_supplicant *wpa_s) -{ - u8 pmk[PMK_LEN]; - int ret = 1; - - if (eapol_sm_get_key(wpa_s->eapol, pmk, PMK_LEN) == 0) { - wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN); - if (memcmp(pmk, wpa_s->authenticator_pmk, PMK_LEN) != 0) - printf("WARNING: PMK mismatch\n"); - else if (wpa_s->radius_access_accept_received) - ret = 0; - } else if (wpa_s->authenticator_pmk_len == 16 && - eapol_sm_get_key(wpa_s->eapol, pmk, 16) == 0) { - wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16); - if (memcmp(pmk, wpa_s->authenticator_pmk, 16) != 0) - printf("WARNING: PMK mismatch\n"); - else if (wpa_s->radius_access_accept_received) - ret = 0; - } else if (wpa_s->radius_access_accept_received && no_mppe_keys) { - /* No keying material expected */ - ret = 0; - } - - if (ret) - num_mppe_mismatch++; - else if (!no_mppe_keys) - num_mppe_ok++; - - return ret; -} - - -static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - printf("eapol_sm_cb: success=%d\n", success); - eapol_test_num_reauths--; - if (eapol_test_num_reauths < 0) - eloop_terminate(); - else { - eapol_test_compare_pmk(wpa_s); - eloop_register_timeout(0, 100000, eapol_sm_reauth, - wpa_s, NULL); - } -} - - -static int test_eapol(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - ctx = malloc(sizeof(*ctx)); - if (ctx == NULL) { - printf("Failed to allocate EAPOL context.\n"); - return -1; - } - memset(ctx, 0, sizeof(*ctx)); - ctx->ctx = wpa_s; - ctx->msg_ctx = wpa_s; - ctx->scard_ctx = wpa_s->scard; - ctx->cb = eapol_sm_cb; - ctx->cb_ctx = wpa_s; - ctx->preauth = 0; - ctx->eapol_done_cb = eapol_test_eapol_done_cb; - ctx->eapol_send = eapol_test_eapol_send; - - wpa_s->eapol = eapol_sm_init(ctx); - if (wpa_s->eapol == NULL) { - free(ctx); - printf("Failed to initialize EAPOL state machines.\n"); - return -1; - } - - wpa_s->current_ssid = ssid; - memset(&eapol_conf, 0, sizeof(eapol_conf)); - eapol_conf.accept_802_1x_keys = 1; - eapol_conf.required_keys = 0; - eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; - eapol_conf.workaround = ssid->eap_workaround; - eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf); - eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); - - - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); - - return 0; -} - - -static void test_eapol_clean(struct wpa_supplicant *wpa_s) -{ - radius_client_deinit(wpa_s); - free(wpa_s->last_eap_radius); - if (wpa_s->last_recv_radius) { - radius_msg_free(wpa_s->last_recv_radius); - free(wpa_s->last_recv_radius); - } - free(wpa_s->eap_identity); - wpa_s->eap_identity = NULL; - eapol_sm_deinit(wpa_s->eapol); - wpa_s->eapol = NULL; - if (wpa_s->auth_server) { - free(wpa_s->auth_server->shared_secret); - free(wpa_s->auth_server); - } - scard_deinit(wpa_s->scard); - wpa_supplicant_ctrl_iface_deinit(wpa_s); - wpa_config_free(wpa_s->conf); -} - - -static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - u8 buf[100], *pos; - struct ieee802_1x_hdr *hdr; - struct eap_hdr *eap; - - hdr = (struct ieee802_1x_hdr *) buf; - hdr->version = EAPOL_VERSION; - hdr->type = IEEE802_1X_TYPE_EAP_PACKET; - hdr->length = htons(5); - - eap = (struct eap_hdr *) (hdr + 1); - eap->code = EAP_CODE_REQUEST; - eap->identifier = 0; - eap->length = htons(5); - pos = (u8 *) (eap + 1); - *pos = EAP_TYPE_IDENTITY; - - printf("Sending fake EAP-Request-Identity\n"); - eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf, - sizeof(*hdr) + 5); -} - - -static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - printf("EAPOL test timed out\n"); - wpa_s->auth_timed_out = 1; - eloop_terminate(); -} - - -static char *eap_type_text(u8 type) -{ - switch (type) { - case EAP_TYPE_IDENTITY: return "Identity"; - case EAP_TYPE_NOTIFICATION: return "Notification"; - case EAP_TYPE_NAK: return "Nak"; - case EAP_TYPE_TLS: return "TLS"; - case EAP_TYPE_TTLS: return "TTLS"; - case EAP_TYPE_PEAP: return "PEAP"; - case EAP_TYPE_SIM: return "SIM"; - case EAP_TYPE_GTC: return "GTC"; - case EAP_TYPE_MD5: return "MD5"; - case EAP_TYPE_OTP: return "OTP"; - default: return "Unknown"; - } -} - - -static void ieee802_1x_decapsulate_radius(struct wpa_supplicant *wpa_s) -{ - u8 *eap; - size_t len; - struct eap_hdr *hdr; - int eap_type = -1; - char buf[64]; - struct radius_msg *msg; - - if (wpa_s->last_recv_radius == NULL) - return; - - msg = wpa_s->last_recv_radius; - - eap = radius_msg_get_eap(msg, &len); - if (eap == NULL) { - /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3: - * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message - * attribute */ - wpa_printf(MSG_DEBUG, "could not extract " - "EAP-Message from RADIUS message"); - free(wpa_s->last_eap_radius); - wpa_s->last_eap_radius = NULL; - wpa_s->last_eap_radius_len = 0; - return; - } - - if (len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "too short EAP packet " - "received from authentication server"); - free(eap); - return; - } - - if (len > sizeof(*hdr)) - eap_type = eap[sizeof(*hdr)]; - - hdr = (struct eap_hdr *) eap; - switch (hdr->code) { - case EAP_CODE_REQUEST: - snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_RESPONSE: - snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_SUCCESS: - snprintf(buf, sizeof(buf), "EAP Success"); - /* LEAP uses EAP Success within an authentication, so must not - * stop here with eloop_terminate(); */ - break; - case EAP_CODE_FAILURE: - snprintf(buf, sizeof(buf), "EAP Failure"); - eloop_terminate(); - break; - default: - snprintf(buf, sizeof(buf), "unknown EAP code"); - wpa_hexdump(MSG_DEBUG, "Decapsulated EAP packet", eap, len); - break; - } - wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d " - "id=%d len=%d) from RADIUS server: %s", - hdr->code, hdr->identifier, ntohs(hdr->length), buf); - - /* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */ - - if (wpa_s->last_eap_radius) - free(wpa_s->last_eap_radius); - wpa_s->last_eap_radius = eap; - wpa_s->last_eap_radius_len = len; - - { - struct ieee802_1x_hdr *hdr; - hdr = malloc(sizeof(*hdr) + len); - assert(hdr != NULL); - hdr->version = EAPOL_VERSION; - hdr->type = IEEE802_1X_TYPE_EAP_PACKET; - hdr->length = htons(len); - memcpy((u8 *) (hdr + 1), eap, len); - eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, - (u8 *) hdr, sizeof(*hdr) + len); - free(hdr); - } -} - - -static void ieee802_1x_get_keys(struct wpa_supplicant *wpa_s, - struct radius_msg *msg, struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len) -{ - struct radius_ms_mppe_keys *keys; - - keys = radius_msg_get_ms_keys(msg, req, shared_secret, - shared_secret_len); - if (keys && keys->send == NULL && keys->recv == NULL) { - free(keys); - keys = radius_msg_get_cisco_keys(msg, req, shared_secret, - shared_secret_len); - } - - if (keys) { - if (keys->send) { - wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)", - keys->send, keys->send_len); - } - if (keys->recv) { - wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)", - keys->recv, keys->recv_len); - wpa_s->authenticator_pmk_len = - keys->recv_len > PMK_LEN ? PMK_LEN : - keys->recv_len; - memcpy(wpa_s->authenticator_pmk, keys->recv, - wpa_s->authenticator_pmk_len); - } - - free(keys->send); - free(keys->recv); - free(keys); - } -} - - -/* Process the RADIUS frames from Authentication Server */ -static RadiusRxResult -ieee802_1x_receive_auth(struct wpa_supplicant *wpa_s, - struct radius_msg *msg, struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be - * present when packet contains an EAP-Message attribute */ - if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT && - radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, - 0) < 0 && - radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { - wpa_printf(MSG_DEBUG, "Allowing RADIUS " - "Access-Reject without Message-Authenticator " - "since it does not include EAP-Message\n"); - } else if (radius_msg_verify(msg, shared_secret, shared_secret_len, - req)) { - printf("Incoming RADIUS packet did not have correct " - "Message-Authenticator - dropped\n"); - return RADIUS_RX_UNKNOWN; - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT && - msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - wpa_s->radius_identifier = -1; - wpa_printf(MSG_DEBUG, "RADIUS packet matching with station"); - - if (wpa_s->last_recv_radius) { - radius_msg_free(wpa_s->last_recv_radius); - free(wpa_s->last_recv_radius); - } - - wpa_s->last_recv_radius = msg; - - switch (msg->hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - wpa_s->radius_access_accept_received = 1; - ieee802_1x_get_keys(wpa_s, msg, req, shared_secret, - shared_secret_len); - break; - case RADIUS_CODE_ACCESS_REJECT: - wpa_s->radius_access_reject_received = 1; - break; - } - - ieee802_1x_decapsulate_radius(wpa_s); - - if ((msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT && - eapol_test_num_reauths < 0) || - msg->hdr->code == RADIUS_CODE_ACCESS_REJECT) { - eloop_terminate(); - } - - return RADIUS_RX_QUEUED; -} - - -static void wpa_supplicant_imsi_identity(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - int aka = 0; - u8 *pos = ssid->eap_methods; - - while (pos && *pos != EAP_TYPE_NONE) { - if (*pos == EAP_TYPE_AKA) { - aka = 1; - break; - } - pos++; - } - - if (ssid->identity == NULL && wpa_s->imsi) { - ssid->identity = malloc(1 + wpa_s->imsi_len); - if (ssid->identity) { - ssid->identity[0] = aka ? '0' : '1'; - memcpy(ssid->identity + 1, wpa_s->imsi, - wpa_s->imsi_len); - ssid->identity_len = 1 + wpa_s->imsi_len; - wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " - "IMSI", ssid->identity, - ssid->identity_len); - } - } -} - - -static void wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - char buf[100]; - size_t len; - - if (ssid->pcsc == NULL) - return; - if (wpa_s->scard != NULL) { - wpa_supplicant_imsi_identity(wpa_s, ssid); - return; - } - wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM - " - "initialize PCSC"); - wpa_s->scard = scard_init(SCARD_TRY_BOTH, ssid->pin); - if (wpa_s->scard == NULL) { - wpa_printf(MSG_WARNING, "Failed to initialize SIM " - "(pcsc-lite)"); - /* TODO: what to do here? */ - return; - } - eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); - - len = sizeof(buf); - if (scard_get_imsi(wpa_s->scard, buf, &len)) { - wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); - /* TODO: what to do here? */ - return; - } - - wpa_hexdump(MSG_DEBUG, "IMSI", (u8 *) buf, len); - free(wpa_s->imsi); - wpa_s->imsi = malloc(len); - if (wpa_s->imsi) { - memcpy(wpa_s->imsi, buf, len); - wpa_s->imsi_len = len; - wpa_supplicant_imsi_identity(wpa_s, ssid); - } -} - - -static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *authsrv, - int port, const char *secret) -{ - struct hostapd_radius_server *as; - int res; - - wpa_s->bssid[5] = 1; - wpa_s->own_addr[5] = 2; - wpa_s->own_ip_addr.s_addr = htonl((127 << 24) | 1); - strncpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname)); - - wpa_s->num_auth_servers = 1; - as = malloc(sizeof(struct hostapd_radius_server)); - assert(as != NULL); - inet_aton(authsrv, &as->addr); - as->port = port; - as->shared_secret = (u8 *) strdup(secret); - as->shared_secret_len = strlen(secret); - wpa_s->auth_server = wpa_s->auth_servers = as; - - - res = radius_client_init(wpa_s); - assert(res == 0); - - res = radius_client_register(wpa_s, RADIUS_AUTH, - ieee802_1x_receive_auth, NULL); - assert(res == 0); -} - - -static int scard_test(void) -{ - struct scard_data *scard; - size_t len; - char imsi[20]; - unsigned char rand[16]; -#ifdef PCSC_FUNCS - unsigned char sres[4]; - unsigned char kc[8]; -#endif /* PCSC_FUNCS */ -#define num_triplets 5 - unsigned char rand_[num_triplets][16]; - unsigned char sres_[num_triplets][4]; - unsigned char kc_[num_triplets][8]; - int i, j, res; - -#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 - unsigned char aka_rand[AKA_RAND_LEN]; - unsigned char aka_autn[AKA_AUTN_LEN]; - unsigned char aka_auts[AKA_AUTS_LEN]; - unsigned char aka_res[RES_MAX_LEN]; - size_t aka_res_len; - unsigned char aka_ik[IK_LEN]; - unsigned char aka_ck[CK_LEN]; - - scard = scard_init(SCARD_TRY_BOTH, "1234"); - if (scard == NULL) - return -1; - - len = sizeof(imsi); - if (scard_get_imsi(scard, imsi, &len)) - goto failed; - wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len); - /* NOTE: Permanent Username: 1 | IMSI */ - - memset(rand, 0, sizeof(rand)); - if (scard_gsm_auth(scard, rand, sres, kc)) - goto failed; - - memset(rand, 0xff, sizeof(rand)); - if (scard_gsm_auth(scard, rand, sres, kc)) - goto failed; - - for (i = 0; i < num_triplets; i++) { - memset(rand_[i], i, sizeof(rand_[i])); - if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i])) - goto failed; - } - - for (i = 0; i < num_triplets; i++) { - printf("1"); - for (j = 0; j < len; j++) - printf("%c", imsi[j]); - printf(","); - for (j = 0; j < 16; j++) - printf("%02X", rand_[i][j]); - printf(","); - for (j = 0; j < 4; j++) - printf("%02X", sres_[i][j]); - printf(","); - for (j = 0; j < 8; j++) - printf("%02X", kc_[i][j]); - printf("\n"); - } - - wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication"); - - /* seq 39 (0x28) */ - memset(aka_rand, 0xaa, 16); - memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf" - "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16); - - res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len, - aka_ik, aka_ck, aka_auts); - if (res == 0) { - wpa_printf(MSG_DEBUG, "UMTS auth completed successfully"); - wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len); - wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN); - wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN); - } else if (res == -2) { - wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization " - "failure"); - wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN); - } else { - wpa_printf(MSG_DEBUG, "UMTS auth failed"); - } - -failed: - scard_deinit(scard); - - return 0; -#undef num_triplets -} - - -static int scard_get_triplets(int argc, char *argv[]) -{ - struct scard_data *scard; - size_t len; - char imsi[20]; - unsigned char rand[16]; - unsigned char sres[4]; - unsigned char kc[8]; - int num_triplets; - int i, j; - - if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) { - printf("invalid parameters for sim command\n"); - return -1; - } - - if (argc <= 2 || strcmp(argv[2], "debug") != 0) { - /* disable debug output */ - wpa_debug_level = 99; - } - - scard = scard_init(SCARD_GSM_SIM_ONLY, argv[0]); - if (scard == NULL) { - printf("Failed to open smartcard connection\n"); - return -1; - } - - len = sizeof(imsi); - if (scard_get_imsi(scard, imsi, &len)) { - scard_deinit(scard); - return -1; - } - - for (i = 0; i < num_triplets; i++) { - memset(rand, i, sizeof(rand)); - if (scard_gsm_auth(scard, rand, sres, kc)) - break; - - /* IMSI:Kc:SRES:RAND */ - for (j = 0; j < len; j++) - printf("%c", imsi[j]); - printf(":"); - for (j = 0; j < 8; j++) - printf("%02X", kc[j]); - printf(":"); - for (j = 0; j < 4; j++) - printf("%02X", sres[j]); - printf(":"); - for (j = 0; j < 16; j++) - printf("%02X", rand[j]); - printf("\n"); - } - - scard_deinit(scard); - - return 0; -} - - -static void eapol_test_terminate(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -static void usage(void) -{ - printf("usage:\n" - "eapol_test [-n] -c<conf> [-a<AS IP>] [-p<AS port>] " - "[-s<AS secret>] [-r<count>]\n" - "eapol_test scard\n" - "eapol_test sim <PIN> <num triplets> [debug]\n" - "\n" - "options:\n" - " -c<conf> = configuration file\n" - " -a<AS IP> = IP address of the authentication server, " - "default 127.0.0.1\n" - " -p<AS port> = UDP port of the authentication server, " - "default 1812\n" - " -s<AS secret> = shared secret with the authentication " - "server, default 'radius'\n" - " -r<count> = number of re-authentications\n" - " -n = no MPPE keys expected\n"); -} - - -int main(int argc, char *argv[]) -{ - struct wpa_supplicant wpa_s; - int c, ret = 1; - char *as_addr = "127.0.0.1"; - int as_port = 1812; - char *as_secret = "radius"; - char *conf = NULL; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - for (;;) { - c = getopt(argc, argv, "a:c:np:r:s:"); - if (c < 0) - break; - switch (c) { - case 'a': - as_addr = optarg; - break; - case 'c': - conf = optarg; - break; - case 'n': - no_mppe_keys++; - break; - case 'p': - as_port = atoi(optarg); - break; - case 'r': - eapol_test_num_reauths = atoi(optarg); - break; - case 's': - as_secret = optarg; - break; - default: - usage(); - return -1; - } - } - - if (argc > optind && strcmp(argv[optind], "scard") == 0) { - return scard_test(); - } - - if (argc > optind && strcmp(argv[optind], "sim") == 0) { - return scard_get_triplets(argc - optind - 1, - &argv[optind + 1]); - } - - if (conf == NULL) { - usage(); - printf("Configuration file is required.\n"); - return -1; - } - - eloop_init(&wpa_s); - - memset(&wpa_s, 0, sizeof(wpa_s)); - wpa_s.conf = wpa_config_read(conf); - if (wpa_s.conf == NULL) { - printf("Failed to parse configuration file '%s'.\n", conf); - return -1; - } - if (wpa_s.conf->ssid == NULL) { - printf("No networks defined.\n"); - return -1; - } - - wpa_init_conf(&wpa_s, as_addr, as_port, as_secret); - if (wpa_supplicant_ctrl_iface_init(&wpa_s)) { - printf("Failed to initialize control interface '%s'.\n" - "You may have another eapol_test process already " - "running or the file was\n" - "left by an unclean termination of eapol_test in " - "which case you will need\n" - "to manually remove this file before starting " - "eapol_test again.\n", - wpa_s.conf->ctrl_interface); - return -1; - } - wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid); - - if (test_eapol(&wpa_s, wpa_s.conf->ssid)) - return -1; - - eloop_register_timeout(30, 0, eapol_test_timeout, &wpa_s, NULL); - eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL); - eloop_register_signal(SIGINT, eapol_test_terminate, NULL); - eloop_register_signal(SIGTERM, eapol_test_terminate, NULL); - eloop_register_signal(SIGHUP, eapol_test_terminate, NULL); - eloop_run(); - - if (eapol_test_compare_pmk(&wpa_s) == 0) - ret = 0; - if (wpa_s.auth_timed_out) - ret = -2; - if (wpa_s.radius_access_reject_received) - ret = -3; - - test_eapol_clean(&wpa_s); - - eloop_destroy(); - - printf("MPPE keys OK: %d mismatch: %d\n", - num_mppe_ok, num_mppe_mismatch); - if (num_mppe_mismatch) - ret = -4; - if (ret) - printf("FAILURE\n"); - else - printf("SUCCESS\n"); - - return ret; -} diff --git a/contrib/wpa_supplicant/eloop.c b/contrib/wpa_supplicant/eloop.c deleted file mode 100644 index 60715089beb2..000000000000 --- a/contrib/wpa_supplicant/eloop.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Event loop - * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#include <errno.h> -#include <signal.h> - -#ifdef CONFIG_NATIVE_WINDOWS -#include "common.h" -#endif /* CONFIG_NATIVE_WINDOWS */ - -#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 timeval 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 { - void *user_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; -}; - -static struct eloop_data eloop; - - -void eloop_init(void *user_data) -{ - memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; -} - - -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; - - 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--; -} - - -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; - gettimeofday(&timeout->time, NULL); - timeout->time.tv_sec += secs; - timeout->time.tv_usec += usecs; - while (timeout->time.tv_usec >= 1000000) { - timeout->time.tv_sec++; - timeout->time.tv_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 (timercmp(&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; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void eloop_handle_alarm(int sig) -{ - fprintf(stderr, "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.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; - signal(sig, eloop_handle_signal); - - return 0; -} - - -void eloop_run(void) -{ - fd_set rfds; - int i, res; - struct timeval tv, now; - - while (!eloop.terminate && - (eloop.timeout || eloop.reader_count > 0)) { - if (eloop.timeout) { - gettimeofday(&now, NULL); - if (timercmp(&now, &eloop.timeout->time, <)) - timersub(&eloop.timeout->time, &now, &tv); - else - tv.tv_sec = tv.tv_usec = 0; -#if 0 - printf("next timeout in %lu.%06lu sec\n", - tv.tv_sec, tv.tv_usec); -#endif - } - - FD_ZERO(&rfds); - for (i = 0; i < eloop.reader_count; i++) - FD_SET(eloop.readers[i].sock, &rfds); - res = select(eloop.max_sock + 1, &rfds, NULL, NULL, - eloop.timeout ? &tv : NULL); - if (res < 0 && errno != EINTR) { - perror("select"); - return; - } - eloop_process_pending_signals(); - - /* check if some registered timeouts have occurred */ - if (eloop.timeout) { - struct eloop_timeout *tmp; - - gettimeofday(&now, NULL); - if (!timercmp(&now, &eloop.timeout->time, <)) { - tmp = eloop.timeout; - eloop.timeout = eloop.timeout->next; - tmp->handler(tmp->eloop_data, - tmp->user_data); - free(tmp); - } - - } - - if (res <= 0) - continue; - - for (i = 0; i < eloop.reader_count; i++) { - if (FD_ISSET(eloop.readers[i].sock, &rfds)) { - eloop.readers[i].handler( - eloop.readers[i].sock, - eloop.readers[i].eloop_data, - eloop.readers[i].user_data); - } - } - } -} - - -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; -} diff --git a/contrib/wpa_supplicant/eloop.h b/contrib/wpa_supplicant/eloop.h deleted file mode 100644 index f5b884740421..000000000000 --- a/contrib/wpa_supplicant/eloop.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef ELOOP_H -#define ELOOP_H - -/* Magic number for eloop_cancel_timeout() */ -#define ELOOP_ALL_CTX (void *) -1 - -/* Initialize global event loop data - must be called before any other eloop_* - * function. user_data is a pointer to global data structure and will be passed - * as eloop_ctx to signal handlers. */ -void eloop_init(void *user_data); - -/* Register handler for read event */ -int eloop_register_read_sock(int sock, - void (*handler)(int sock, void *eloop_ctx, - void *sock_ctx), - void *eloop_data, void *user_data); -void eloop_unregister_read_sock(int sock); - -/* Register timeout */ -int eloop_register_timeout(unsigned int secs, unsigned int usecs, - void (*handler)(void *eloop_ctx, void *timeout_ctx), - void *eloop_data, void *user_data); - -/* Cancel timeouts matching <handler,eloop_data,user_data>. - * ELOOP_ALL_CTX can be used as a wildcard for cancelling all timeouts - * regardless of eloop_data/user_data. */ -int eloop_cancel_timeout(void (*handler)(void *eloop_ctx, void *sock_ctx), - void *eloop_data, void *user_data); - -/* Register handler for signal. - * Note: signals are 'global' events and there is no local eloop_data pointer - * like with other handlers. The (global) pointer given to eloop_init() will be - * used as eloop_ctx for signal handlers. */ -int eloop_register_signal(int sock, - void (*handler)(int sig, void *eloop_ctx, - void *signal_ctx), - void *user_data); - -/* Start event loop and continue running as long as there are any registered - * event handlers. */ -void eloop_run(void); - -/* Terminate event loop even if there are registered events. */ -void eloop_terminate(void); - -/* Free any reserved resources. After calling eloop_destoy(), other eloop_* - * functions must not be called before re-running eloop_init(). */ -void eloop_destroy(void); - -/* Check whether event loop has been terminated. */ -int eloop_terminated(void); - -#endif /* ELOOP_H */ diff --git a/contrib/wpa_supplicant/hostap_common.h b/contrib/wpa_supplicant/hostap_common.h deleted file mode 100644 index 003ad9ac6b58..000000000000 --- a/contrib/wpa_supplicant/hostap_common.h +++ /dev/null @@ -1,557 +0,0 @@ -#ifndef HOSTAP_COMMON_H -#define HOSTAP_COMMON_H - -#define BIT(x) (1 << (x)) - -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - - - -/* IEEE 802.11 defines */ - -#define WLAN_FC_PVER (BIT(1) | BIT(0)) -#define WLAN_FC_TODS BIT(8) -#define WLAN_FC_FROMDS BIT(9) -#define WLAN_FC_MOREFRAG BIT(10) -#define WLAN_FC_RETRY BIT(11) -#define WLAN_FC_PWRMGT BIT(12) -#define WLAN_FC_MOREDATA BIT(13) -#define WLAN_FC_ISWEP BIT(14) -#define WLAN_FC_ORDER BIT(15) - -#define WLAN_FC_GET_TYPE(fc) (((fc) & (BIT(3) | BIT(2))) >> 2) -#define WLAN_FC_GET_STYPE(fc) \ - (((fc) & (BIT(7) | BIT(6) | BIT(5) | BIT(4))) >> 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 - -/* 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 - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 - -#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) - -/* Status codes */ -#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 -/* 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.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 - -/* Reason codes */ -#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.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_CHALLENGE 16 -#define WLAN_EID_RSN 48 -#define WLAN_EID_GENERIC 221 - - -/* HFA384X Configuration RIDs */ -#define HFA384X_RID_CNFPORTTYPE 0xFC00 -#define HFA384X_RID_CNFOWNMACADDR 0xFC01 -#define HFA384X_RID_CNFDESIREDSSID 0xFC02 -#define HFA384X_RID_CNFOWNCHANNEL 0xFC03 -#define HFA384X_RID_CNFOWNSSID 0xFC04 -#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05 -#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06 -#define HFA384X_RID_CNFMAXDATALEN 0xFC07 -#define HFA384X_RID_CNFWDSADDRESS 0xFC08 -#define HFA384X_RID_CNFPMENABLED 0xFC09 -#define HFA384X_RID_CNFPMEPS 0xFC0A -#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B -#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C -#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D -#define HFA384X_RID_CNFOWNNAME 0xFC0E -#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10 -#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */ -#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */ -#define HFA384X_RID_UNKNOWN1 0xFC20 -#define HFA384X_RID_UNKNOWN2 0xFC21 -#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23 -#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24 -#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25 -#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26 -#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27 -#define HFA384X_RID_CNFWEPFLAGS 0xFC28 -#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29 -#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A -#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */ -#define HFA384X_RID_CNFTXCONTROL 0xFC2C -#define HFA384X_RID_CNFROAMINGMODE 0xFC2D -#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */ -#define HFA384X_RID_CNFRCVCRCERROR 0xFC30 -#define HFA384X_RID_CNFMMLIFE 0xFC31 -#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32 -#define HFA384X_RID_CNFBEACONINT 0xFC33 -#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */ -#define HFA384X_RID_CNFSTAPCFINFO 0xFC35 -#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37 -#define HFA384X_RID_CNFTIMCTRL 0xFC40 -#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */ -#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */ -#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */ -#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0; - * write only */ -#define HFA384X_RID_PROPAGATIONDELAY 0xFC49 /* added in STA f/w 1.7.6 */ -#define HFA384X_RID_GROUPADDRESSES 0xFC80 -#define HFA384X_RID_CREATEIBSS 0xFC81 -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82 -#define HFA384X_RID_RTSTHRESHOLD 0xFC83 -#define HFA384X_RID_TXRATECONTROL 0xFC84 -#define HFA384X_RID_PROMISCUOUSMODE 0xFC85 -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */ -#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0 -#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1 -#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2 -#define HFA384X_RID_CNFBASICRATES 0xFCB3 -#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4 -#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */ -#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */ -#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */ -#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */ -#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */ -#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */ -#define HFA384X_RID_LED_CTRL 0xFCC4 /* added in STA f/w 1.7.6 */ -#define HFA384X_RID_HFODELAY 0xFCC5 /* added in STA f/w 1.7.6 */ -#define HFA384X_RID_DISALLOWEDBSSID 0xFCC6 /* added in STA f/w 1.8.0 */ -#define HFA384X_RID_TICKTIME 0xFCE0 -#define HFA384X_RID_SCANREQUEST 0xFCE1 -#define HFA384X_RID_JOINREQUEST 0xFCE2 -#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */ -#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */ -#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */ - -/* HFA384X Information RIDs */ -#define HFA384X_RID_MAXLOADTIME 0xFD00 -#define HFA384X_RID_DOWNLOADBUFFER 0xFD01 -#define HFA384X_RID_PRIID 0xFD02 -#define HFA384X_RID_PRISUPRANGE 0xFD03 -#define HFA384X_RID_CFIACTRANGES 0xFD04 -#define HFA384X_RID_NICSERNUM 0xFD0A -#define HFA384X_RID_NICID 0xFD0B -#define HFA384X_RID_MFISUPRANGE 0xFD0C -#define HFA384X_RID_CFISUPRANGE 0xFD0D -#define HFA384X_RID_CHANNELLIST 0xFD10 -#define HFA384X_RID_REGULATORYDOMAINS 0xFD11 -#define HFA384X_RID_TEMPTYPE 0xFD12 -#define HFA384X_RID_CIS 0xFD13 -#define HFA384X_RID_STAID 0xFD20 -#define HFA384X_RID_STASUPRANGE 0xFD21 -#define HFA384X_RID_MFIACTRANGES 0xFD22 -#define HFA384X_RID_CFIACTRANGES2 0xFD23 -#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1; - * only Prism2.5(?) */ -#define HFA384X_RID_PORTSTATUS 0xFD40 -#define HFA384X_RID_CURRENTSSID 0xFD41 -#define HFA384X_RID_CURRENTBSSID 0xFD42 -#define HFA384X_RID_COMMSQUALITY 0xFD43 -#define HFA384X_RID_CURRENTTXRATE 0xFD44 -#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45 -#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46 -#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47 -#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48 -#define HFA384X_RID_LONGRETRYLIMIT 0xFD49 -#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A -#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B -#define HFA384X_RID_CFPOLLABLE 0xFD4C -#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D -#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F -#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */ -#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */ -#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */ -#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */ -#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */ -#define HFA384X_RID_ASSOCIATIONFAILURE 0xFD8D /* added in STA f/w 1.8.0 */ -#define HFA384X_RID_PHYTYPE 0xFDC0 -#define HFA384X_RID_CURRENTCHANNEL 0xFDC1 -#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2 -#define HFA384X_RID_CCAMODE 0xFDC3 -#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6 -#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */ -#define HFA384X_RID_BUILDSEQ 0xFFFE -#define HFA384X_RID_FWID 0xFFFF - - -struct hfa384x_comp_ident -{ - u16 id; - u16 variant; - u16 major; - u16 minor; -} __attribute__ ((packed)); - -#define HFA384X_COMP_ID_PRI 0x15 -#define HFA384X_COMP_ID_STA 0x1f -#define HFA384X_COMP_ID_FW_AP 0x14b - -struct hfa384x_sup_range -{ - u16 role; - u16 id; - u16 variant; - u16 bottom; - u16 top; -} __attribute__ ((packed)); - - -struct hfa384x_build_id -{ - u16 pri_seq; - u16 sec_seq; -} __attribute__ ((packed)); - -/* FD01 - Download Buffer */ -struct hfa384x_rid_download_buffer -{ - u16 page; - u16 offset; - u16 length; -} __attribute__ ((packed)); - -/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */ -struct hfa384x_comms_quality { - u16 comm_qual; /* 0 .. 92 */ - u16 signal_level; /* 27 .. 154 */ - u16 noise_level; /* 27 .. 154 */ -} __attribute__ ((packed)); - - -/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ - -/* New wireless extensions API - SET/GET convention (even ioctl numbers are - * root only) - */ -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) -#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) -#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) -#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) -#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) -#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) -#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) -#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) -#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) -#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) -#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) - -/* following are not in SIOCGIWPRIV list; check permission in the driver code - */ -#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) - - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - PRISM2_PARAM_ENH_SEC = 30, - PRISM2_PARAM_IO_DEBUG = 31, - PRISM2_PARAM_BASIC_RATES = 32, - PRISM2_PARAM_OPER_RATES = 33, - PRISM2_PARAM_HOSTAPD = 34, - PRISM2_PARAM_HOSTAPD_STA = 35, - PRISM2_PARAM_WPA = 36, - PRISM2_PARAM_PRIVACY_INVOKED = 37, - PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, - PRISM2_PARAM_DROP_UNENCRYPTED = 39, -}; - -enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, - HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; - - -/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ -enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, - AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, - AP_MAC_CMD_KICKALL = 4 }; - - -/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ -enum { - PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, - /* Note! Old versions of prism2_srec have a fatal error in CRC-16 - * calculation, which will corrupt all non-volatile downloads. - * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to - * prevent use of old versions of prism2_srec for non-volatile - * download. */ - PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */, - PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */, - /* Persistent versions of volatile download commands (keep firmware - * data in memory and automatically re-download after hw_reset */ - PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5, - PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6, -}; - -struct prism2_download_param { - u32 dl_cmd; - u32 start_addr; - u32 num_areas; - struct prism2_download_area { - u32 addr; /* wlan card address */ - u32 len; - caddr_t ptr; /* pointer to data in user space */ - } data[0]; -}; - -#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 -#define PRISM2_MAX_DOWNLOAD_LEN 262144 - - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, - PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_RID_HDR_LEN \ -((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) - -/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() - */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u16 aid; - u16 capability; - u8 tx_supp_rates; - } add_sta; - struct { - u32 inactive_sec; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0]; - } rid; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - - -#endif /* HOSTAP_COMMON_H */ diff --git a/contrib/wpa_supplicant/l2_packet.h b/contrib/wpa_supplicant/l2_packet.h deleted file mode 100644 index 3e3914ca5502..000000000000 --- a/contrib/wpa_supplicant/l2_packet.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef L2_PACKET_H -#define L2_PACKET_H - -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL 0x888e -#endif - -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif - -struct l2_packet_data; - -struct l2_ethhdr { - u8 h_dest[ETH_ALEN]; - u8 h_source[ETH_ALEN]; - u16 h_proto; -} __attribute__ ((packed)); - -struct l2_packet_data * l2_packet_init( - const char *ifname, const u8 *own_addr, unsigned short protocol, - void (*rx_callback)(void *ctx, unsigned char *src_addr, - unsigned char *buf, size_t len), - void *rx_callback_ctx); -void l2_packet_deinit(struct l2_packet_data *l2); - -int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr); -int l2_packet_send(struct l2_packet_data *l2, u8 *buf, size_t len); -void l2_packet_set_rx_l2_hdr(struct l2_packet_data *l2, int rx_l2_hdr); - -#endif /* L2_PACKET_H */ diff --git a/contrib/wpa_supplicant/md5.c b/contrib/wpa_supplicant/md5.c deleted file mode 100644 index 1564e8f64797..000000000000 --- a/contrib/wpa_supplicant/md5.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "md5.h" - - -void md5_mac(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - MD5_CTX context; - MD5Init(&context); - MD5Update(&context, key, key_len); - MD5Update(&context, data, data_len); - MD5Update(&context, key, key_len); - MD5Final(mac, &context); -} - - -/* HMAC code is based on RFC 2104 */ -void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - MD5_CTX context; - u8 k_ipad[65]; /* inner padding - key XORd with ipad */ - u8 k_opad[65]; /* outer padding - key XORd with opad */ - u8 tk[16]; - int i; - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - MD5Init(&context); - MD5Update(&context, key, key_len); - MD5Final(tk, &context); - - 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 pads */ - memset(k_ipad, 0, sizeof(k_ipad)); - memset(k_opad, 0, sizeof(k_opad)); - memcpy(k_ipad, key, key_len); - memcpy(k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - /* perform inner MD5 */ - MD5Init(&context); /* init context for 1st pass */ - MD5Update(&context, k_ipad, 64); /* start with inner pad */ - /* then text of datagram; all fragments */ - for (i = 0; i < num_elem; i++) { - MD5Update(&context, addr[i], len[i]); - } - MD5Final(mac, &context); /* finish up 1st pass */ - - /* perform outer MD5 */ - MD5Init(&context); /* init context for 2nd pass */ - MD5Update(&context, k_opad, 64); /* start with outer pad */ - MD5Update(&context, mac, 16); /* then results of 1st hash */ - MD5Final(mac, &context); /* finish up 2nd pass */ -} - - -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); -} - - -#ifndef EAP_TLS_FUNCS - -/* ===== 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 -void byteReverse(unsigned char *buf, unsigned longs); - -#ifndef ASM_MD5 -/* - * Note: this code is harmless on little-endian machines. - */ -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 -#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) { - memcpy(p, buf, len); - return; - } - 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) { - 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. */ - - 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 */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (u32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - 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); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* 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<<s | 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. - */ -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; -} - -#endif -/* ===== end - public domain MD5 implementation ===== */ - -#endif /* !EAP_TLS_FUNCS */ diff --git a/contrib/wpa_supplicant/md5.h b/contrib/wpa_supplicant/md5.h deleted file mode 100644 index cc3eb950b507..000000000000 --- a/contrib/wpa_supplicant/md5.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MD5_H -#define MD5_H - -#ifdef EAP_TLS_FUNCS - -#include <openssl/md5.h> - -#define MD5Init MD5_Init -#define MD5Update MD5_Update -#define MD5Final MD5_Final -#define MD5Transform MD5_Transform - -#define MD5_MAC_LEN MD5_DIGEST_LENGTH - -#else /* EAP_TLS_FUNCS */ - -#define MD5_MAC_LEN 16 - -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); -void MD5Transform(u32 buf[4], u32 const in[16]); - -typedef struct MD5Context MD5_CTX; - -#endif /* EAP_TLS_FUNCS */ - - -void md5_mac(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); - -#endif /* MD5_H */ diff --git a/contrib/wpa_supplicant/ms_funcs.c b/contrib/wpa_supplicant/ms_funcs.c deleted file mode 100644 index 590b58949d74..000000000000 --- a/contrib/wpa_supplicant/ms_funcs.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "sha1.h" -#include "ms_funcs.h" -#include "crypto.h" - - -static void challenge_hash(u8 *peer_challenge, u8 *auth_challenge, - 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; - - sha1_vector(3, addr, len, hash); - memcpy(challenge, hash, 8); -} - - -void nt_password_hash(u8 *password, size_t password_len, u8 *password_hash) -{ - u8 *buf; - int i; - - /* Convert password into unicode */ - buf = malloc(password_len * 2); - if (buf == NULL) - return; - memset(buf, 0, password_len * 2); - for (i = 0; i < password_len; i++) - buf[2 * i] = password[i]; - - md4(buf, password_len * 2, password_hash); - free(buf); -} - - -void hash_nt_password_hash(u8 *password_hash, u8 *password_hash_hash) -{ - md4(password_hash, 16, password_hash_hash); -} - - -void challenge_response(u8 *challenge, 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]; - memset(zpwd + 2, 0, 5); - des_encrypt(challenge, zpwd, response + 16); -} - - -void generate_nt_response(u8 *auth_challenge, u8 *peer_challenge, - u8 *username, size_t username_len, - 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); - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -void generate_authenticator_response(u8 *password, size_t password_len, - u8 *peer_challenge, - u8 *auth_challenge, - u8 *username, size_t username_len, - 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[16], 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; - - nt_password_hash(password, password_len, password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - sha1_vector(3, addr1, len1, response); - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - sha1_vector(3, addr2, len2, response); -} - - -void nt_challenge_response(u8 *challenge, u8 *password, size_t password_len, - u8 *response) -{ - u8 password_hash[16]; - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/* IN: 16-octet password_hash_hash and 24-octet nt_response - * OUT: 16-octet master_key */ -void 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; - - sha1_vector(3, addr, len, hash); - memcpy(master_key, hash, 16); -} - - -void 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; - - sha1_vector(4, addr, len, digest); - - if (session_key_len > SHA1_MAC_LEN) - session_key_len = SHA1_MAC_LEN; - memcpy(session_key, digest, session_key_len); -} - - -#ifdef TEST_MAIN_MS_FUNCS -int main(int argc, char *argv[]) -{ - /* Test vector from RFC2759 example */ - u8 *username = "User"; - u8 *password = "clientPass"; - u8 auth_challenge[] = { - 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E, - 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28 - }; - u8 peer_challenge[] = { - 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, - 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E - }; - u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 }; - u8 password_hash[] = { - 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6, - 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE - }; - u8 nt_response[] = { - 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E, - 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54, - 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF - }; - u8 password_hash_hash[] = { - 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C, - 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F - }; - u8 authenticator_response[] = { - 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6, - 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66, - 0x93, 0x2C, 0xDA, 0x56 - }; - u8 master_key[] = { - 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C, - 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31 - }; - u8 send_start_key[] = { - 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B, - 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB - }; - u8 buf[32]; - - int errors = 0; - - printf("Testing ms_funcs.c\n"); - - challenge_hash(peer_challenge, auth_challenge, - username, strlen(username), - buf); - if (memcmp(challenge, buf, sizeof(challenge)) != 0) { - printf("challenge_hash failed\n"); - errors++; - } - - nt_password_hash(password, strlen(password), buf); - if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) { - printf("nt_password_hash failed\n"); - errors++; - } - - generate_nt_response(auth_challenge, peer_challenge, - username, strlen(username), - password, strlen(password), - buf); - if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) { - printf("generate_nt_response failed\n"); - errors++; - } - - hash_nt_password_hash(password_hash, buf); - if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) { - printf("hash_nt_password_hash failed\n"); - errors++; - } - - generate_authenticator_response(password, strlen(password), - peer_challenge, auth_challenge, - username, strlen(username), - nt_response, buf); - if (memcmp(authenticator_response, buf, sizeof(authenticator_response)) - != 0) { - printf("generate_authenticator_response failed\n"); - errors++; - } - - get_master_key(password_hash_hash, nt_response, buf); - if (memcmp(master_key, buf, sizeof(master_key)) != 0) { - printf("get_master_key failed\n"); - errors++; - } - - get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1); - if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) { - printf("get_asymetric_start_key failed\n"); - errors++; - } - - if (errors) - printf("FAILED! %d errors\n", errors); - - return errors; -} -#endif /* TEST_MAIN_MS_FUNCS */ diff --git a/contrib/wpa_supplicant/ms_funcs.h b/contrib/wpa_supplicant/ms_funcs.h deleted file mode 100644 index a08ab06d72be..000000000000 --- a/contrib/wpa_supplicant/ms_funcs.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef MS_FUNCS_H -#define MS_FUNCS_H - -void generate_nt_response(u8 *auth_challenge, u8 *peer_challenge, - u8 *username, size_t username_len, - u8 *password, size_t password_len, - u8 *response); -void generate_authenticator_response(u8 *password, size_t password_len, - u8 *peer_challenge, - u8 *auth_challenge, - u8 *username, size_t username_len, - u8 *nt_response, u8 *response); -void nt_challenge_response(u8 *challenge, u8 *password, size_t password_len, - u8 *response); - -void challenge_response(u8 *challenge, u8 *password_hash, u8 *response); -void nt_password_hash(u8 *password, size_t password_len, u8 *password_hash); -void hash_nt_password_hash(u8 *password_hash, u8 *password_hash_hash); -void get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key); -void get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server); - -#endif /* MS_FUNCS_H */ diff --git a/contrib/wpa_supplicant/openssl-tls-extensions.patch b/contrib/wpa_supplicant/openssl-tls-extensions.patch deleted file mode 100644 index 77e9a4132ef0..000000000000 --- a/contrib/wpa_supplicant/openssl-tls-extensions.patch +++ /dev/null @@ -1,166 +0,0 @@ -This is a quick hack for testing EAP-FAST with openssl. - -Addition of TLS extensions to ClientHello/ServerHello is more or less -ok, though not very clean in the way that the caller needs to take -care of constructing set of all extensions. In addition there is not -mechanism for reading the TLS extensions, i.e., this would not be -enough for EAP-FAST authenticator. - -Rest of the changes are obviously ugly and/or incorrect for most -parts, but it demonstrates the minimum set of changes to skip some of -the error cases that prevented completion of TLS handshake without -certificates. In other words, this is just a proof-of-concept type of -example to make it possible to experiment with EAP-FAST. Cleaner patch -for the needed functionality would be welcome.. - - -diff -upr openssl-0.9.7e.orig/include/openssl/ssl.h openssl-0.9.7e/include/openssl/ssl.h ---- openssl-0.9.7e.orig/include/openssl/ssl.h 2004-07-27 11:28:49.000000000 -0700 -+++ openssl-0.9.7e/include/openssl/ssl.h 2004-12-24 20:29:01.000000000 -0800 -@@ -929,6 +929,11 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* Optional ClientHello/ServerHello extension to be added to the end -+ * of the SSLv3/TLS hello message. */ -+ char *hello_extension; -+ int hello_extension_len; - }; - - #ifdef __cplusplus -diff -upr openssl-0.9.7e.orig/ssl/s3_both.c openssl-0.9.7e/ssl/s3_both.c ---- openssl-0.9.7e.orig/ssl/s3_both.c 2003-02-12 09:05:17.000000000 -0800 -+++ openssl-0.9.7e/ssl/s3_both.c 2004-12-31 21:18:15.556846272 -0800 -@@ -199,6 +199,12 @@ int ssl3_get_finished(SSL *s, int a, int - 64, /* should actually be 36+4 :-) */ - &ok); - -+ if (!ok && s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } -+ - if (!ok) return((int)n); - - /* If this occurs, we have missed a message */ -diff -upr openssl-0.9.7e.orig/ssl/s3_clnt.c openssl-0.9.7e/ssl/s3_clnt.c ---- openssl-0.9.7e.orig/ssl/s3_clnt.c 2004-05-15 09:39:22.000000000 -0700 -+++ openssl-0.9.7e/ssl/s3_clnt.c 2004-12-31 21:16:38.617583280 -0800 -@@ -588,6 +588,12 @@ static int ssl3_client_hello(SSL *s) - *(p++)=comp->id; - } - *(p++)=0; /* Add the NULL method */ -+ -+ if (s->hello_extension) -+ { -+ memcpy(p,s->hello_extension,s->hello_extension_len); -+ p+=s->hello_extension_len; -+ } - - l=(p-d); - d=buf; -@@ -779,6 +785,11 @@ static int ssl3_get_server_certificate(S - - if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE) - { -+ if (s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } - al=SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_BAD_MESSAGE_TYPE); - goto f_err; -@@ -951,6 +962,12 @@ static int ssl3_get_key_exchange(SSL *s) - DH *dh=NULL; - #endif - -+ if (s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } -+ - /* use same message size as in ssl3_get_certificate_request() - * as ServerKeyExchange message may be skipped */ - n=ssl3_get_message(s, -@@ -1264,6 +1281,12 @@ static int ssl3_get_certificate_request( - unsigned char *p,*d,*q; - STACK_OF(X509_NAME) *ca_sk=NULL; - -+ if (s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } -+ - n=ssl3_get_message(s, - SSL3_ST_CR_CERT_REQ_A, - SSL3_ST_CR_CERT_REQ_B, -@@ -1407,6 +1430,12 @@ static int ssl3_get_server_done(SSL *s) - int ok,ret=0; - long n; - -+ if (s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } -+ - n=ssl3_get_message(s, - SSL3_ST_CR_SRVR_DONE_A, - SSL3_ST_CR_SRVR_DONE_B, -@@ -1439,6 +1468,12 @@ static int ssl3_send_client_key_exchange - KSSL_ERR kssl_err; - #endif /* OPENSSL_NO_KRB5 */ - -+ if (s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } -+ - if (s->state == SSL3_ST_CW_KEY_EXCH_A) - { - d=(unsigned char *)s->init_buf->data; -@@ -1880,6 +1915,12 @@ static int ssl3_check_cert_and_algorithm - DH *dh; - #endif - -+ if (s->hello_extension) -+ { -+ /* Quick hack to test EAP-FAST. */ -+ return(1); -+ } -+ - sc=s->session->sess_cert; - - if (sc == NULL) -diff -upr openssl-0.9.7e.orig/ssl/ssl.h openssl-0.9.7e/ssl/ssl.h ---- openssl-0.9.7e.orig/ssl/ssl.h 2004-07-27 11:28:49.000000000 -0700 -+++ openssl-0.9.7e/ssl/ssl.h 2004-12-24 20:29:01.000000000 -0800 -@@ -929,6 +929,11 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* Optional ClientHello/ServerHello extension to be added to the end -+ * of the SSLv3/TLS hello message. */ -+ char *hello_extension; -+ int hello_extension_len; - }; - - #ifdef __cplusplus -diff -upr openssl-0.9.7e.orig/ssl/ssl_lib.c openssl-0.9.7e/ssl/ssl_lib.c ---- openssl-0.9.7e.orig/ssl/ssl_lib.c 2004-05-11 05:46:12.000000000 -0700 -+++ openssl-0.9.7e/ssl/ssl_lib.c 2004-12-24 20:35:22.000000000 -0800 -@@ -478,6 +478,7 @@ void SSL_free(SSL *s) - kssl_ctx_free(s->kssl_ctx); - #endif /* OPENSSL_NO_KRB5 */ - -+ OPENSSL_free(s->hello_extension); - OPENSSL_free(s); - } - diff --git a/contrib/wpa_supplicant/pcsc_funcs.c b/contrib/wpa_supplicant/pcsc_funcs.c deleted file mode 100644 index 541661fb00ed..000000000000 --- a/contrib/wpa_supplicant/pcsc_funcs.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - * WPA Supplicant / PC/SC smartcard interface for USIM, GSM SIM - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <winscard.h> - -#include "common.h" -#include "wpa_supplicant.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 <file_id, 2 bytes> - * GET RESPONSE: C0 00 00 <len> - * RUN GSM ALG: 88 00 00 00 <RAND len = 10> - * RUN UMTS ALG: 88 00 81 <len=0x22> data: 0x10 | RAND | 0x10 | AUTN - * P1 = ID of alg in card - * P2 = ID of secret key - * READ BINARY: B0 <offset high> <offset low> <len> - * VERIFY CHV: 20 00 <CHV number> 08 - * CHANGE CHV: 24 00 <CHV number> 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_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 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 { - long ctx; - long card; - unsigned long protocol; - SCARD_IO_REQUEST recv_pci; - sim_types sim_type; -}; - - -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); -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, char *pin); - - -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) - return 1; - } - - return -1; -} - - -struct scard_data * scard_init(scard_sim_type sim_type, char *pin) -{ - long ret, len; - struct scard_data *scard; - char *readers = NULL; - char buf[100]; - size_t blen; - - wpa_printf(MSG_DEBUG, "SCARD: initializing smart card interface"); - scard = malloc(sizeof(*scard)); - if (scard == NULL) - return NULL; - memset(scard, 0, sizeof(*scard)); - - 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; - } - - readers = malloc(len); - if (readers == NULL) { - printf("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.. */ - wpa_printf(MSG_DEBUG, "SCARD: Selected reader='%s'", readers); - - ret = SCardConnect(scard->ctx, readers, SCARD_SHARE_SHARED, - SCARD_PROTOCOL_T0, &scard->card, &scard->protocol); - if (ret != SCARD_S_SUCCESS) { - if (ret == SCARD_E_NO_SMARTCARD) - wpa_printf(MSG_INFO, "No smart card inserted."); - else - wpa_printf(MSG_WARNING, "SCardConnect err=%lx", ret); - goto failed; - } - - free(readers); - readers = NULL; - - wpa_printf(MSG_DEBUG, "SCARD: card=%ld active_protocol=%lu", - scard->card, scard->protocol); - - 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)) { - 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 { - /* Select based on AID = 3G RID */ - blen = sizeof(buf); - if (_scard_select_file(scard, 0, buf, &blen, scard->sim_type, - "\xA0\x00\x00\x00\x87")) { - wpa_printf(MSG_DEBUG, "SCARD: Failed to read 3G RID " - "AID"); - goto failed; - } - } - - /* Verify whether CHV1 (PIN1) is needed to access the card. */ - if (scard_pin_needed(scard, buf, blen)) { - wpa_printf(MSG_DEBUG, "PIN1 needed for SIM access"); - if (pin == NULL) { - wpa_printf(MSG_INFO, "No PIN configured for SIM " - "access"); - /* TODO: ask PIN from user through a frontend (e.g., - * wpa_cli) */ - goto failed; - } - if (scard_verify_pin(scard, pin)) { - wpa_printf(MSG_INFO, "PIN verification failed for " - "SIM access"); - /* TODO: what to do? */ - goto failed; - } - } - - return scard; - -failed: - free(readers); - scard_deinit(scard); - return NULL; -} - - -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); - } - } - free(scard); -} - - -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, - &scard->recv_pci, 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) -{ - long ret; - unsigned char resp[3]; - unsigned char cmd[10] = { 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) { - cmd[2] = 0x04; /* Select by AID */ - cmd[4] = 5; /* len */ - memcpy(cmd + 5, aid, 5); - cmdlen = 10; - } 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); -} - - -static int scard_read_file(struct scard_data *scard, - unsigned char *data, size_t len) -{ - char cmd[5] = { SIM_CMD_READ_BIN, len }; - size_t blen = len + 3; - unsigned char *buf; - long ret; - - buf = 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) { - free(buf); - return -2; - } - if (blen != len + 2) { - wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " - "length %d (expected %d)", blen, len + 2); - 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]); - free(buf); - return -4; - } - - memcpy(data, buf, len); - free(buf); - - return 0; -} - - -static int scard_verify_pin(struct scard_data *scard, char *pin) -{ - long ret; - unsigned char resp[3]; - char cmd[5 + 8] = { SIM_CMD_VERIFY_CHV1 }; - size_t len; - - wpa_printf(MSG_DEBUG, "SCARD: verifying PIN"); - - if (pin == NULL || strlen(pin) > 8) - return -1; - - if (scard->sim_type == SCARD_USIM) - cmd[0] = USIM_CLA; - memcpy(cmd + 5, pin, strlen(pin)); - memset(cmd + 5 + strlen(pin), 0xff, 8 - 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; -} - - -int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) -{ - char buf[100]; - size_t blen, imsilen; - char *pos; - int i; - - 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=%d)", 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=%d", - blen); - return -3; - } - - imsilen = (blen - 2) * 2 + 1; - wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%d imsilen=%d", - blen, 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; -} - - -int scard_gsm_auth(struct scard_data *scard, 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; - memcpy(cmd + 5, rand, 16); - } else { - cmdlen = 5 + 1 + 16; - cmd[0] = USIM_CLA; - cmd[3] = 0x80; - cmd[4] = 17; - cmd[5] = 16; - memcpy(cmd + 6, rand, 16); - } - len = sizeof(resp); - ret = scard_transmit(scard, cmd, sizeof(cmd), 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=%d resp=%02x %02x)", - 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=%d, expected 14)", - len); - return -5; - } - memcpy(sres, buf, 4); - 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=%d, " - "expected 16)", 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]); - } - memcpy(sres, buf + 1, 4); - 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; -} - - -int scard_umts_auth(struct scard_data *scard, unsigned char *rand, - 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 }; - int cmdlen; - 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); - cmdlen = 5 + 1 + AKA_RAND_LEN + 1 + AKA_AUTN_LEN; - cmd[5] = AKA_RAND_LEN; - memcpy(cmd + 6, rand, AKA_RAND_LEN); - cmd[6 + AKA_RAND_LEN] = AKA_AUTN_LEN; - 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 >= 0 && 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=%d resp=%02x %02x)", - 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 < 0 || 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"); - 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++; - 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++; - 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++; - 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; -} diff --git a/contrib/wpa_supplicant/pcsc_funcs.h b/contrib/wpa_supplicant/pcsc_funcs.h deleted file mode 100644 index 1b64fa279441..000000000000 --- a/contrib/wpa_supplicant/pcsc_funcs.h +++ /dev/null @@ -1,50 +0,0 @@ -#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_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, char *pin); -void scard_deinit(struct scard_data *scard); - -int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len); -int scard_gsm_auth(struct scard_data *scard, unsigned char *rand, - unsigned char *sres, unsigned char *kc); -int scard_umts_auth(struct scard_data *scard, unsigned char *rand, - 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, p) NULL -#define scard_deinit(s) do { } while (0) -#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 */ diff --git a/contrib/wpa_supplicant/preauth_test.c b/contrib/wpa_supplicant/preauth_test.c deleted file mode 100644 index 13741bbaa367..000000000000 --- a/contrib/wpa_supplicant/preauth_test.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * WPA Supplicant - test code for pre-authentication - * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c. - * Not used in production version. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <ctype.h> -#include <string.h> -#include <signal.h> -#include <netinet/in.h> -#include <assert.h> -#include <arpa/inet.h> - -#include "common.h" -#include "config.h" -#include "eapol_sm.h" -#include "eloop.h" -#include "wpa.h" -#include "eap.h" -#include "wpa_supplicant.h" -#include "wpa_supplicant_i.h" -#include "l2_packet.h" -#include "ctrl_iface.h" -#include "pcsc_funcs.h" - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; - -void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = malloc(buflen); - if (buf == NULL) { - printf("Failed to allocate message buffer for:\n"); - va_start(ap, fmt); - vprintf(fmt, ap); - printf("\n"); - va_end(ap); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s", buf); - wpa_supplicant_ctrl_iface_send(wpa_s, level, buf, len); - free(buf); -} - - -void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event, - union wpa_event_data *data) -{ -} - - -int rsn_preauth_init(struct wpa_supplicant *wpa_s, u8 *dst) -{ - return -1; -} - - -void rsn_preauth_deinit(struct wpa_supplicant *wpa_s) -{ -} - - -int pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len) -{ - return 0; -} - - -int wpa_get_mib(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) -{ - return 0; -} - - -void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) -{ -} - - -const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len) -{ - return NULL; -} - - -int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) -{ - return -1; -} - - -static int eapol_test_eapol_send(void *ctx, int type, u8 *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - u8 *msg; - size_t msglen; - struct l2_ethhdr *ethhdr; - struct ieee802_1x_hdr *hdr; - int res; - - printf("WPA: wpa_eapol_send(type=%d len=%d)\n", type, len); - - if (wpa_s->l2_preauth == NULL) - return -1; - - msglen = sizeof(*ethhdr) + sizeof(*hdr) + len; - msg = malloc(msglen); - if (msg == NULL) - return -1; - - ethhdr = (struct l2_ethhdr *) msg; - memcpy(ethhdr->h_dest, wpa_s->preauth_bssid, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_RSN_PREAUTH); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = type; - hdr->length = htons(len); - - memcpy((u8 *) (hdr + 1), buf, len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen); - res = l2_packet_send(wpa_s->l2_preauth, msg, msglen); - free(msg); - return res; -} - - -static void eapol_test_eapol_done_cb(void *ctx) -{ - printf("WPA: EAPOL processing complete\n"); -} - - -static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx) -{ - printf("eapol_sm_cb: success=%d\n", success); - eloop_terminate(); -} - - -static int test_eapol(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - ctx = malloc(sizeof(*ctx)); - if (ctx == NULL) { - printf("Failed to allocate EAPOL context.\n"); - return -1; - } - memset(ctx, 0, sizeof(*ctx)); - ctx->ctx = wpa_s; - ctx->msg_ctx = wpa_s; - ctx->scard_ctx = wpa_s->scard; - ctx->cb = eapol_sm_cb; - ctx->cb_ctx = wpa_s; - ctx->preauth = 0; - ctx->eapol_done_cb = eapol_test_eapol_done_cb; - ctx->eapol_send = eapol_test_eapol_send; - - wpa_s->preauth_eapol = eapol_sm_init(ctx); - if (wpa_s->preauth_eapol == NULL) { - free(ctx); - printf("Failed to initialize EAPOL state machines.\n"); - return -1; - } - - wpa_s->current_ssid = ssid; - memset(&eapol_conf, 0, sizeof(eapol_conf)); - eapol_conf.accept_802_1x_keys = 1; - eapol_conf.required_keys = 0; - eapol_conf.workaround = ssid->eap_workaround; - eapol_sm_notify_config(wpa_s->preauth_eapol, ssid, &eapol_conf); - - - eapol_sm_notify_portValid(wpa_s->preauth_eapol, FALSE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->preauth_eapol, TRUE); - - return 0; -} - - -static void test_eapol_clean(struct wpa_supplicant *wpa_s) -{ - l2_packet_deinit(wpa_s->l2_preauth); - eapol_sm_deinit(wpa_s->preauth_eapol); - wpa_s->preauth_eapol = NULL; - scard_deinit(wpa_s->scard); - wpa_supplicant_ctrl_iface_deinit(wpa_s); - wpa_config_free(wpa_s->conf); -} - - -static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - printf("EAPOL test timed out\n"); - wpa_s->auth_timed_out = 1; - eloop_terminate(); -} - - -static void wpa_supplicant_imsi_identity(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - if (ssid->identity == NULL && wpa_s->imsi) { - ssid->identity = malloc(1 + wpa_s->imsi_len); - if (ssid->identity) { - ssid->identity[0] = '1'; - memcpy(ssid->identity + 1, wpa_s->imsi, - wpa_s->imsi_len); - ssid->identity_len = 1 + wpa_s->imsi_len; - wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " - "IMSI", ssid->identity, - ssid->identity_len); - } - } -} - - -static void wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - char buf[100]; - size_t len; - - if (ssid->pcsc == NULL) - return; - if (wpa_s->scard != NULL) { - wpa_supplicant_imsi_identity(wpa_s, ssid); - return; - } - wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM - " - "initialize PCSC"); - wpa_s->scard = scard_init(SCARD_TRY_BOTH, ssid->pin); - if (wpa_s->scard == NULL) { - wpa_printf(MSG_WARNING, "Failed to initialize SIM " - "(pcsc-lite)"); - /* TODO: what to do here? */ - return; - } - eapol_sm_register_scard_ctx(wpa_s->preauth_eapol, wpa_s->scard); - - len = sizeof(buf); - if (scard_get_imsi(wpa_s->scard, buf, &len)) { - wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); - /* TODO: what to do here? */ - return; - } - - wpa_hexdump(MSG_DEBUG, "IMSI", (u8 *) buf, len); - free(wpa_s->imsi); - wpa_s->imsi = malloc(len); - if (wpa_s->imsi) { - memcpy(wpa_s->imsi, buf, len); - wpa_s->imsi_len = len; - wpa_supplicant_imsi_identity(wpa_s, ssid); - } -} - - -static void rsn_preauth_receive(void *ctx, unsigned char *src_addr, - unsigned char *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - - wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr)); - wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len); - - if (wpa_s->preauth_eapol == NULL || - memcmp(wpa_s->preauth_bssid, "\x00\x00\x00\x00\x00\x00", - ETH_ALEN) == 0 || - memcmp(wpa_s->preauth_bssid, src_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_WARNING, "RSN pre-auth frame received from " - "unexpected source " MACSTR " - dropped", - MAC2STR(src_addr)); - return; - } - - eapol_sm_rx_eapol(wpa_s->preauth_eapol, src_addr, buf, len); -} - - -static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *target, - const char *ifname) -{ - strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); - - if (hwaddr_aton(target, wpa_s->preauth_bssid)) { - printf("Failed to parse target address '%s'.\n", target); - exit(-1); - } - - wpa_s->l2_preauth = l2_packet_init(wpa_s->ifname, NULL, - ETH_P_RSN_PREAUTH, - rsn_preauth_receive, wpa_s); - if (wpa_s->l2_preauth == NULL) { - wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " - "processing for pre-authentication"); - exit(-1); - } - - if (l2_packet_get_own_addr(wpa_s->l2_preauth, wpa_s->own_addr)) { - wpa_printf(MSG_WARNING, "Failed to get own L2 address\n"); - exit(-1); - } -} - - -static void eapol_test_terminate(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -int main(int argc, char *argv[]) -{ - struct wpa_supplicant wpa_s; - int ret = 1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (argc != 4) { - printf("usage: eapol_test <conf> <target MAC address> " - "<ifname>\n"); - return -1; - } - - eloop_init(&wpa_s); - - memset(&wpa_s, 0, sizeof(wpa_s)); - wpa_s.conf = wpa_config_read(argv[1]); - if (wpa_s.conf == NULL) { - printf("Failed to parse configuration file '%s'.\n", argv[1]); - return -1; - } - if (wpa_s.conf->ssid == NULL) { - printf("No networks defined.\n"); - return -1; - } - - wpa_init_conf(&wpa_s, argv[2], argv[3]); - if (wpa_supplicant_ctrl_iface_init(&wpa_s)) { - printf("Failed to initialize control interface '%s'.\n" - "You may have another eapol_test process already " - "running or the file was\n" - "left by an unclean termination of eapol_test in " - "which case you will need\n" - "to manually remove this file before starting " - "eapol_test again.\n", - wpa_s.conf->ctrl_interface); - return -1; - } - wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid); - - if (test_eapol(&wpa_s, wpa_s.conf->ssid)) - return -1; - - eloop_register_timeout(30, 0, eapol_test_timeout, &wpa_s, NULL); - eloop_register_signal(SIGINT, eapol_test_terminate, NULL); - eloop_register_signal(SIGTERM, eapol_test_terminate, NULL); - eloop_register_signal(SIGHUP, eapol_test_terminate, NULL); - eloop_run(); - - if (wpa_s.auth_timed_out) - ret = -2; - else - ret = 0; - - test_eapol_clean(&wpa_s); - - eloop_destroy(); - - return ret; -} diff --git a/contrib/wpa_supplicant/radius.c b/contrib/wpa_supplicant/radius.c deleted file mode 100644 index 5fd323d65c85..000000000000 --- a/contrib/wpa_supplicant/radius.c +++ /dev/null @@ -1,1125 +0,0 @@ -/* - * Host AP (software wireless LAN access point) user space daemon for - * Host AP kernel driver / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <netinet/in.h> -#include <string.h> -#include <sys/ioctl.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <arpa/inet.h> - - -#include "common.h" -#include "radius.h" -#include "md5.h" - - -struct radius_msg *radius_msg_new(u8 code, u8 identifier) -{ - struct radius_msg *msg; - - msg = (struct radius_msg *) malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) { - free(msg); - return NULL; - } - - radius_msg_set_hdr(msg, code, identifier); - - return msg; -} - - -int radius_msg_initialize(struct radius_msg *msg, size_t init_len) -{ - if (msg == NULL || init_len < sizeof(struct radius_hdr)) - return -1; - - memset(msg, 0, sizeof(*msg)); - msg->buf = (unsigned char *) malloc(init_len); - if (msg->buf == NULL) - return -1; - memset(msg->buf, 0, init_len); - - msg->buf_size = init_len; - msg->hdr = (struct radius_hdr *) msg->buf; - msg->buf_used = sizeof(*msg->hdr); - - msg->attrs = (struct radius_attr_hdr **) - malloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attrs)); - if (msg->attrs == NULL) { - free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - return -1; - } - - msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT; - msg->attr_used = 0; - - return 0; -} - - -void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier) -{ - msg->hdr->code = code; - msg->hdr->identifier = identifier; -} - - -void radius_msg_free(struct radius_msg *msg) -{ - if (msg->buf != NULL) { - free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - } - msg->buf_size = msg->buf_used = 0; - - if (msg->attrs != NULL) { - free(msg->attrs); - msg->attrs = NULL; - } - msg->attr_size = msg->attr_used = 0; -} - - -static const char *radius_code_string(u8 code) -{ - switch (code) { - case RADIUS_CODE_ACCESS_REQUEST: return "Access-Request"; - case RADIUS_CODE_ACCESS_ACCEPT: return "Access-Accept"; - case RADIUS_CODE_ACCESS_REJECT: return "Access-Reject"; - case RADIUS_CODE_ACCOUNTING_REQUEST: return "Accounting-Request"; - case RADIUS_CODE_ACCOUNTING_RESPONSE: return "Accounting-Response"; - case RADIUS_CODE_ACCESS_CHALLENGE: return "Access-Challenge"; - case RADIUS_CODE_STATUS_SERVER: return "Status-Server"; - case RADIUS_CODE_STATUS_CLIENT: return "Status-Client"; - case RADIUS_CODE_RESERVED: return "Reserved"; - default: return "?Unknown?"; - } -} - - -struct radius_attr_type { - u8 type; - char *name; - enum { RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP, - RADIUS_ATTR_HEXDUMP, RADIUS_ATTR_INT32 } data_type; -}; - -static struct radius_attr_type radius_attrs[] = -{ - { RADIUS_ATTR_USER_NAME, "User-Name", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_USER_PASSWORD, "User-Password", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_NAS_IP_ADDRESS, "NAS-IP-Address", RADIUS_ATTR_IP }, - { RADIUS_ATTR_NAS_PORT, "NAS-Port", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_FRAMED_MTU, "Framed-MTU", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_STATE, "State", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_CLASS, "Class", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_VENDOR_SPECIFIC, "Vendor-Specific", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_SESSION_TIMEOUT, "Session-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_IDLE_TIMEOUT, "Idle-Timeout", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_TERMINATION_ACTION, "Termination-Action", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_CALLED_STATION_ID, "Called-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_OCTETS, "Acct-Input-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_OCTETS, "Acct-Output-Octets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_ID, "Acct-Session-Id", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_AUTHENTIC, "Acct-Authentic", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_SESSION_TIME, "Acct-Session-Time", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_PACKETS, "Acct-Input-Packets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_PACKETS, "Acct-Output-Packets", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_TERMINATE_CAUSE, "Acct-Terminate-Cause", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_MULTI_SESSION_ID, "Acct-Multi-Session-Id", - RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_ACCT_LINK_COUNT, "Acct-Link-Count", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_INPUT_GIGAWORDS, "Acct-Input-Gigawords", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS, "Acct-Output-Gigawords", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_EVENT_TIMESTAMP, "Event-Timestamp", - RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_NAS_PORT_TYPE, "NAS-Port-Type", RADIUS_ATTR_INT32 }, - { RADIUS_ATTR_CONNECT_INFO, "Connect-Info", RADIUS_ATTR_TEXT }, - { RADIUS_ATTR_EAP_MESSAGE, "EAP-Message", RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_MESSAGE_AUTHENTICATOR, "Message-Authenticator", - RADIUS_ATTR_UNDIST }, - { RADIUS_ATTR_ACCT_INTERIM_INTERVAL, "Acct-Interim-Interval", - RADIUS_ATTR_INT32 } - -}; -#define RADIUS_ATTRS (sizeof(radius_attrs) / sizeof(radius_attrs[0])) - - -static struct radius_attr_type *radius_get_attr_type(u8 type) -{ - int i; - - for (i = 0; i < RADIUS_ATTRS; i++) { - if (type == radius_attrs[i].type) - return &radius_attrs[i]; - } - - return NULL; -} - - -static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) -{ - struct radius_attr_type *attr; - int i, len; - unsigned char *pos; - - attr = radius_get_attr_type(hdr->type); - - printf(" Attribute %d (%s) length=%d\n", - hdr->type, attr ? attr->name : "?Unknown?", hdr->length); - - if (attr == NULL) - return; - - len = hdr->length - sizeof(struct radius_attr_hdr); - pos = (unsigned char *) (hdr + 1); - - switch (attr->data_type) { - case RADIUS_ATTR_TEXT: - printf(" Value: '"); - for (i = 0; i < len; i++) - print_char(pos[i]); - printf("'\n"); - break; - - case RADIUS_ATTR_IP: - if (len == 4) { - struct in_addr *addr = (struct in_addr *) pos; - printf(" Value: %s\n", inet_ntoa(*addr)); - } else - printf(" Invalid IP address length %d\n", len); - break; - - case RADIUS_ATTR_HEXDUMP: - case RADIUS_ATTR_UNDIST: - printf(" Value:"); - for (i = 0; i < len; i++) - printf(" %02x", pos[i]); - printf("\n"); - break; - - case RADIUS_ATTR_INT32: - if (len == 4) { - u32 *val = (u32 *) pos; - printf(" Value: %d\n", ntohl(*val)); - } else - printf(" Invalid INT32 length %d\n", len); - break; - - default: - break; - } -} - - -void radius_msg_dump(struct radius_msg *msg) -{ - int i; - - printf("RADIUS message: code=%d (%s) identifier=%d length=%d\n", - msg->hdr->code, radius_code_string(msg->hdr->code), - msg->hdr->identifier, ntohs(msg->hdr->length)); - - for (i = 0; i < msg->attr_used; i++) { - radius_msg_dump_attr(msg->attrs[i]); - } -} - - -int radius_msg_finish(struct radius_msg *msg, u8 *secret, size_t secret_len) -{ - if (secret) { - u8 auth[MD5_MAC_LEN]; - struct radius_attr_hdr *attr; - - memset(auth, 0, MD5_MAC_LEN); - attr = radius_msg_add_attr(msg, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - auth, MD5_MAC_LEN); - if (attr == NULL) { - printf("WARNING: Could not add " - "Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(msg->buf_used); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (u8 *) (attr + 1)); - } else - msg->hdr->length = htons(msg->buf_used); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - return -1; - } - return 0; -} - - -int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_authenticator) -{ - u8 auth[MD5_MAC_LEN]; - struct radius_attr_hdr *attr; - MD5_CTX context; - - memset(auth, 0, MD5_MAC_LEN); - attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, - auth, MD5_MAC_LEN); - if (attr == NULL) { - printf("WARNING: Could not add Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(msg->buf_used); - memcpy(msg->hdr->authenticator, req_authenticator, - sizeof(msg->hdr->authenticator)); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (u8 *) (attr + 1)); - - /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ - MD5Init(&context); - MD5Update(&context, (u8 *) msg->hdr, 1 + 1 + 2); - MD5Update(&context, req_authenticator, MD5_MAC_LEN); - MD5Update(&context, (u8 *) (msg->hdr + 1), - msg->buf_used - sizeof(*msg->hdr)); - MD5Update(&context, secret, secret_len); - MD5Final(msg->hdr->authenticator, &context); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - return -1; - } - return 0; -} - - -void radius_msg_finish_acct(struct radius_msg *msg, u8 *secret, - size_t secret_len) -{ - MD5_CTX context; - - msg->hdr->length = htons(msg->buf_used); - memset(msg->hdr->authenticator, 0, MD5_MAC_LEN); - MD5Init(&context); - MD5Update(&context, msg->buf, msg->buf_used); - MD5Update(&context, secret, secret_len); - MD5Final(msg->hdr->authenticator, &context); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS messages (%lu)\n", - (unsigned long) msg->buf_used); - } -} - - -static int radius_msg_add_attr_to_array(struct radius_msg *msg, - struct radius_attr_hdr *attr) -{ - if (msg->attr_used >= msg->attr_size) { - struct radius_attr_hdr **nattrs; - int nlen = msg->attr_size * 2; - - nattrs = (struct radius_attr_hdr **) - realloc(msg->attrs, nlen * sizeof(*msg->attrs)); - - if (nattrs == NULL) - return -1; - - msg->attrs = nattrs; - msg->attr_size = nlen; - } - - msg->attrs[msg->attr_used++] = attr; - - return 0; -} - - -struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, - u8 *data, size_t data_len) -{ - size_t buf_needed; - struct radius_attr_hdr *attr; - - if (data_len > RADIUS_MAX_ATTR_LEN) { - printf("radius_msg_add_attr: too long attribute (%lu bytes)\n", - (unsigned long) data_len); - return NULL; - } - - buf_needed = msg->buf_used + sizeof(*attr) + data_len; - - if (msg->buf_size < buf_needed) { - /* allocate more space for message buffer */ - unsigned char *nbuf; - int nlen = msg->buf_size; - int diff, i; - - while (nlen < buf_needed) - nlen *= 2; - nbuf = (unsigned char *) realloc(msg->buf, nlen); - if (nbuf == NULL) - return NULL; - diff = nbuf - msg->buf; - msg->buf = nbuf; - msg->hdr = (struct radius_hdr *) msg->buf; - /* adjust attr pointers to match with the new buffer */ - for (i = 0; i < msg->attr_used; i++) - msg->attrs[i] = (struct radius_attr_hdr *) - (((u8 *) msg->attrs[i]) + diff); - memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size); - msg->buf_size = nlen; - } - - attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used); - attr->type = type; - attr->length = sizeof(*attr) + data_len; - if (data_len > 0) - memcpy(attr + 1, data, data_len); - - msg->buf_used += sizeof(*attr) + data_len; - - if (radius_msg_add_attr_to_array(msg, attr)) - return NULL; - - return attr; -} - - -struct radius_msg *radius_msg_parse(const u8 *data, size_t len) -{ - struct radius_msg *msg; - struct radius_hdr *hdr; - struct radius_attr_hdr *attr; - size_t msg_len; - unsigned char *pos, *end; - - if (data == NULL || len < sizeof(*hdr)) - return NULL; - - hdr = (struct radius_hdr *) data; - - msg_len = ntohs(hdr->length); - if (msg_len < sizeof(*hdr) || msg_len > len) { - printf("Invalid RADIUS message length\n"); - return NULL; - } - - if (msg_len < len) { - printf("Ignored %lu extra bytes after RADIUS message\n", - (unsigned long) len - msg_len); - } - - msg = (struct radius_msg *) malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, msg_len)) { - free(msg); - return NULL; - } - - memcpy(msg->buf, data, msg_len); - msg->buf_size = msg->buf_used = msg_len; - - /* parse attributes */ - pos = (unsigned char *) (msg->hdr + 1); - end = msg->buf + msg->buf_used; - while (pos < end) { - if (end - pos < sizeof(*attr)) - goto fail; - - attr = (struct radius_attr_hdr *) pos; - - if (pos + attr->length > end || attr->length < sizeof(*attr)) - goto fail; - - /* TODO: check that attr->length is suitable for attr->type */ - - if (radius_msg_add_attr_to_array(msg, attr)) - goto fail; - - pos += attr->length; - } - - return msg; - - fail: - radius_msg_free(msg); - free(msg); - return NULL; -} - - -int radius_msg_add_eap(struct radius_msg *msg, u8 *data, size_t data_len) -{ - u8 *pos = data; - size_t left = data_len; - - while (left > 0) { - int len; - if (left > RADIUS_MAX_ATTR_LEN) - len = RADIUS_MAX_ATTR_LEN; - else - len = left; - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_EAP_MESSAGE, - pos, len)) - return 0; - - pos += len; - left -= len; - } - - return 1; -} - - -u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *eap_len) -{ - u8 *eap, *pos; - size_t len; - int i; - - if (msg == NULL) - return NULL; - - len = 0; - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) - len += msg->attrs[i]->length - - sizeof(struct radius_attr_hdr); - } - - if (len == 0) - return NULL; - - eap = malloc(len); - if (eap == NULL) - return NULL; - - pos = eap; - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) { - struct radius_attr_hdr *attr = msg->attrs[i]; - int flen = attr->length - sizeof(*attr); - memcpy(pos, attr + 1, flen); - pos += flen; - } - } - - if (eap_len) - *eap_len = len; - - return eap; -} - - -int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_auth) -{ - u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN]; - u8 orig_authenticator[16]; - struct radius_attr_hdr *attr = NULL; - int i; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) { - if (attr != NULL) { - printf("Multiple Message-Authenticator " - "attributes in RADIUS message\n"); - return 1; - } - attr = msg->attrs[i]; - } - } - - if (attr == NULL) { - printf("No Message-Authenticator attribute found\n"); - return 1; - } - - memcpy(orig, attr + 1, MD5_MAC_LEN); - memset(attr + 1, 0, MD5_MAC_LEN); - if (req_auth) { - memcpy(orig_authenticator, msg->hdr->authenticator, - sizeof(orig_authenticator)); - memcpy(msg->hdr->authenticator, req_auth, - sizeof(msg->hdr->authenticator)); - } - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, auth); - memcpy(attr + 1, orig, MD5_MAC_LEN); - if (req_auth) { - memcpy(msg->hdr->authenticator, orig_authenticator, - sizeof(orig_authenticator)); - } - - if (memcmp(orig, auth, MD5_MAC_LEN) != 0) { - printf("Invalid Message-Authenticator!\n"); - return 1; - } - - return 0; -} - - -int radius_msg_verify(struct radius_msg *msg, u8 *secret, size_t secret_len, - struct radius_msg *sent_msg) -{ - MD5_CTX context; - u8 hash[MD5_MAC_LEN]; - - if (sent_msg == NULL) { - printf("No matching Access-Request message found\n"); - return 1; - } - - if (radius_msg_verify_msg_auth(msg, secret, secret_len, - sent_msg->hdr->authenticator)) { - return 1; - } - - /* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */ - MD5Init(&context); - MD5Update(&context, (u8 *) msg->hdr, 1 + 1 + 2); - MD5Update(&context, sent_msg->hdr->authenticator, MD5_MAC_LEN); - MD5Update(&context, (u8 *) (msg->hdr + 1), - msg->buf_used - sizeof(*msg->hdr)); - MD5Update(&context, secret, secret_len); - MD5Final(hash, &context); - if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) { - printf("Response Authenticator invalid!\n"); - return 1; - } - - return 0; - -} - - -int radius_msg_verify_acct(struct radius_msg *msg, u8 *secret, - size_t secret_len, struct radius_msg *sent_msg) -{ - MD5_CTX context; - u8 hash[MD5_MAC_LEN]; - - MD5Init(&context); - MD5Update(&context, msg->buf, 4); - MD5Update(&context, sent_msg->hdr->authenticator, MD5_MAC_LEN); - if (msg->buf_used > sizeof(struct radius_hdr)) - MD5Update(&context, msg->buf + sizeof(struct radius_hdr), - msg->buf_used - sizeof(struct radius_hdr)); - MD5Update(&context, secret, secret_len); - MD5Final(hash, &context); - if (memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) { - printf("Response Authenticator invalid!\n"); - return 1; - } - - return 0; -} - - -int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, - u8 type) -{ - struct radius_attr_hdr *attr = NULL; - int i; - - for (i = 0; i < src->attr_used; i++) { - if (src->attrs[i]->type == type) { - attr = src->attrs[i]; - break; - } - } - - if (attr == NULL) - return 0; - - if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1), - attr->length - sizeof(*attr))) - return -1; - - return 1; -} - - -/* Create Request Authenticator. The value should be unique over the lifetime - * of the shared secret between authenticator and authentication server. - * Use one-way MD5 hash calculated from current timestamp and some data given - * by the caller. */ -void radius_msg_make_authenticator(struct radius_msg *msg, - u8 *data, size_t len) -{ - struct timeval tv; - MD5_CTX context; - long int l; - - gettimeofday(&tv, NULL); - l = random(); - MD5Init(&context); - MD5Update(&context, (u8 *) &tv, sizeof(tv)); - MD5Update(&context, data, len); - MD5Update(&context, (u8 *) &l, sizeof(l)); - MD5Final(msg->hdr->authenticator, &context); -} - - -/* Get Vendor-specific RADIUS Attribute from a parsed RADIUS message. - * Returns the Attribute payload and sets alen to indicate the length of the - * payload if a vendor attribute with subtype is found, otherwise returns NULL. - * The returned payload is allocated with malloc() and caller must free it. - */ -static u8 *radius_msg_get_vendor_attr(struct radius_msg *msg, u32 vendor, - u8 subtype, size_t *alen) -{ - u8 *data, *pos; - int i; - size_t len; - - if (msg == NULL) - return NULL; - - for (i = 0; i < msg->attr_used; i++) { - struct radius_attr_hdr *attr = msg->attrs[i]; - int left; - u32 vendor_id; - struct radius_attr_vendor *vhdr; - - if (attr->type != RADIUS_ATTR_VENDOR_SPECIFIC) - continue; - - left = attr->length - sizeof(*attr); - if (left < 4) - continue; - - pos = (u8 *) (attr + 1); - - memcpy(&vendor_id, pos, 4); - pos += 4; - left -= 4; - - if (ntohl(vendor_id) != vendor) - continue; - - while (left >= sizeof(*vhdr)) { - vhdr = (struct radius_attr_vendor *) pos; - if (vhdr->vendor_length > left || - vhdr->vendor_length < sizeof(*vhdr)) { - left = 0; - break; - } - if (vhdr->vendor_type != subtype) { - pos += vhdr->vendor_length; - left -= vhdr->vendor_length; - continue; - } - - len = vhdr->vendor_length - sizeof(*vhdr); - data = malloc(len); - if (data == NULL) - return NULL; - memcpy(data, pos + sizeof(*vhdr), len); - if (alen) - *alen = len; - return data; - } - } - - return NULL; -} - - -static u8 * decrypt_ms_key(const u8 *key, size_t len, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, size_t *reslen) -{ - u8 *plain, *ppos, *res; - const u8 *pos; - size_t left, plen; - u8 hash[MD5_MAC_LEN]; - MD5_CTX context; - int i, first = 1; - - /* key: 16-bit salt followed by encrypted key info */ - - if (len < 2 + 16) - return NULL; - - pos = key + 2; - left = len - 2; - if (left % 16) { - printf("Invalid ms key len %lu\n", (unsigned long) left); - return NULL; - } - - plen = left; - ppos = plain = malloc(plen); - if (plain == NULL) - return NULL; - - while (left > 0) { - /* b(1) = MD5(Secret + Request-Authenticator + Salt) - * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ - - MD5Init(&context); - MD5Update(&context, secret, secret_len); - if (first) { - MD5Update(&context, req_authenticator, MD5_MAC_LEN); - MD5Update(&context, key, 2); /* Salt */ - first = 0; - } else - MD5Update(&context, pos - MD5_MAC_LEN, MD5_MAC_LEN); - MD5Final(hash, &context); - - for (i = 0; i < MD5_MAC_LEN; i++) - *ppos++ = *pos++ ^ hash[i]; - left -= MD5_MAC_LEN; - } - - if (plain[0] > plen - 1) { - printf("Failed to decrypt MPPE key\n"); - free(plain); - return NULL; - } - - res = malloc(plain[0]); - if (res == NULL) { - free(plain); - return NULL; - } - memcpy(res, plain + 1, plain[0]); - if (reslen) - *reslen = plain[0]; - free(plain); - return res; -} - - -static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - u8 *ebuf, size_t *elen) -{ - int i, len, first = 1; - u8 hash[MD5_MAC_LEN], saltbuf[2], *pos; - MD5_CTX context; - - saltbuf[0] = salt >> 8; - saltbuf[1] = salt; - - len = 1 + key_len; - if (len & 0x0f) { - len = (len & 0xf0) + 16; - } - memset(ebuf, 0, len); - ebuf[0] = key_len; - memcpy(ebuf + 1, key, key_len); - - *elen = len; - - pos = ebuf; - while (len > 0) { - /* b(1) = MD5(Secret + Request-Authenticator + Salt) - * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ - MD5Init(&context); - MD5Update(&context, secret, secret_len); - if (first) { - MD5Update(&context, req_authenticator, MD5_MAC_LEN); - MD5Update(&context, saltbuf, sizeof(saltbuf)); - first = 0; - } else { - MD5Update(&context, pos - MD5_MAC_LEN, MD5_MAC_LEN); - } - MD5Final(hash, &context); - - for (i = 0; i < MD5_MAC_LEN; i++) - *pos++ ^= hash[i]; - - len -= MD5_MAC_LEN; - } -} - - -struct radius_ms_mppe_keys * -radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - u8 *secret, size_t secret_len) -{ - u8 *key; - size_t keylen; - struct radius_ms_mppe_keys *keys; - - if (msg == NULL || sent_msg == NULL) - return NULL; - - keys = (struct radius_ms_mppe_keys *) malloc(sizeof(*keys)); - if (keys == NULL) - return NULL; - - memset(keys, 0, sizeof(*keys)); - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT, - RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY, - &keylen); - if (key) { - keys->send = decrypt_ms_key(key, keylen, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->send_len); - free(key); - } - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_MICROSOFT, - RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY, - &keylen); - if (key) { - keys->recv = decrypt_ms_key(key, keylen, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->recv_len); - free(key); - } - - return keys; -} - - -struct radius_ms_mppe_keys * -radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - u8 *secret, size_t secret_len) -{ - u8 *key; - size_t keylen; - struct radius_ms_mppe_keys *keys; - - if (msg == NULL || sent_msg == NULL) - return NULL; - - keys = (struct radius_ms_mppe_keys *) malloc(sizeof(*keys)); - if (keys == NULL) - return NULL; - - memset(keys, 0, sizeof(*keys)); - - key = radius_msg_get_vendor_attr(msg, RADIUS_VENDOR_ID_CISCO, - RADIUS_CISCO_AV_PAIR, &keylen); - if (key && keylen == 51 && memcmp(key, "leap:session-key=", 17) == 0) { - keys->recv = decrypt_ms_key(key + 17, keylen - 17, - sent_msg->hdr->authenticator, - secret, secret_len, - &keys->recv_len); - free(key); - } - - return keys; -} - - -int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - const u8 *send_key, size_t send_key_len, - const u8 *recv_key, size_t recv_key_len) -{ - struct radius_attr_hdr *attr; - u32 vendor_id = htonl(RADIUS_VENDOR_ID_MICROSOFT); - u8 *buf; - struct radius_attr_vendor *vhdr; - u8 *pos; - size_t elen; - int hlen; - u16 salt; - - hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2; - - /* MS-MPPE-Send-Key */ - buf = malloc(hlen + send_key_len + 16); - if (buf == NULL) { - return 0; - } - pos = buf; - memcpy(pos, &vendor_id, sizeof(vendor_id)); - pos += sizeof(vendor_id); - vhdr = (struct radius_attr_vendor *) pos; - vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY; - pos = (u8 *) (vhdr + 1); - salt = random() | 0x8000; - *pos++ = salt >> 8; - *pos++ = salt; - encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret, - secret_len, pos, &elen); - vhdr->vendor_length = hlen + elen - sizeof(vendor_id); - - attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, - buf, hlen + elen); - free(buf); - if (attr == NULL) { - return 0; - } - - /* MS-MPPE-Recv-Key */ - buf = malloc(hlen + send_key_len + 16); - if (buf == NULL) { - return 0; - } - pos = buf; - memcpy(pos, &vendor_id, sizeof(vendor_id)); - pos += sizeof(vendor_id); - vhdr = (struct radius_attr_vendor *) pos; - vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY; - pos = (u8 *) (vhdr + 1); - salt ^= 1; - *pos++ = salt >> 8; - *pos++ = salt; - encrypt_ms_key(recv_key, recv_key_len, salt, req_authenticator, secret, - secret_len, pos, &elen); - vhdr->vendor_length = hlen + elen - sizeof(vendor_id); - - attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, - buf, hlen + elen); - free(buf); - if (attr == NULL) { - return 0; - } - - return 1; -} - - -/* Add User-Password attribute to a RADIUS message and encrypt it as specified - * in RFC 2865, Chap. 5.2 */ -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - u8 *data, size_t data_len, - u8 *secret, size_t secret_len) -{ - u8 buf[128]; - int padlen, i, pos; - MD5_CTX context; - size_t buf_len; - u8 hash[16]; - - if (data_len > 128) - return NULL; - - memcpy(buf, data, data_len); - buf_len = data_len; - - padlen = data_len % 16; - if (padlen) { - padlen = 16 - padlen; - memset(buf + data_len, 0, padlen); - buf_len += padlen; - } - - MD5Init(&context); - MD5Update(&context, secret, secret_len); - MD5Update(&context, msg->hdr->authenticator, 16); - MD5Final(hash, &context); - - for (i = 0; i < 16; i++) - buf[i] ^= hash[i]; - pos = 16; - - while (pos < buf_len) { - MD5Init(&context); - MD5Update(&context, secret, secret_len); - MD5Update(&context, &buf[pos - 16], 16); - MD5Final(hash, &context); - - for (i = 0; i < 16; i++) - buf[pos + i] ^= hash[i]; - - pos += 16; - } - - return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD, - buf, buf_len); -} - - -int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len) -{ - int i; - struct radius_attr_hdr *attr = NULL; - size_t dlen; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == type) { - attr = msg->attrs[i]; - break; - } - } - - if (!attr) - return -1; - - dlen = attr->length - sizeof(*attr); - if (buf) - memcpy(buf, (attr + 1), dlen > len ? len : dlen); - return dlen; -} - - -int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, - size_t *len) -{ - int i; - struct radius_attr_hdr *attr = NULL; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == type) { - attr = msg->attrs[i]; - break; - } - } - - if (!attr) - return -1; - - *buf = (u8 *) (attr + 1); - *len = attr->length - sizeof(*attr); - return 0; -} diff --git a/contrib/wpa_supplicant/radius.h b/contrib/wpa_supplicant/radius.h deleted file mode 100644 index 318e0adecf24..000000000000 --- a/contrib/wpa_supplicant/radius.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef RADIUS_H -#define RADIUS_H - -/* RFC 2865 - RADIUS */ - -struct radius_hdr { - u8 code; - u8 identifier; - u16 length; /* including this header */ - u8 authenticator[16]; - /* followed by length-20 octets of attributes */ -} __attribute__ ((packed)); - -enum { RADIUS_CODE_ACCESS_REQUEST = 1, - RADIUS_CODE_ACCESS_ACCEPT = 2, - RADIUS_CODE_ACCESS_REJECT = 3, - RADIUS_CODE_ACCOUNTING_REQUEST = 4, - RADIUS_CODE_ACCOUNTING_RESPONSE = 5, - RADIUS_CODE_ACCESS_CHALLENGE = 11, - RADIUS_CODE_STATUS_SERVER = 12, - RADIUS_CODE_STATUS_CLIENT = 13, - RADIUS_CODE_RESERVED = 255 -}; - -struct radius_attr_hdr { - u8 type; - u8 length; /* including this header */ - /* followed by length-2 octets of attribute value */ -} __attribute__ ((packed)); - -#define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr)) - -enum { RADIUS_ATTR_USER_NAME = 1, - RADIUS_ATTR_USER_PASSWORD = 2, - RADIUS_ATTR_NAS_IP_ADDRESS = 4, - RADIUS_ATTR_NAS_PORT = 5, - RADIUS_ATTR_FRAMED_MTU = 12, - RADIUS_ATTR_STATE = 24, - RADIUS_ATTR_CLASS = 25, - RADIUS_ATTR_VENDOR_SPECIFIC = 26, - RADIUS_ATTR_SESSION_TIMEOUT = 27, - RADIUS_ATTR_IDLE_TIMEOUT = 28, - RADIUS_ATTR_TERMINATION_ACTION = 29, - RADIUS_ATTR_CALLED_STATION_ID = 30, - RADIUS_ATTR_CALLING_STATION_ID = 31, - RADIUS_ATTR_NAS_IDENTIFIER = 32, - RADIUS_ATTR_ACCT_STATUS_TYPE = 40, - RADIUS_ATTR_ACCT_DELAY_TIME = 41, - RADIUS_ATTR_ACCT_INPUT_OCTETS = 42, - RADIUS_ATTR_ACCT_OUTPUT_OCTETS = 43, - RADIUS_ATTR_ACCT_SESSION_ID = 44, - RADIUS_ATTR_ACCT_AUTHENTIC = 45, - RADIUS_ATTR_ACCT_SESSION_TIME = 46, - RADIUS_ATTR_ACCT_INPUT_PACKETS = 47, - RADIUS_ATTR_ACCT_OUTPUT_PACKETS = 48, - RADIUS_ATTR_ACCT_TERMINATE_CAUSE = 49, - RADIUS_ATTR_ACCT_MULTI_SESSION_ID = 50, - RADIUS_ATTR_ACCT_LINK_COUNT = 51, - RADIUS_ATTR_ACCT_INPUT_GIGAWORDS = 52, - RADIUS_ATTR_ACCT_OUTPUT_GIGAWORDS = 53, - RADIUS_ATTR_EVENT_TIMESTAMP = 55, - RADIUS_ATTR_NAS_PORT_TYPE = 61, - RADIUS_ATTR_CONNECT_INFO = 77, - RADIUS_ATTR_EAP_MESSAGE = 79, - RADIUS_ATTR_MESSAGE_AUTHENTICATOR = 80, - RADIUS_ATTR_ACCT_INTERIM_INTERVAL = 85 -}; - - -/* Termination-Action */ -#define RADIUS_TERMINATION_ACTION_DEFAULT 0 -#define RADIUS_TERMINATION_ACTION_RADIUS_REQUEST 1 - -/* NAS-Port-Type */ -#define RADIUS_NAS_PORT_TYPE_IEEE_802_11 19 - -/* Acct-Status-Type */ -#define RADIUS_ACCT_STATUS_TYPE_START 1 -#define RADIUS_ACCT_STATUS_TYPE_STOP 2 -#define RADIUS_ACCT_STATUS_TYPE_INTERIM_UPDATE 3 -#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_ON 7 -#define RADIUS_ACCT_STATUS_TYPE_ACCOUNTING_OFF 8 - -/* Acct-Authentic */ -#define RADIUS_ACCT_AUTHENTIC_RADIUS 1 -#define RADIUS_ACCT_AUTHENTIC_LOCAL 2 -#define RADIUS_ACCT_AUTHENTIC_REMOTE 3 - -/* Acct-Terminate-Cause */ -#define RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST 1 -#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_CARRIER 2 -#define RADIUS_ACCT_TERMINATE_CAUSE_LOST_SERVICE 3 -#define RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT 4 -#define RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT 5 -#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET 6 -#define RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_REBOOT 7 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_ERROR 8 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_ERROR 9 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REQUEST 10 -#define RADIUS_ACCT_TERMINATE_CAUSE_NAS_REBOOT 11 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_UNNEEDED 12 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_PREEMPTED 13 -#define RADIUS_ACCT_TERMINATE_CAUSE_PORT_SUSPENDED 14 -#define RADIUS_ACCT_TERMINATE_CAUSE_SERVICE_UNAVAILABLE 15 -#define RADIUS_ACCT_TERMINATE_CAUSE_CALLBACK 16 -#define RADIUS_ACCT_TERMINATE_CAUSE_USER_ERROR 17 -#define RADIUS_ACCT_TERMINATE_CAUSE_HOST_REQUEST 18 - - -struct radius_attr_vendor { - u8 vendor_type; - u8 vendor_length; -} __attribute__ ((packed)); - -#define RADIUS_VENDOR_ID_CISCO 9 -#define RADIUS_CISCO_AV_PAIR 1 - -/* RFC 2548 - Microsoft Vendor-specific RADIUS Attributes */ -#define RADIUS_VENDOR_ID_MICROSOFT 311 - -enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16, - RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17 -}; - -struct radius_ms_mppe_keys { - u8 *send; - size_t send_len; - u8 *recv; - size_t recv_len; -}; - - -/* RADIUS message structure for new and parsed messages */ -struct radius_msg { - unsigned char *buf; - size_t buf_size; /* total size allocated for buf */ - size_t buf_used; /* bytes used in buf */ - - struct radius_hdr *hdr; - - struct radius_attr_hdr **attrs; /* array of pointers to attributes */ - size_t attr_size; /* total size of the attribute pointer array */ - size_t attr_used; /* total number of attributes in the array */ -}; - - -/* Default size to be allocated for new RADIUS messages */ -#define RADIUS_DEFAULT_MSG_SIZE 1024 - -/* Default size to be allocated for attribute array */ -#define RADIUS_DEFAULT_ATTR_COUNT 16 - - -/* MAC address ASCII format for IEEE 802.1X use - * (draft-congdon-radius-8021x-20.txt) */ -#define RADIUS_802_1X_ADDR_FORMAT "%02X-%02X-%02X-%02X-%02X-%02X" -/* MAC address ASCII format for non-802.1X use */ -#define RADIUS_ADDR_FORMAT "%02x%02x%02x%02x%02x%02x" - -struct radius_msg *radius_msg_new(u8 code, u8 identifier); -int radius_msg_initialize(struct radius_msg *msg, size_t init_len); -void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier); -void radius_msg_free(struct radius_msg *msg); -void radius_msg_dump(struct radius_msg *msg); -int radius_msg_finish(struct radius_msg *msg, u8 *secret, size_t secret_len); -int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_authenticator); -void radius_msg_finish_acct(struct radius_msg *msg, u8 *secret, - size_t secret_len); -struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type, - u8 *data, size_t data_len); -struct radius_msg *radius_msg_parse(const u8 *data, size_t len); -int radius_msg_add_eap(struct radius_msg *msg, u8 *data, size_t data_len); -u8 *radius_msg_get_eap(struct radius_msg *msg, size_t *len); -int radius_msg_verify(struct radius_msg *msg, u8 *secret, size_t secret_len, - struct radius_msg *sent_msg); -int radius_msg_verify_msg_auth(struct radius_msg *msg, const u8 *secret, - size_t secret_len, const u8 *req_auth); -int radius_msg_verify_acct(struct radius_msg *msg, u8 *secret, - size_t secret_len, struct radius_msg *sent_msg); -int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, - u8 type); -void radius_msg_make_authenticator(struct radius_msg *msg, - u8 *data, size_t len); -struct radius_ms_mppe_keys * -radius_msg_get_ms_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - u8 *secret, size_t secret_len); -struct radius_ms_mppe_keys * -radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg, - u8 *secret, size_t secret_len); -int radius_msg_add_mppe_keys(struct radius_msg *msg, - const u8 *req_authenticator, - const u8 *secret, size_t secret_len, - const u8 *send_key, size_t send_key_len, - const u8 *recv_key, size_t recv_key_len); -struct radius_attr_hdr * -radius_msg_add_attr_user_password(struct radius_msg *msg, - u8 *data, size_t data_len, - u8 *secret, size_t secret_len); -int radius_msg_get_attr(struct radius_msg *msg, u8 type, u8 *buf, size_t len); - -static inline int radius_msg_add_attr_int32(struct radius_msg *msg, u8 type, - u32 value) -{ - u32 val = htonl(value); - return radius_msg_add_attr(msg, type, (u8 *) &val, 4) != NULL; -} - -static inline int radius_msg_get_attr_int32(struct radius_msg *msg, u8 type, - u32 *value) -{ - u32 val; - int res; - res = radius_msg_get_attr(msg, type, (u8 *) &val, 4); - if (res != 4) - return -1; - - *value = ntohl(val); - return 0; -} -int radius_msg_get_attr_ptr(struct radius_msg *msg, u8 type, u8 **buf, - size_t *len); - -#endif /* RADIUS_H */ diff --git a/contrib/wpa_supplicant/radius_client.c b/contrib/wpa_supplicant/radius_client.c deleted file mode 100644 index 91ab3c7cda8b..000000000000 --- a/contrib/wpa_supplicant/radius_client.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * Host AP (software wireless LAN access point) user space daemon for - * Host AP kernel driver / RADIUS client / modified for eapol_test - * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 COPYING for - * more details. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <netinet/in.h> -#include <string.h> -#include <time.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> - -#include "common.h" -#include "wpa.h" -#include "config_ssid.h" -#include "wpa_supplicant.h" -#include "wpa_supplicant_i.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" -#include "l2_packet.h" - -#include "wpa_supplicant.h" -#define hostapd_logger(h, a, m, l, t...) wpa_printf(MSG_DEBUG, t) -#define HOSTAPD_DEBUG(l, a...) wpa_printf(MSG_DEBUG, a) -#define HOSTAPD_DEBUG_COND(l) 1 - -/* Defaults for RADIUS retransmit values (exponential backoff) */ -#define RADIUS_CLIENT_FIRST_WAIT 1 /* seconds */ -#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */ -#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts - * before entry is removed from retransmit - * list */ -#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit - * list (oldest will be removed, if this - * limit is exceeded) */ -#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this - * many failed retry attempts */ - - - -static int -radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int sock, int auth); - - -static void radius_client_msg_free(struct radius_msg_list *req) -{ - radius_msg_free(req->msg); - free(req->msg); - free(req); -} - - -int radius_client_register(struct wpa_supplicant *wpa_s, RadiusType msg_type, - RadiusRxResult (*handler)(struct wpa_supplicant *wpa_s, - struct radius_msg *msg, - struct radius_msg *req, - u8 *shared_secret, - size_t shared_secret_len, - void *data), - void *data) -{ - struct radius_rx_handler **handlers, *newh; - size_t *num; - - if (msg_type == RADIUS_ACCT) { - handlers = &wpa_s->radius->acct_handlers; - num = &wpa_s->radius->num_acct_handlers; - } else { - handlers = &wpa_s->radius->auth_handlers; - num = &wpa_s->radius->num_auth_handlers; - } - - newh = (struct radius_rx_handler *) - realloc(*handlers, - (*num + 1) * sizeof(struct radius_rx_handler)); - if (newh == NULL) - return -1; - - newh[*num].handler = handler; - newh[*num].data = data; - (*num)++; - *handlers = newh; - - return 0; -} - - -static int radius_client_retransmit(struct wpa_supplicant *wpa_s, - struct radius_msg_list *entry, time_t now) -{ - int s; - - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) - s = wpa_s->radius->acct_serv_sock; - else - s = wpa_s->radius->auth_serv_sock; - - /* retransmit; remove entry if too many attempts */ - entry->attempts++; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Resending RADIUS message (id=%d)" - "\n", entry->msg->hdr->identifier); - - if (send(s, entry->msg->buf, entry->msg->buf_used, 0) < 0) - perror("send[RADIUS]"); - - entry->next_try = now + entry->next_wait; - entry->next_wait *= 2; - if (entry->next_wait > RADIUS_CLIENT_MAX_WAIT) - entry->next_wait = RADIUS_CLIENT_MAX_WAIT; - if (entry->attempts >= RADIUS_CLIENT_MAX_RETRIES) { - printf("Removing un-ACKed RADIUS message due to too many " - "failed retransmit attempts\n"); - return 1; - } - - return 0; -} - - -static void radius_client_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - time_t now, first; - struct radius_msg_list *entry, *prev, *tmp; - int auth_failover = 0, acct_failover = 0; - - entry = wpa_s->radius->msgs; - if (!entry) - return; - - time(&now); - first = 0; - - prev = NULL; - while (entry) { - if (now >= entry->next_try && - radius_client_retransmit(wpa_s, entry, now)) { - if (prev) - prev->next = entry->next; - else - wpa_s->radius->msgs = entry->next; - - tmp = entry; - entry = entry->next; - radius_client_msg_free(tmp); - wpa_s->radius->num_msgs--; - continue; - } - - if (entry->attempts > RADIUS_CLIENT_NUM_FAILOVER) { - if (entry->msg_type == RADIUS_ACCT || - entry->msg_type == RADIUS_ACCT_INTERIM) - acct_failover++; - else - auth_failover++; - } - - if (first == 0 || entry->next_try < first) - first = entry->next_try; - - prev = entry; - entry = entry->next; - } - - if (wpa_s->radius->msgs) { - if (first < now) - first = now; - eloop_register_timeout(first - now, 0, - radius_client_timer, wpa_s, NULL); - } - - if (auth_failover && wpa_s->num_auth_servers > 1) { - struct hostapd_radius_server *next, *old; - old = wpa_s->auth_server; - hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_NOTICE, - "No response from Authentication server " - "%s:%d - failover", - inet_ntoa(old->addr), old->port); - - next = old + 1; - if (next > &(wpa_s->auth_servers - [wpa_s->num_auth_servers - 1])) - next = wpa_s->auth_servers; - wpa_s->auth_server = next; - radius_change_server(wpa_s, next, old, - wpa_s->radius->auth_serv_sock, 1); - } - - if (acct_failover && wpa_s->num_acct_servers > 1) { - struct hostapd_radius_server *next, *old; - old = wpa_s->acct_server; - hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_NOTICE, - "No response from Accounting server " - "%s:%d - failover", - inet_ntoa(old->addr), old->port); - next = old + 1; - if (next > &wpa_s->acct_servers - [wpa_s->num_acct_servers - 1]) - next = wpa_s->acct_servers; - wpa_s->acct_server = next; - radius_change_server(wpa_s, next, old, - wpa_s->radius->acct_serv_sock, 0); - } -} - - -static void radius_client_list_add(struct wpa_supplicant *wpa_s, struct radius_msg *msg, - RadiusType msg_type, u8 *shared_secret, - size_t shared_secret_len, u8 *addr) -{ - struct radius_msg_list *entry, *prev; - - if (eloop_terminated()) { - /* No point in adding entries to retransmit queue since event - * loop has already been terminated. */ - radius_msg_free(msg); - free(msg); - return; - } - - entry = malloc(sizeof(*entry)); - if (entry == NULL) { - printf("Failed to add RADIUS packet into retransmit list\n"); - radius_msg_free(msg); - free(msg); - return; - } - - memset(entry, 0, sizeof(*entry)); - if (addr) - memcpy(entry->addr, addr, ETH_ALEN); - entry->msg = msg; - entry->msg_type = msg_type; - entry->shared_secret = shared_secret; - entry->shared_secret_len = shared_secret_len; - time(&entry->first_try); - entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; - entry->attempts = 1; - entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; - - if (!wpa_s->radius->msgs) - eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, - radius_client_timer, wpa_s, NULL); - - entry->next = wpa_s->radius->msgs; - wpa_s->radius->msgs = entry; - - if (wpa_s->radius->num_msgs >= RADIUS_CLIENT_MAX_ENTRIES) { - printf("Removing the oldest un-ACKed RADIUS packet due to " - "retransmit list limits.\n"); - prev = NULL; - while (entry->next) { - prev = entry; - entry = entry->next; - } - if (prev) { - prev->next = NULL; - radius_client_msg_free(entry); - } - } else - wpa_s->radius->num_msgs++; -} - - -static void radius_client_list_del(struct wpa_supplicant *wpa_s, - RadiusType msg_type, u8 *addr) -{ - struct radius_msg_list *entry, *prev, *tmp; - - if (addr == NULL) - return; - - entry = wpa_s->radius->msgs; - prev = NULL; - while (entry) { - if (entry->msg_type == msg_type && - memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (prev) - prev->next = entry->next; - else - wpa_s->radius->msgs = entry->next; - tmp = entry; - entry = entry->next; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Removing matching RADIUS message for " - MACSTR "\n", MAC2STR(addr)); - radius_client_msg_free(tmp); - wpa_s->radius->num_msgs--; - continue; - } - prev = entry; - entry = entry->next; - } -} - - -int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg, - RadiusType msg_type, u8 *addr) -{ - u8 *shared_secret; - size_t shared_secret_len; - char *name; - int s, res; - - if (msg_type == RADIUS_ACCT_INTERIM) { - /* Remove any pending interim acct update for the same STA. */ - radius_client_list_del(wpa_s, msg_type, addr); - } - - if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { - shared_secret = wpa_s->acct_server->shared_secret; - shared_secret_len = wpa_s->acct_server->shared_secret_len; - radius_msg_finish_acct(msg, shared_secret, shared_secret_len); - name = "accounting"; - s = wpa_s->radius->acct_serv_sock; - } else { - shared_secret = wpa_s->auth_server->shared_secret; - shared_secret_len = wpa_s->auth_server->shared_secret_len; - radius_msg_finish(msg, shared_secret, shared_secret_len); - name = "authentication"; - s = wpa_s->radius->auth_serv_sock; - } - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Sending RADIUS message to %s server\n", name); - if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) - radius_msg_dump(msg); - - res = send(s, msg->buf, msg->buf_used, 0); - if (res < 0) - perror("send[RADIUS]"); - - radius_client_list_add(wpa_s, msg, msg_type, shared_secret, - shared_secret_len, addr); - - return res; -} - - -static void radius_client_receive(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = (struct wpa_supplicant *) eloop_ctx; - RadiusType msg_type = (RadiusType) sock_ctx; - int len, i; - unsigned char buf[3000]; - struct radius_msg *msg; - struct radius_rx_handler *handlers; - size_t num_handlers; - struct radius_msg_list *req, *prev_req; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv[RADIUS]"); - return; - } - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Received %d bytes from RADIUS server\n", len); - if (len == sizeof(buf)) { - printf("Possibly too long UDP frame for our buffer - " - "dropping it\n"); - return; - } - - msg = radius_msg_parse(buf, len); - if (msg == NULL) { - printf("Parsing incoming RADIUS frame failed\n"); - return; - } - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Received RADIUS message\n"); - if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) - radius_msg_dump(msg); - - if (msg_type == RADIUS_ACCT) { - handlers = wpa_s->radius->acct_handlers; - num_handlers = wpa_s->radius->num_acct_handlers; - } else { - handlers = wpa_s->radius->auth_handlers; - num_handlers = wpa_s->radius->num_auth_handlers; - } - - prev_req = NULL; - req = wpa_s->radius->msgs; - while (req) { - /* TODO: also match by src addr:port of the packet when using - * alternative RADIUS servers (?) */ - if ((req->msg_type == msg_type || - (req->msg_type == RADIUS_ACCT_INTERIM && - msg_type == RADIUS_ACCT)) && - req->msg->hdr->identifier == msg->hdr->identifier) - break; - - prev_req = req; - req = req->next; - } - - if (req == NULL) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "No matching RADIUS request found (type=%d " - "id=%d) - dropping packet\n", - msg_type, msg->hdr->identifier); - goto fail; - } - - /* Remove ACKed RADIUS packet from retransmit list */ - if (prev_req) - prev_req->next = req->next; - else - wpa_s->radius->msgs = req->next; - wpa_s->radius->num_msgs--; - - for (i = 0; i < num_handlers; i++) { - RadiusRxResult res; - res = handlers[i].handler(wpa_s, msg, req->msg, - req->shared_secret, - req->shared_secret_len, - handlers[i].data); - switch (res) { - case RADIUS_RX_PROCESSED: - radius_msg_free(msg); - free(msg); - /* continue */ - case RADIUS_RX_QUEUED: - radius_client_msg_free(req); - return; - case RADIUS_RX_UNKNOWN: - /* continue with next handler */ - break; - } - } - - printf("No RADIUS RX handler found (type=%d code=%d id=%d) - dropping " - "packet\n", msg_type, msg->hdr->code, msg->hdr->identifier); - radius_client_msg_free(req); - - fail: - radius_msg_free(msg); - free(msg); -} - - -u8 radius_client_get_id(struct wpa_supplicant *wpa_s) -{ - struct radius_msg_list *entry, *prev, *remove; - u8 id = wpa_s->radius->next_radius_identifier++; - - /* remove entries with matching id from retransmit list to avoid - * using new reply from the RADIUS server with an old request */ - entry = wpa_s->radius->msgs; - prev = NULL; - while (entry) { - if (entry->msg->hdr->identifier == id) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Removing pending RADIUS message, since " - "its id (%d) is reused\n", id); - if (prev) - prev->next = entry->next; - else - wpa_s->radius->msgs = entry->next; - remove = entry; - } else - remove = NULL; - prev = entry; - entry = entry->next; - - if (remove) - radius_client_msg_free(remove); - } - - return id; -} - - -void radius_client_flush(struct wpa_supplicant *wpa_s) -{ - struct radius_msg_list *entry, *prev; - - if (!wpa_s->radius) - return; - - eloop_cancel_timeout(radius_client_timer, wpa_s, NULL); - - entry = wpa_s->radius->msgs; - wpa_s->radius->msgs = NULL; - wpa_s->radius->num_msgs = 0; - while (entry) { - prev = entry; - entry = entry->next; - radius_client_msg_free(prev); - } -} - - -static int -radius_change_server(struct wpa_supplicant *wpa_s, struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int sock, int auth) -{ - struct sockaddr_in serv; - - hostapd_logger(wpa_s, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, - "%s server %s:%d", - auth ? "Authentication" : "Accounting", - inet_ntoa(nserv->addr), nserv->port); - - if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || - memcmp(nserv->shared_secret, oserv->shared_secret, - nserv->shared_secret_len) != 0) { - /* Pending RADIUS packets used different shared - * secret, so they would need to be modified. Could - * update all message authenticators and - * User-Passwords, etc. and retry with new server. For - * now, just drop all pending packets. */ - radius_client_flush(wpa_s); - } else { - /* Reset retry counters for the new server */ - struct radius_msg_list *entry; - entry = wpa_s->radius->msgs; - while (entry) { - entry->next_try = entry->first_try + - RADIUS_CLIENT_FIRST_WAIT; - entry->attempts = 0; - entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; - entry = entry->next; - } - if (wpa_s->radius->msgs) { - eloop_cancel_timeout(radius_client_timer, wpa_s, NULL); - eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, - radius_client_timer, wpa_s, - NULL); - } - } - - memset(&serv, 0, sizeof(serv)); - serv.sin_family = AF_INET; - serv.sin_addr.s_addr = nserv->addr.s_addr; - serv.sin_port = htons(nserv->port); - - if (connect(sock, (struct sockaddr *) &serv, sizeof(serv)) < 0) { - perror("connect[radius]"); - return -1; - } - - return 0; -} - - -static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - struct hostapd_radius_server *oserv; - - if (wpa_s->radius->auth_serv_sock >= 0 && wpa_s->auth_servers && - wpa_s->auth_server != wpa_s->auth_servers) { - oserv = wpa_s->auth_server; - wpa_s->auth_server = wpa_s->auth_servers; - radius_change_server(wpa_s, wpa_s->auth_server, oserv, - wpa_s->radius->auth_serv_sock, 1); - } - - if (wpa_s->radius->acct_serv_sock >= 0 && wpa_s->acct_servers && - wpa_s->acct_server != wpa_s->acct_servers) { - oserv = wpa_s->acct_server; - wpa_s->acct_server = wpa_s->acct_servers; - radius_change_server(wpa_s, wpa_s->acct_server, oserv, - wpa_s->radius->acct_serv_sock, 0); - } - - if (wpa_s->radius_retry_primary_interval) - eloop_register_timeout(wpa_s-> - radius_retry_primary_interval, 0, - radius_retry_primary_timer, wpa_s, NULL); -} - - -static int radius_client_init_auth(struct wpa_supplicant *wpa_s) -{ - wpa_s->radius->auth_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (wpa_s->radius->auth_serv_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - return -1; - } - - radius_change_server(wpa_s, wpa_s->auth_server, NULL, - wpa_s->radius->auth_serv_sock, 1); - - if (eloop_register_read_sock(wpa_s->radius->auth_serv_sock, - radius_client_receive, wpa_s, - (void *) RADIUS_AUTH)) { - printf("Could not register read socket for authentication " - "server\n"); - return -1; - } - - return 0; -} - - -static int radius_client_init_acct(struct wpa_supplicant *wpa_s) -{ - wpa_s->radius->acct_serv_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (wpa_s->radius->acct_serv_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - return -1; - } - - radius_change_server(wpa_s, wpa_s->acct_server, NULL, - wpa_s->radius->acct_serv_sock, 0); - - if (eloop_register_read_sock(wpa_s->radius->acct_serv_sock, - radius_client_receive, wpa_s, - (void *) RADIUS_ACCT)) { - printf("Could not register read socket for accounting " - "server\n"); - return -1; - } - - return 0; -} - - -int radius_client_init(struct wpa_supplicant *wpa_s) -{ - wpa_s->radius = malloc(sizeof(struct radius_client_data)); - if (wpa_s->radius == NULL) - return -1; - - memset(wpa_s->radius, 0, sizeof(struct radius_client_data)); - wpa_s->radius->auth_serv_sock = wpa_s->radius->acct_serv_sock = -1; - - if (wpa_s->auth_server && radius_client_init_auth(wpa_s)) - return -1; - - if (wpa_s->acct_server && radius_client_init_acct(wpa_s)) - return -1; - - if (wpa_s->radius_retry_primary_interval) - eloop_register_timeout(wpa_s->radius_retry_primary_interval, 0, - radius_retry_primary_timer, wpa_s, - NULL); - - return 0; -} - - -void radius_client_deinit(struct wpa_supplicant *wpa_s) -{ - if (!wpa_s->radius) - return; - - eloop_cancel_timeout(radius_retry_primary_timer, wpa_s, NULL); - - radius_client_flush(wpa_s); - free(wpa_s->radius->auth_handlers); - free(wpa_s->radius->acct_handlers); - free(wpa_s->radius); - wpa_s->radius = NULL; -} diff --git a/contrib/wpa_supplicant/radius_client.h b/contrib/wpa_supplicant/radius_client.h deleted file mode 100644 index 993f8d0b7102..000000000000 --- a/contrib/wpa_supplicant/radius_client.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef RADIUS_CLIENT_H -#define RADIUS_CLIENT_H - -typedef enum { - RADIUS_AUTH, - RADIUS_ACCT, - RADIUS_ACCT_INTERIM /* used only with radius_client_send(); just like - * RADIUS_ACCT, but removes any pending interim - * RADIUS Accounting packages for the same STA - * before sending the new interim update */ -} RadiusType; - -/* RADIUS message retransmit list */ -struct radius_msg_list { - u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages - * for the same STA. */ - struct radius_msg *msg; - RadiusType msg_type; - time_t first_try; - time_t next_try; - int attempts; - int next_wait; - - u8 *shared_secret; - size_t shared_secret_len; - - /* TODO: server config with failover to backup server(s) */ - - struct radius_msg_list *next; -}; - - -typedef enum { - RADIUS_RX_PROCESSED, - RADIUS_RX_QUEUED, - RADIUS_RX_UNKNOWN -} RadiusRxResult; - -struct radius_rx_handler { - RadiusRxResult (*handler)(struct wpa_supplicant *wpa_s, - struct radius_msg *msg, - struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, - void *data); - void *data; -}; - -struct radius_client_data { - int auth_serv_sock; /* socket for authentication RADIUS messages */ - int acct_serv_sock; /* socket for accounting RADIUS messages */ - - struct radius_rx_handler *auth_handlers; - size_t num_auth_handlers; - struct radius_rx_handler *acct_handlers; - size_t num_acct_handlers; - - struct radius_msg_list *msgs; - size_t num_msgs; - - u8 next_radius_identifier; - u32 acct_session_id_hi; - u32 acct_session_id_lo; -}; - - -int radius_client_register(struct wpa_supplicant *wpa_s, RadiusType msg_type, - RadiusRxResult (*handler) - (struct wpa_supplicant *wpa_s, - struct radius_msg *msg, struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, - void *data), - void *data); -int radius_client_send(struct wpa_supplicant *wpa_s, struct radius_msg *msg, - RadiusType msg_type, u8 *addr); -u8 radius_client_get_id(struct wpa_supplicant *wpa_s); - -void radius_client_flush(struct wpa_supplicant *wpa_s); -int radius_client_init(struct wpa_supplicant *wpa_s); -void radius_client_deinit(struct wpa_supplicant *wpa_s); - -#endif /* RADIUS_CLIENT_H */ diff --git a/contrib/wpa_supplicant/rc4.c b/contrib/wpa_supplicant/rc4.c deleted file mode 100644 index 97ec1b0ae357..000000000000 --- a/contrib/wpa_supplicant/rc4.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Host AP (software wireless LAN access point) user space daemon for - * Host AP kernel driver / RC4 - * Copyright (c) 2002-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdio.h> -#include "common.h" -#include "rc4.h" - -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - -void rc4_skip(u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) -{ - u32 i, j, k; - u8 S[256], *pos; - int 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]; - } -} - - -void rc4(u8 *buf, size_t len, u8 *key, size_t key_len) -{ - rc4_skip(key, key_len, 0, buf, len); -} diff --git a/contrib/wpa_supplicant/rc4.h b/contrib/wpa_supplicant/rc4.h deleted file mode 100644 index 0e77b7e470d0..000000000000 --- a/contrib/wpa_supplicant/rc4.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef RC4_H -#define RC4_H - -void rc4_skip(u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len); -void rc4(u8 *buf, size_t len, u8 *key, size_t key_len); - -#endif /* RC4_H */ diff --git a/contrib/wpa_supplicant/sha1.c b/contrib/wpa_supplicant/sha1.c deleted file mode 100644 index 04943b5a775c..000000000000 --- a/contrib/wpa_supplicant/sha1.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "common.h" -#include "sha1.h" -#include "md5.h" - - -void sha1_mac(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - SHA1_CTX context; - SHA1Init(&context); - SHA1Update(&context, key, key_len); - SHA1Update(&context, data, data_len); - SHA1Update(&context, key, key_len); - SHA1Final(mac, &context); -} - - -/* HMAC code is based on RFC 2104 */ -void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - SHA1_CTX context; - unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */ - unsigned char k_opad[65]; /* outer padding - key XORd with opad */ - unsigned char tk[20]; - int i; - - /* if key is longer than 64 bytes reset it to key = SHA1(key) */ - if (key_len > 64) { - SHA1Init(&context); - SHA1Update(&context, key, key_len); - SHA1Final(tk, &context); - - 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 pads */ - memset(k_ipad, 0, sizeof(k_ipad)); - memset(k_opad, 0, sizeof(k_opad)); - memcpy(k_ipad, key, key_len); - memcpy(k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - k_ipad[i] ^= 0x36; - k_opad[i] ^= 0x5c; - } - - /* perform inner SHA1 */ - SHA1Init(&context); /* init context for 1st pass */ - SHA1Update(&context, k_ipad, 64); /* start with inner pad */ - /* then text of datagram; all fragments */ - for (i = 0; i < num_elem; i++) { - SHA1Update(&context, addr[i], len[i]); - } - SHA1Final(mac, &context); /* finish up 1st pass */ - - /* perform outer SHA1 */ - SHA1Init(&context); /* init context for 2nd pass */ - SHA1Update(&context, k_opad, 64); /* start with outer pad */ - SHA1Update(&context, mac, 20); /* then results of 1st hash */ - SHA1Final(mac, &context); /* finish up 2nd pass */ -} - - -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); -} - - -void 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 zero = 0, counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = strlen(label); - const unsigned char *addr[4]; - size_t len[4]; - - addr[0] = (u8 *) label; - len[0] = label_len; - addr[1] = &zero; - len[1] = 1; - addr[2] = data; - len[2] = data_len; - addr[3] = &counter; - len[3] = 1; - - pos = 0; - while (pos < buf_len) { - plen = buf_len - pos; - if (plen >= SHA1_MAC_LEN) { - hmac_sha1_vector(key, key_len, 4, addr, len, - &buf[pos]); - pos += SHA1_MAC_LEN; - } else { - hmac_sha1_vector(key, key_len, 4, addr, len, - hash); - memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -/* draft-cam-winget-eap-fast-00.txt */ -void 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 = 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; - hmac_sha1_vector(key, key_len, 5, addr, len, hash); - if (plen >= SHA1_MAC_LEN) { - memcpy(&buf[pos], hash, SHA1_MAC_LEN); - pos += SHA1_MAC_LEN; - } else { - memcpy(&buf[pos], hash, plen); - break; - } - len[0] = SHA1_MAC_LEN; - } -} - - -/* RFC 2246 */ -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; - 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 i, 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] = 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] = 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; - - hmac_md5_vector(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(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); - MD5_pos = 0; - hmac_md5(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; -} - - -static void pbkdf2_sha1_f(const char *passphrase, const char *ssid, - size_t ssid_len, int iterations, 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 = 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; - hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp); - memcpy(digest, tmp, SHA1_MAC_LEN); - - for (i = 1; i < iterations; i++) { - hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, - tmp2); - memcpy(tmp, tmp2, SHA1_MAC_LEN); - for (j = 0; j < SHA1_MAC_LEN; j++) - digest[j] ^= tmp2[j]; - } -} - - -void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen) -{ - int count = 0; - unsigned char *pos = buf; - size_t left = buflen, plen; - unsigned char digest[SHA1_MAC_LEN]; - - while (left > 0) { - count++; - pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, - digest); - plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; - memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } -} - - -void sha1_transform(u8 *state, u8 data[64]) -{ -#ifdef EAP_TLS_FUNCS - SHA_CTX context; - memset(&context, 0, sizeof(context)); - memcpy(&context.h0, state, 5 * 4); - SHA1_Transform(&context, data); - memcpy(state, &context.h0, 5 * 4); -#else /* EAP_TLS_FUNCS */ - SHA1Transform((u32 *) state, data); -#endif /* EAP_TLS_FUNCS */ -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - SHA1_CTX ctx; - int i; - - SHA1Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1Update(&ctx, addr[i], len[i]); - SHA1Final(mac, &ctx); -} - - -#ifndef EAP_TLS_FUNCS - -/* ===== start - public domain SHA1 implementation ===== */ - -/* -SHA-1 in C -By Steve Reid <sreid@sea-to-sky.net> -100% Public Domain - ------------------ -Modified 7/98 -By James H. Brown <jbrown@burgoyne.com> -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 <process.h> 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 <sreid@sea-to-sky.net> -Still 100% public domain - -1- Removed #include <process.h> 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 <Saul.Kravitz@celera.com> -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Modified 4/01 -By Jouni Malinen <jkmaline@cc.hut.fi> -Minor changes to match the coding style used in Dynamics. - -Modified September 24, 2004 -By Jouni Malinen <jkmaline@cc.hut.fi> -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 - u32 workspace[16]; - block = (CHAR64LONG16 *) workspace; - 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 - 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) { - 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; - 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; - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(finalcount, 0, 8); -} - -/* ===== end - public domain SHA1 implementation ===== */ - -#endif /* EAP_TLS_FUNCS */ - - -#ifdef TEST_MAIN - -#include "md5.c" - -static int test_eap_fast(void) -{ - /* draft-cam-winget-eap-fast-01.txt */ - const u8 pac_key[] = { - 0x0B, 0x97, 0x39, 0x0F, 0x37, 0x51, 0x78, 0x09, - 0x81, 0x1E, 0xFD, 0x9C, 0x6E, 0x65, 0x94, 0x2B, - 0x63, 0x2C, 0xE9, 0x53, 0x89, 0x38, 0x08, 0xBA, - 0x36, 0x0B, 0x03, 0x7C, 0xD1, 0x85, 0xE4, 0x14 - }; - const u8 seed[] = { - 0x3F, 0xFB, 0x11, 0xC4, 0x6C, 0xBF, 0xA5, 0x7A, - 0x54, 0x40, 0xDA, 0xE8, 0x22, 0xD3, 0x11, 0xD3, - 0xF7, 0x6D, 0xE4, 0x1D, 0xD9, 0x33, 0xE5, 0x93, - 0x70, 0x97, 0xEB, 0xA9, 0xB3, 0x66, 0xF4, 0x2A, - 0x00, 0x00, 0x00, 0x02, 0x6A, 0x66, 0x43, 0x2A, - 0x8D, 0x14, 0x43, 0x2C, 0xEC, 0x58, 0x2D, 0x2F, - 0xC7, 0x9C, 0x33, 0x64, 0xBA, 0x04, 0xAD, 0x3A, - 0x52, 0x54, 0xD6, 0xA5, 0x79, 0xAD, 0x1E, 0x00 - }; - const u8 master_secret[] = { - 0x4A, 0x1A, 0x51, 0x2C, 0x01, 0x60, 0xBC, 0x02, - 0x3C, 0xCF, 0xBC, 0x83, 0x3F, 0x03, 0xBC, 0x64, - 0x88, 0xC1, 0x31, 0x2F, 0x0B, 0xA9, 0xA2, 0x77, - 0x16, 0xA8, 0xD8, 0xE8, 0xBD, 0xC9, 0xD2, 0x29, - 0x38, 0x4B, 0x7A, 0x85, 0xBE, 0x16, 0x4D, 0x27, - 0x33, 0xD5, 0x24, 0x79, 0x87, 0xB1, 0xC5, 0xA2 - }; - const u8 key_block[] = { - 0x59, 0x59, 0xBE, 0x8E, 0x41, 0x3A, 0x77, 0x74, - 0x8B, 0xB2, 0xE5, 0xD3, 0x60, 0xAC, 0x4D, 0x35, - 0xDF, 0xFB, 0xC8, 0x1E, 0x9C, 0x24, 0x9C, 0x8B, - 0x0E, 0xC3, 0x1D, 0x72, 0xC8, 0x84, 0x9D, 0x57, - 0x48, 0x51, 0x2E, 0x45, 0x97, 0x6C, 0x88, 0x70, - 0xBE, 0x5F, 0x01, 0xD3, 0x64, 0xE7, 0x4C, 0xBB, - 0x11, 0x24, 0xE3, 0x49, 0xE2, 0x3B, 0xCD, 0xEF, - 0x7A, 0xB3, 0x05, 0x39, 0x5D, 0x64, 0x8A, 0x44, - 0x11, 0xB6, 0x69, 0x88, 0x34, 0x2E, 0x8E, 0x29, - 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05, - 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96, - 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84, - 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98, - 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71 - }; - const u8 sks[] = { - 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05, - 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96, - 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84, - 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98, - 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71 - }; - const u8 isk[] = { - 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 - }; - const u8 imck[] = { - 0x16, 0x15, 0x3C, 0x3F, 0x21, 0x55, 0xEF, 0xD9, - 0x7F, 0x34, 0xAE, 0xC8, 0x1A, 0x4E, 0x66, 0x80, - 0x4C, 0xC3, 0x76, 0xF2, 0x8A, 0xA9, 0x6F, 0x96, - 0xC2, 0x54, 0x5F, 0x8C, 0xAB, 0x65, 0x02, 0xE1, - 0x18, 0x40, 0x7B, 0x56, 0xBE, 0xEA, 0xA7, 0xC5, - 0x76, 0x5D, 0x8F, 0x0B, 0xC5, 0x07, 0xC6, 0xB9, - 0x04, 0xD0, 0x69, 0x56, 0x72, 0x8B, 0x6B, 0xB8, - 0x15, 0xEC, 0x57, 0x7B - }; - const u8 msk[] = { - 0x4D, 0x83, 0xA9, 0xBE, 0x6F, 0x8A, 0x74, 0xED, - 0x6A, 0x02, 0x66, 0x0A, 0x63, 0x4D, 0x2C, 0x33, - 0xC2, 0xDA, 0x60, 0x15, 0xC6, 0x37, 0x04, 0x51, - 0x90, 0x38, 0x63, 0xDA, 0x54, 0x3E, 0x14, 0xB9, - 0x27, 0x99, 0x18, 0x1E, 0x07, 0xBF, 0x0F, 0x5A, - 0x5E, 0x3C, 0x32, 0x93, 0x80, 0x8C, 0x6C, 0x49, - 0x67, 0xED, 0x24, 0xFE, 0x45, 0x40, 0xA0, 0x59, - 0x5E, 0x37, 0xC2, 0xE9, 0xD0, 0x5D, 0x0A, 0xE3 - }; - u8 tlv[] = { - 0x80, 0x0C, 0x00, 0x38, 0x00, 0x01, 0x01, 0x00, - 0xD8, 0x6A, 0x8C, 0x68, 0x3C, 0x32, 0x31, 0xA8, - 0x56, 0x63, 0xB6, 0x40, 0x21, 0xFE, 0x21, 0x14, - 0x4E, 0xE7, 0x54, 0x20, 0x79, 0x2D, 0x42, 0x62, - 0xC9, 0xBF, 0x53, 0x7F, 0x54, 0xFD, 0xAC, 0x58, - 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF, - 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC, - 0x05, 0xC5, 0x5B, 0xB7 - }; - const u8 compound_mac[] = { - 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF, - 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC, - 0x05, 0xC5, 0x5B, 0xB7 - }; - u8 buf[512]; - const u8 *simck, *cmk; - int errors = 0; - - printf("EAP-FAST test cases\n"); - - printf("- T-PRF (SHA1) test case / master_secret\n"); - sha1_t_prf(pac_key, sizeof(pac_key), "PAC to master secret label hash", - seed, sizeof(seed), buf, sizeof(master_secret)); - if (memcmp(master_secret, buf, sizeof(master_secret)) != 0) { - printf("T-PRF test - FAILED!\n"); - errors++; - } - - printf("- PRF (TLS, SHA1/MD5) test case / key_block\n"); - tls_prf(master_secret, sizeof(master_secret), "key expansion", - seed, sizeof(seed), buf, sizeof(key_block)); - if (memcmp(key_block, buf, sizeof(key_block)) != 0) { - printf("PRF test - FAILED!\n"); - errors++; - } - - printf("- T-PRF (SHA1) test case / IMCK\n"); - sha1_t_prf(sks, sizeof(sks), "Inner Methods Compound Keys", - isk, sizeof(isk), buf, sizeof(imck)); - if (memcmp(imck, buf, sizeof(imck)) != 0) { - printf("T-PRF test - FAILED!\n"); - errors++; - } - - simck = imck; - cmk = imck + 40; - - printf("- T-PRF (SHA1) test case / MSK\n"); - sha1_t_prf(simck, 40, "Session Key Generating Function", - "", 0, buf, sizeof(msk)); - if (memcmp(msk, buf, sizeof(msk)) != 0) { - printf("T-PRF test - FAILED!\n"); - errors++; - } - - printf("- Compound MAC test case\n"); - memset(tlv + sizeof(tlv) - 20, 0, 20); - hmac_sha1(cmk, 20, tlv, sizeof(tlv), tlv + sizeof(tlv) - 20); - if (memcmp(tlv + sizeof(tlv) - 20, compound_mac, sizeof(compound_mac)) - != 0) { - printf("Compound MAC test - FAILED!\n"); - errors++; - } - - return errors; -} - - -static u8 key0[] = -{ - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b -}; -static u8 data0[] = "Hi There"; -static u8 prf0[] = -{ - 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84, - 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54, - 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06, - 0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee, - 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88, - 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb, - 0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e, - 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a -}; - -static u8 key1[] = "Jefe"; -static u8 data1[] = "what do ya want for nothing?"; -static u8 prf1[] = -{ - 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad, - 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4, - 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58, - 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09, - 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa, - 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02, - 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7, - 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc -}; - - -static u8 key2[] = -{ - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa -}; -static u8 data2[] = -{ - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd -}; -static u8 prf2[] = -{ - 0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f, - 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1, - 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1, - 0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce, - 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc, - 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae, - 0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6, - 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07 -}; - - -struct passphrase_test { - char *passphrase; - char *ssid; - char psk[32]; -}; - -static struct passphrase_test passphrase_tests[] = -{ - { - "password", - "IEEE", - { - 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef, - 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90, - 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2, - 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e - } - }, - { - "ThisIsAPassword", - "ThisIsASSID", - { - 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6, - 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3, - 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08, - 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf - } - }, - { - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", - { - 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83, - 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c, - 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48, - 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62 - } - }, -}; - -#define NUM_PASSPHRASE_TESTS \ -(sizeof(passphrase_tests) / sizeof(passphrase_tests[0])) - - -int main(int argc, char *argv[]) -{ - u8 res[512]; - int ret = 0, i; - - printf("PRF-SHA1 test cases:\n"); - - sha1_prf(key0, sizeof(key0), "prefix", data0, sizeof(data0) - 1, - res, sizeof(prf0)); - if (memcmp(res, prf0, sizeof(prf0)) == 0) - printf("Test case 0 - OK\n"); - else { - printf("Test case 0 - FAILED!\n"); - ret++; - } - - sha1_prf(key1, sizeof(key1) - 1, "prefix", data1, sizeof(data1) - 1, - res, sizeof(prf1)); - if (memcmp(res, prf1, sizeof(prf1)) == 0) - printf("Test case 1 - OK\n"); - else { - printf("Test case 1 - FAILED!\n"); - ret++; - } - - sha1_prf(key2, sizeof(key2), "prefix", data2, sizeof(data2), - res, sizeof(prf2)); - if (memcmp(res, prf2, sizeof(prf2)) == 0) - printf("Test case 2 - OK\n"); - else { - printf("Test case 2 - FAILED!\n"); - ret++; - } - - ret += test_eap_fast(); - - printf("PBKDF2-SHA1 Passphrase test cases:\n"); - for (i = 0; i < NUM_PASSPHRASE_TESTS; i++) { - u8 psk[32]; - struct passphrase_test *test = &passphrase_tests[i]; - pbkdf2_sha1(test->passphrase, - test->ssid, strlen(test->ssid), - 4096, psk, 32); - if (memcmp(psk, test->psk, 32) == 0) - printf("Test case %d - OK\n", i); - else { - printf("Test case %d - FAILED!\n", i); - ret++; - } - } - - return ret; -} -#endif /* TEST_MAIN */ diff --git a/contrib/wpa_supplicant/sha1.h b/contrib/wpa_supplicant/sha1.h deleted file mode 100644 index 186e3c1c25b1..000000000000 --- a/contrib/wpa_supplicant/sha1.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef SHA1_H -#define SHA1_H - -#ifdef EAP_TLS_FUNCS - -#include <openssl/sha.h> - -#define SHA1_CTX SHA_CTX -#define SHA1Init SHA1_Init -#define SHA1Update SHA1_Update -#define SHA1Final SHA1_Final -#define SHA1Transform SHA1_Transform -#define SHA1_MAC_LEN SHA_DIGEST_LENGTH - -#else /* EAP_TLS_FUNCS */ - -#define SHA1_MAC_LEN 20 - -typedef struct { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -} SHA1_CTX; - -void SHA1Init(SHA1_CTX *context); -void SHA1Update(SHA1_CTX *context, const void *data, u32 len); -void SHA1Final(unsigned char digest[20], SHA1_CTX* context); -void SHA1Transform(u32 state[5], const unsigned char buffer[64]); - -#endif /* EAP_TLS_FUNCS */ - -void sha1_mac(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -void 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); -void 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 tls_prf(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen); -void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); -void sha1_transform(u8 *state, u8 data[64]); -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); - -#endif /* SHA1_H */ diff --git a/contrib/wpa_supplicant/tls.h b/contrib/wpa_supplicant/tls.h deleted file mode 100644 index 99c9b332360a..000000000000 --- a/contrib/wpa_supplicant/tls.h +++ /dev/null @@ -1,312 +0,0 @@ -#ifndef TLS_H -#define TLS_H - -struct tls_connection; - -struct tls_keys { - const u8 *master_key; - size_t master_key_len; - const u8 *client_random; - size_t client_random_len; - const u8 *server_random; - size_t server_random_len; -}; - -/** - * tls_init - initialize 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. - */ -void * tls_init(void); - -/** - * tls_deinit - deinitialize TLS library - * @tls_ctx: TLS context data from tls_init() - * - * Called once during program shutdown. - */ -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 data. - * @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); - -/** - * tls_connection_ca_cert - set trusted CA certificate for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @ca_cert: File name for CA certificate in PEM or DER format - * @subject_match: String to match in the subject of the peer certificate or - * %NULL to allow all subjects - * - * Returns: 0 on success, -1 on failure - */ -int tls_connection_ca_cert(void *tls_ctx, struct tls_connection *conn, - const char *ca_cert, const char *subject_match); - -/** - * tls_global_ca_cert - set trusted CA certificate for all TLS connections - * @tls_ctx: TLS context data from tls_init() - * @ca_cert: File name for CA certificate in PEM or DER format - * %NULL to allow all subjects - * - * Returns: 0 on success, -1 on failure - */ -int tls_global_ca_cert(void *tls_ctx, const char *ca_cert); - -/** - * tls_connection_ca_cert - set trusted CA certificate for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @verify_peer: 1 = verify peer certificate - * @subject_match: String to match in the subject of the peer certificate or - * %NULL to allow all subjects - * - * Returns: 0 on success, -1 on failure - */ -int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, - int verify_peer, const char *subject_match); - -/** - * tls_connection_client_cert - set client certificate for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @client_cert: File name for client certificate in PEM or DER format - * - * Returns: 0 on success, -1 on failure - */ -int tls_connection_client_cert(void *tls_ctx, struct tls_connection *conn, - const char *client_cert); - -/** - * tls_global_client_cert - set client certificate for all TLS connections - * @tls_ctx: TLS context data from tls_init() - * @client_cert: File name for client certificate in PEM or DER format - * - * Returns: 0 on success, -1 on failure - */ -int tls_global_client_cert(void *tls_ctx, const char *client_cert); - -/** - * tls_connection_private_key - set private key for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @private_key: File name for client private key in PEM or DER format - * @private_key_passwd: Passphrase for decrypted private key, %NULL if no - * passphrase is used. - * - * Returns: 0 on success, -1 on failure - */ -int tls_connection_private_key(void *tls_ctx, struct tls_connection *conn, - const char *private_key, - const char *private_key_passwd); - -/** - * tls_global_private_key - set private key for all TLS connections - * @tls_ctx: TLS context data from tls_init() - * @private_key: File name for client private key in PEM or DER format - * @private_key_passwd: Passphrase for decrypted private key, %NULL if no - * passphrase is used. - * - * Returns: 0 on success, -1 on failure - */ -int tls_global_private_key(void *tls_ctx, const char *private_key, - const char *private_key_passwd); - -/** - * tls_connection_dh - set DH/DSA parameters for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @dh_file: File name for DH/DSA data in PEM format. - * - * Returns: 0 on success, -1 on failure - */ -int tls_connection_dh(void *tls_ctx, struct tls_connection *conn, - const char *dh_file); - -/** - * 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 tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, - struct tls_keys *keys); - -/** - * 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 peer - * @in_len: Input data length - * @out_len: Length of the output buffer. - * - * Returns: pointer to output data, %NULL on failure - * - * Caller is responsible for freeing returned output data. - */ -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len); - -/** - * tls_connection_servr_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 - * @in_len: Input data length - * @out_len: Length of the output buffer. - * - * Returns: pointer to output data, %NULL on failure - * - * Caller is responsible for freeing returned output data. - */ -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len); - -/** - * 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: 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 - */ -int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * 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: 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 - */ -int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * 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); - -/** - * tls_connection_set_master_key - configure master secret for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @key: TLS pre-master-secret - * @key_len: length of @key in bytes - * - * Returns: 0 on success, -1 on failure - */ -int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len); - -/** - * tls_connection_set_anon_dh - configure TLS connection to use anonymous DH - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * - * Returns: 0 on success, -1 on failure - * - * TODO: consider changing this to more generic routine for configuring allowed - * ciphers - */ -int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn); - -/** - * tls_get_cipher - get current cipher name - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * - * Returns: 0 on success, -1 on failure - * - * Get the name of the currently used cipher. - */ -int tls_get_cipher(void *ssl_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 tls_connection_enable_workaround(void *ssl_ctx, - struct tls_connection *conn); - -int tls_connection_client_hello_ext(void *ssl_ctx, struct tls_connection *conn, - int ext_type, const u8 *data, - size_t data_len); - -#endif /* TLS_H */ diff --git a/contrib/wpa_supplicant/tls_none.c b/contrib/wpa_supplicant/tls_none.c deleted file mode 100644 index 2b3cafc10415..000000000000 --- a/contrib/wpa_supplicant/tls_none.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for no TLS case - * Copyright (c) 2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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. - */ - -void * tls_init(void) -{ - return (void *) 1; -} - -void tls_deinit(void *ssl_ctx) -{ -} diff --git a/contrib/wpa_supplicant/tls_openssl.c b/contrib/wpa_supplicant/tls_openssl.c deleted file mode 100644 index 4e6ea539209f..000000000000 --- a/contrib/wpa_supplicant/tls_openssl.c +++ /dev/null @@ -1,879 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/pkcs12.h> - -#include "common.h" -#include "tls.h" - - -struct tls_connection { - SSL *ssl; - BIO *ssl_in, *ssl_out; - char *subject_match; -}; - - -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 (authentication server reported an error)" : - "write (local SSL3 detected an error)", - SSL_alert_type_string_long(ret), - SSL_alert_desc_string_long(ret)); - } 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)); - } -} - - -void * tls_init(void) -{ - SSL_CTX *ssl; - - SSL_load_error_strings(); - SSL_library_init(); - /* 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 - PKCS12_PBE_add(); -#endif /* PKCS12_FUNCS */ - - ssl = SSL_CTX_new(TLSv1_method()); - if (ssl == NULL) - return NULL; - - SSL_CTX_set_info_callback(ssl, ssl_info_cb); - - return ssl; -} - - -void tls_deinit(void *ssl_ctx) -{ - SSL_CTX *ssl = ssl_ctx; - SSL_CTX_free(ssl); - ERR_free_strings(); - EVP_cleanup(); -} - - -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; - - conn = malloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - memset(conn, 0, sizeof(*conn)); - conn->ssl = SSL_new(ssl); - if (conn->ssl == NULL) { - wpa_printf(MSG_INFO, "TLS: Failed to initialize new SSL " - "connection: %s", - ERR_error_string(ERR_get_error(), NULL)); - free(conn); - return NULL; - } - - SSL_set_options(conn->ssl, - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_SINGLE_DH_USE); - - conn->ssl_in = BIO_new(BIO_s_mem()); - if (!conn->ssl_in) { - wpa_printf(MSG_INFO, "SSL: Failed to create a new BIO for " - "ssl_in: %s", - ERR_error_string(ERR_get_error(), NULL)); - SSL_free(conn->ssl); - free(conn); - return NULL; - } - - conn->ssl_out = BIO_new(BIO_s_mem()); - if (!conn->ssl_out) { - wpa_printf(MSG_INFO, "SSL: Failed to create a new BIO for " - "ssl_out: %s", - ERR_error_string(ERR_get_error(), NULL)); - SSL_free(conn->ssl); - BIO_free(conn->ssl_in); - 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); - free(conn->subject_match); - 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_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; - - 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, 256); - - conn = SSL_get_app_data(ssl); - match = conn ? conn->subject_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; - } - } - - return preverify_ok; -} - - -int tls_connection_ca_cert(void *ssl_ctx, struct tls_connection *conn, - const char *ca_cert, const char *subject_match) -{ - if (conn == NULL) - return -1; - - free(conn->subject_match); - conn->subject_match = NULL; - if (subject_match) { - conn->subject_match = strdup(subject_match); - if (conn->subject_match == NULL) - return -1; - } - - if (ca_cert) { - if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) - { - wpa_printf(MSG_WARNING, "TLS: Failed to load root " - "certificates: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } else { - wpa_printf(MSG_DEBUG, "TLS: Trusted root " - "certificate(s) loaded"); - tls_get_errors(ssl_ctx); - } - SSL_set_app_data(conn->ssl, conn); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - } else { - /* No ca_cert configured - do not try to verify server - * certificate */ - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - return 0; -} - - -int tls_global_ca_cert(void *_ssl_ctx, const char *ca_cert) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - if (ca_cert) { - if (SSL_CTX_load_verify_locations(ssl_ctx, ca_cert, NULL) != 1) - { - wpa_printf(MSG_WARNING, "TLS: Failed to load root " - "certificates: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } else { - wpa_printf(MSG_DEBUG, "TLS: Trusted root " - "certificate(s) loaded"); - } - } - - return 0; -} - - -int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, - int verify_peer, const char *subject_match) -{ - if (conn == NULL) - return -1; - - free(conn->subject_match); - conn->subject_match = NULL; - if (subject_match) { - conn->subject_match = strdup(subject_match); - if (conn->subject_match == NULL) - return -1; - } - - if (verify_peer) { - SSL_set_app_data(conn->ssl, conn); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT | - SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); - } else { - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - SSL_set_accept_state(conn->ssl); - - return 0; -} - - -int tls_connection_client_cert(void *ssl_ctx, struct tls_connection *conn, - const char *client_cert) -{ - if (client_cert == NULL) - return 0; - if (conn == NULL) - return -1; - - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_ASN1) != 1 && - SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_PEM) != 1) { - wpa_printf(MSG_INFO, "TLS: Failed to load client " - "certificate: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - return 0; -} - - -int tls_global_client_cert(void *_ssl_ctx, const char *client_cert) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - 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) { - wpa_printf(MSG_INFO, "TLS: Failed to load client " - "certificate: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - return 0; -} - - -static int tls_passwd_cb(char *buf, int size, int rwflag, void *password) -{ - if (password == NULL) { - return 0; - } - strncpy(buf, (char *) password, size); - buf[size - 1] = '\0'; - return strlen(buf); -} - - -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; - EVP_PKEY *pkey; - X509 *cert; - int res = 0; - - f = fopen(private_key, "r"); - if (f == NULL) - return -1; - - p12 = d2i_PKCS12_fp(f, NULL); - if (p12 == NULL) { - wpa_printf(MSG_DEBUG, "TLS: Failed to read PKCS12 file '%s'", - private_key); - fclose(f); - return -1; - } - fclose(f); - - pkey = NULL; - cert = NULL; - if (!PKCS12_parse(p12, passwd, &pkey, &cert, NULL)) { - wpa_printf(MSG_DEBUG, "TLS: Failed to parse PKCS12 file '%s': " - "%s", private_key, - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - wpa_printf(MSG_DEBUG, "TLS: Successfully parsed PKCS12 file '%s'", - private_key); - - if (cert) { - wpa_printf(MSG_DEBUG, "TLS: Got certificate from PKCS12"); - 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); - } - - PKCS12_free(p12); - - return res; -#else /* PKCS12_FUNCS */ - wpa_printf(MSG_INFO, "TLS: PKCS12 support disabled - cannot read " - "p12/pfx files"); - return -1; -#endif /* PKCS12_FUNCS */ -} - - -int tls_connection_private_key(void *_ssl_ctx, struct tls_connection *conn, - const char *private_key, - const char *private_key_passwd) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - char *passwd; - - if (private_key == NULL) - return 0; - if (conn == NULL) - return -1; - - if (private_key_passwd) { - passwd = 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 (SSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_ASN1) != 1 && - SSL_use_PrivateKey_file(conn->ssl, private_key, - SSL_FILETYPE_PEM) != 1 && - tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd)) { - wpa_printf(MSG_INFO, "SSL: Failed to load private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - free(passwd); - ERR_clear_error(); - return -1; - } - ERR_clear_error(); - free(passwd); - SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); - - if (!SSL_check_private_key(conn->ssl)) { - wpa_printf(MSG_INFO, "SSL: Private key failed " - "verification: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - return 0; -} - - -int tls_global_private_key(void *_ssl_ctx, const char *private_key, - const char *private_key_passwd) -{ - SSL_CTX *ssl_ctx = _ssl_ctx; - char *passwd; - - if (private_key == NULL) - return 0; - - if (private_key_passwd) { - passwd = 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 (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 && - tls_read_pkcs12(ssl_ctx, NULL, private_key, passwd)) { - wpa_printf(MSG_INFO, "SSL: Failed to load private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - free(passwd); - ERR_clear_error(); - return -1; - } - free(passwd); - ERR_clear_error(); - SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL); - - if (!SSL_CTX_check_private_key(ssl_ctx)) { - wpa_printf(MSG_INFO, "SSL: Private key failed " - "verification: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - return 0; -} - - -int tls_connection_dh(void *ssl_ctx, 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; - - 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 */ -} - - -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; - - 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; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - int res; - u8 *out_data; - - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - wpa_printf(MSG_INFO, "TLS: Handshake failed - BIO_write: %s", - ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - 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 { - wpa_printf(MSG_INFO, "SSL: SSL_connect: %s", - ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - } - - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = malloc(res == 0 ? 1 : res); - if (out_data == NULL) { - wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " - "handshake output (%d bytes)", res); - BIO_reset(conn->ssl_out); - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res); - if (res < 0) { - wpa_printf(MSG_INFO, "TLS: Handshake failed - BIO_read: %s", - ERR_error_string(ERR_get_error(), NULL)); - BIO_reset(conn->ssl_out); - *out_len = 0; - return NULL; - } - *out_len = res; - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - int res; - u8 *out_data; - char buf[10]; - - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - wpa_printf(MSG_INFO, "TLS: Handshake failed - BIO_write: %s", - ERR_error_string(ERR_get_error(), NULL)); - return NULL; - } - - res = SSL_read(conn->ssl, buf, sizeof(buf)); - if (res >= 0) { - wpa_printf(MSG_DEBUG, "SSL: Unexpected data from SSL_read " - "(res=%d)", res); - } - - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = malloc(res == 0 ? 1 : res); - if (out_data == NULL) { - wpa_printf(MSG_DEBUG, "SSL: Failed to allocate memory for " - "handshake output (%d bytes)", res); - BIO_reset(conn->ssl_out); - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, out_data, res); - if (res < 0) { - wpa_printf(MSG_INFO, "TLS: Handshake failed - BIO_read: %s", - ERR_error_string(ERR_get_error(), NULL)); - BIO_reset(conn->ssl_out); - *out_len = 0; - return NULL; - } - *out_len = res; - return out_data; -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - if (conn == NULL) - return -1; - - BIO_reset(conn->ssl_in); - BIO_reset(conn->ssl_out); - res = SSL_write(conn->ssl, in_data, in_len); - if (res < 0) { - wpa_printf(MSG_INFO, "TLS: Encryption failed - SSL_write: %s", - ERR_error_string(ERR_get_error(), NULL)); - return res; - } - - res = BIO_read(conn->ssl_out, out_data, out_len); - if (res < 0) { - wpa_printf(MSG_INFO, "TLS: Encryption failed - BIO_read: %s", - ERR_error_string(ERR_get_error(), NULL)); - return res; - } - - return res; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - res = BIO_write(conn->ssl_in, in_data, in_len); - if (res < 0) { - wpa_printf(MSG_INFO, "TLS: Decryption failed - BIO_write: %s", - ERR_error_string(ERR_get_error(), NULL)); - return res; - } - BIO_reset(conn->ssl_out); - - res = SSL_read(conn->ssl, out_data, out_len); - if (res < 0) { - wpa_printf(MSG_INFO, "TLS: Decryption failed - SSL_read: %s", - ERR_error_string(ERR_get_error(), NULL)); - return res; - } - - return res; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->ssl->hit : 0; -} - - -int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - SSL *ssl; - - if (conn == NULL || key == NULL || key_len > SSL_MAX_MASTER_KEY_LENGTH) - return -1; - ssl = conn->ssl; - if (ssl == NULL || ssl->session == NULL) - return -1; - - memcpy(ssl->session->master_key, key, key_len); - ssl->session->master_key_length = key_len; - - return 0; -} - - -int tls_connection_set_anon_dh(void *ssl_ctx, struct tls_connection *conn) -{ - if (conn == NULL || conn->ssl == NULL) - return -1; - - if (SSL_set_cipher_list(conn->ssl, "ADH-AES128-SHA") != 1) { - wpa_printf(MSG_INFO, "TLS: Anon DH configuration failed - %s", - ERR_error_string(ERR_get_error(), NULL)); - 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; - - snprintf(buf, buflen, "%s", name); - 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; -} - - -#ifdef EAP_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) -{ - struct tls_ext_hdr { - u16 extensions_len; - u16 extension_type; - u16 extension_len; - } *hdr; - - if (conn == NULL || conn->ssl == NULL) - return -1; - OPENSSL_free(conn->ssl->hello_extension); - if (data == NULL) { - conn->ssl->hello_extension = NULL; - conn->ssl->hello_extension_len = 0; - return 0; - } - if (data_len == 0) { - conn->ssl->hello_extension = OPENSSL_malloc(1); - conn->ssl->hello_extension_len = 0; - return 0; - } - conn->ssl->hello_extension = OPENSSL_malloc(sizeof(*hdr) + data_len); - if (conn->ssl->hello_extension == NULL) - return -1; - - hdr = (struct tls_ext_hdr *) conn->ssl->hello_extension; - hdr->extensions_len = host_to_be16(sizeof(*hdr) - 2 + data_len); - hdr->extension_type = host_to_be16(ext_type); - hdr->extension_len = host_to_be16(data_len); - memcpy(hdr + 1, data, data_len); - conn->ssl->hello_extension_len = sizeof(*hdr) + data_len; - - return 0; -} -#endif /* EAP_FAST */ diff --git a/contrib/wpa_supplicant/todo.txt b/contrib/wpa_supplicant/todo.txt deleted file mode 100644 index 52f334900098..000000000000 --- a/contrib/wpa_supplicant/todo.txt +++ /dev/null @@ -1,54 +0,0 @@ -To do: -- add WPA support to Linux Wireless Extensions -- add support for other drivers -- implement GUI for WPA Supplicant/Xsupplicant/iwconfig/iwlist - (easy to use configuration and network stats, etc.) -- add support for opportunistic PMKSA caching -- hostap: try other roaming modes - NOTE: current mode (manual roaming) does not really roam at all.. - Firmware did not notice the current AP disappearing.. -- EAP-MSCHAPv2: add support for password changing -- add support for WPA with ap_scan=0 (update selected cipher etc. based on - AssocInfo; make sure these match with configuration) -- add driver interface for using wpa_supplicant with wired interface - (or a separate program using EAPOL library) -- wpa_supplicant.conf g+rw so that frontend can change wpa_supplicant.conf - and RECONFIG wpa_supplicant (?) - (or wpa_supplicant changes .conf and ctrl interface gets support for - changing config?) -- optional security separation (build time option): run EAPOL state machines - as non-root (need to add something like socketpair between privileged root - process and non-root handler; send EAPOL packets between processes - and send keying data from non-root -> privileged) - EAPOL-Key processing (WPA & WEP keys) could be in privileged part - at least in the beginning; some parts might end up being moved to - non-root part eventually -- consider closing smart card / PCSC connection when EAP-SIM/EAP-AKA - authentication has been completed (cache scard data based on serial#(?) - and try to optimize next connection if the same card is present for next - auth) -- EAP-AKA: AT_CHECKCODE -- EAP-SIM/AKA: AT_RESULT_IND -- abort auth if EAP method initialization fails and there no other - accepted methods (i.e., do not send NAK for the same method that just - failed) -- on disconnect event, could try to associate with another AP if one is - present in scan results; would need to update scan results periodically.. -- add flag scan_requested and only try to re-associate if this is set when - new scan results are received; this would allow background scans without - triggering re-assoc.. -- if driver/hw is not WPA2 capable, must remove WPA_PROTO_RSN flag from - ssid->proto fields to avoid detecting downgrade attacks when the driver - is not reporting RSN IE, but msg 3/4 has one -- read CA certs from PFX file -- EAP-SIM/AKA: if SIM reader initialization fails, do not start authentication -- Cisco AP and non-zero keyidx for unicast -> map to broadcast - (actually, this already works with driver_ndis; so maybe just change - driver_*.c to do the mapping for drivers that cannot handle non-zero keyidx - for unicast) -- IEEE 802.1X and key update with driver_ndis?? wpa_supplicant did not seem - to see unencrypted EAPOL-Key frames at all.. -- update developer.txt to match with current implementation - (driver API updates, EAP methods) -- driver_wext.c and driver that does not support WPA -> fix plaintext, WEP, and - IEEE 802.1X operation (e.g., use capabilities to report no support for WPA) diff --git a/contrib/wpa_supplicant/version.h b/contrib/wpa_supplicant/version.h deleted file mode 100644 index b030f34b94f9..000000000000 --- a/contrib/wpa_supplicant/version.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -#define VERSION_STR "0.3.9" - -#endif /* VERSION_H */ diff --git a/contrib/wpa_supplicant/wpa.c b/contrib/wpa_supplicant/wpa.c deleted file mode 100644 index c70f55652ce0..000000000000 --- a/contrib/wpa_supplicant/wpa.c +++ /dev/null @@ -1,2457 +0,0 @@ -/* - * WPA Supplicant - * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <sys/time.h> -#ifndef CONFIG_NATIVE_WINDOWS -#include <netinet/in.h> -#endif /* CONFIG_NATIVE_WINDOWS */ -#include <string.h> -#include <time.h> - -#include "common.h" -#include "md5.h" -#include "sha1.h" -#include "rc4.h" -#include "aes_wrap.h" -#include "wpa.h" -#include "driver.h" -#include "eloop.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "l2_packet.h" -#include "eapol_sm.h" -#include "wpa_supplicant_i.h" - -static void rsn_preauth_candidate_process(struct wpa_supplicant *wpa_s); - -#define PMKID_CANDIDATE_PRIO_SCAN 1000 - -/* TODO: make these configurable */ -static const int dot11RSNAConfigPMKLifetime = 43200; -static const int dot11RSNAConfigPMKReauthThreshold = 70; -static const int dot11RSNAConfigSATimeout = 60; -static const int pmksa_cache_max_entries = 32; - -static const int WPA_SELECTOR_LEN = 4; -static const u8 WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -static const u16 WPA_VERSION = 1; -static const u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -static const u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 }; -static const u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 }; -static const u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -static const u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; -static const u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; -static const u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 }; -static const u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; -static const u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; - -/* 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[3]; - u8 oui_type; - u16 version; -} __attribute__ ((packed)); - - -static const int RSN_SELECTOR_LEN = 4; -static const u16 RSN_VERSION = 1; -static const u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 }; -static const u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; -static const u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; -static const u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; -static const u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; -static const u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; - -/* EAPOL-Key Key Data Encapsulation - * GroupKey and STAKey require encryption, otherwise, encryption is optional. - */ -static const u8 RSN_KEY_DATA_GROUPKEY[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_KEY_DATA_STAKEY[] = { 0x00, 0x0f, 0xac, 2 }; -static const u8 RSN_KEY_DATA_MAC_ADDR[] = { 0x00, 0x0f, 0xac, 3 }; -static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 }; - -/* 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) - */ - -struct rsn_ie_hdr { - u8 elem_id; /* WLAN_EID_RSN */ - u8 len; - u16 version; -} __attribute__ ((packed)); - - -static int wpa_selector_to_bitfield(u8 *s) -{ - if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_NONE; - if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP40; - if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_TKIP; - if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_CCMP; - if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int wpa_key_mgmt_to_bitfield(u8 *s) -{ - if (memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) == 0) - return WPA_KEY_MGMT_IEEE8021X; - if (memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN) == - 0) - return WPA_KEY_MGMT_PSK; - if (memcmp(s, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN) == 0) - return WPA_KEY_MGMT_WPA_NONE; - return 0; -} - - -static int rsn_selector_to_bitfield(u8 *s) -{ - if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_NONE; - if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP40; - if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_TKIP; - if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_CCMP; - if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int rsn_key_mgmt_to_bitfield(u8 *s) -{ - if (memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) == 0) - return WPA_KEY_MGMT_IEEE8021X; - if (memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN) == - 0) - return WPA_KEY_MGMT_PSK; - return 0; -} - - -static void rsn_pmkid(u8 *pmk, u8 *aa, u8 *spa, u8 *pmkid) -{ - char *title = "PMK Name"; - const unsigned char *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA1_MAC_LEN]; - - addr[0] = (unsigned char *) title; - addr[1] = aa; - addr[2] = spa; - - hmac_sha1_vector(pmk, PMK_LEN, 3, addr, len, hash); - memcpy(pmkid, hash, PMKID_LEN); -} - - -static void pmksa_cache_set_expiration(struct wpa_supplicant *wpa_s); - - -static void pmksa_cache_free_entry(struct wpa_supplicant *wpa_s, - struct rsn_pmksa_cache *entry) -{ - free(entry); - wpa_s->pmksa_count--; - if (wpa_s->cur_pmksa == entry) { - wpa_printf(MSG_DEBUG, "RSN: removed current PMKSA entry"); - /* TODO: should drop PMK and PTK and trigger new key - * negotiation */ - wpa_s->cur_pmksa = NULL; - } -} - - -static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - time_t now; - - time(&now); - while (wpa_s->pmksa && wpa_s->pmksa->expiration <= now) { - struct rsn_pmksa_cache *entry = wpa_s->pmksa; - wpa_s->pmksa = entry->next; - wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " - MACSTR, MAC2STR(entry->aa)); - pmksa_cache_free_entry(wpa_s, entry); - } - - pmksa_cache_set_expiration(wpa_s); -} - - -static void pmksa_cache_set_expiration(struct wpa_supplicant *wpa_s) -{ - int sec; - eloop_cancel_timeout(pmksa_cache_expire, wpa_s, NULL); - if (wpa_s->pmksa == NULL) - return; - sec = wpa_s->pmksa->expiration - time(NULL); - if (sec < 0) - sec = 0; - eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, wpa_s, NULL); -} - - -static void pmksa_cache_add(struct wpa_supplicant *wpa_s, u8 *pmk, - size_t pmk_len, u8 *aa, u8 *spa) -{ - struct rsn_pmksa_cache *entry, *pos, *prev; - - if (wpa_s->proto != WPA_PROTO_RSN || pmk_len > PMK_LEN) - return; - - entry = malloc(sizeof(*entry)); - if (entry == NULL) - return; - memset(entry, 0, sizeof(*entry)); - memcpy(entry->pmk, pmk, pmk_len); - entry->pmk_len = pmk_len; - rsn_pmkid(pmk, aa, spa, entry->pmkid); - entry->expiration = time(NULL) + dot11RSNAConfigPMKLifetime; - entry->akmp = WPA_KEY_MGMT_IEEE8021X; - memcpy(entry->aa, aa, ETH_ALEN); - - /* Replace an old entry for the same Authenticator (if found) with the - * new entry */ - pos = wpa_s->pmksa; - prev = NULL; - while (pos) { - if (memcmp(aa, pos->aa, ETH_ALEN) == 0) { - if (prev == NULL) - wpa_s->pmksa = pos->next; - else - prev->next = pos->next; - pmksa_cache_free_entry(wpa_s, pos); - break; - } - prev = pos; - pos = pos->next; - } - - if (wpa_s->pmksa_count >= pmksa_cache_max_entries && wpa_s->pmksa) { - /* Remove the oldest entry to make room for the new entry */ - pos = wpa_s->pmksa; - wpa_s->pmksa = pos->next; - wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " - "entry (for " MACSTR ") to make room for new one", - MAC2STR(pos->aa)); - wpa_drv_remove_pmkid(wpa_s, pos->aa, pos->pmkid); - pmksa_cache_free_entry(wpa_s, pos); - } - - /* Add the new entry; order by expiration time */ - pos = wpa_s->pmksa; - prev = NULL; - while (pos) { - if (pos->expiration > entry->expiration) - break; - prev = pos; - pos = pos->next; - } - if (prev == NULL) { - entry->next = wpa_s->pmksa; - wpa_s->pmksa = entry; - } else { - entry->next = prev->next; - prev->next = entry; - } - wpa_s->pmksa_count++; - wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, - MAC2STR(entry->aa)); - wpa_drv_add_pmkid(wpa_s, entry->aa, entry->pmkid); -} - - -void pmksa_cache_free(struct wpa_supplicant *wpa_s) -{ - struct rsn_pmksa_cache *entry, *prev; - - entry = wpa_s->pmksa; - wpa_s->pmksa = NULL; - while (entry) { - prev = entry; - entry = entry->next; - free(prev); - } - pmksa_cache_set_expiration(wpa_s); - wpa_s->cur_pmksa = NULL; -} - - -struct rsn_pmksa_cache * pmksa_cache_get(struct wpa_supplicant *wpa_s, - u8 *aa, u8 *pmkid) -{ - struct rsn_pmksa_cache *entry = wpa_s->pmksa; - while (entry) { - if ((aa == NULL || memcmp(entry->aa, aa, ETH_ALEN) == 0) && - (pmkid == NULL || - memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) - return entry; - entry = entry->next; - } - return NULL; -} - - -int pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len) -{ - int i, j; - char *pos = buf; - struct rsn_pmksa_cache *entry; - time_t now; - - time(&now); - pos += snprintf(pos, buf + len - pos, - "Index / AA / PMKID / expiration (in seconds)\n"); - i = 0; - entry = wpa_s->pmksa; - while (entry) { - i++; - pos += snprintf(pos, buf + len - pos, "%d " MACSTR " ", - i, MAC2STR(entry->aa)); - for (j = 0; j < PMKID_LEN; j++) - pos += snprintf(pos, buf + len - pos, "%02x", - entry->pmkid[j]); - pos += snprintf(pos, buf + len - pos, " %d\n", - (int) (entry->expiration - now)); - entry = entry->next; - } - return pos - buf; -} - - -void pmksa_candidate_free(struct wpa_supplicant *wpa_s) -{ - struct rsn_pmksa_candidate *entry, *prev; - - entry = wpa_s->pmksa_candidates; - wpa_s->pmksa_candidates = NULL; - while (entry) { - prev = entry; - entry = entry->next; - free(prev); - } -} - - -static int wpa_parse_wpa_ie_wpa(struct wpa_supplicant *wpa_s, u8 *wpa_ie, - size_t wpa_ie_len, struct wpa_ie_data *data) -{ - struct wpa_ie_hdr *hdr; - u8 *pos; - int left; - int i, count; - - data->proto = WPA_PROTO_WPA; - data->pairwise_cipher = WPA_CIPHER_TKIP; - data->group_cipher = WPA_CIPHER_TKIP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->capabilities = 0; - data->pmkid = NULL; - data->num_pmkid = 0; - - if (wpa_ie_len == 0) { - /* No WPA IE - fail silently */ - return -1; - } - - if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { - wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", - __func__, (unsigned long) wpa_ie_len); - return -1; - } - - hdr = (struct wpa_ie_hdr *) wpa_ie; - - if (hdr->elem_id != GENERIC_INFO_ELEM || - hdr->len != wpa_ie_len - 2 || - memcmp(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 || - le_to_host16(hdr->version) != WPA_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -1; - } - - pos = (u8 *) (hdr + 1); - left = wpa_ie_len - sizeof(*hdr); - - if (left >= WPA_SELECTOR_LEN) { - data->group_cipher = wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } else if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", - __func__, left); - return -1; - } - - if (left >= 2) { - data->pairwise_cipher = 0; - count = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " - "count %u left %u", __func__, count, left); - return -1; - } - for (i = 0; i < count; i++) { - data->pairwise_cipher |= wpa_selector_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", - __func__); - return -1; - } - - if (left >= 2) { - data->key_mgmt = 0; - count = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) { - wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " - "count %u left %u", __func__, count, left); - return -1; - } - for (i = 0; i < count; i++) { - data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); - pos += WPA_SELECTOR_LEN; - left -= WPA_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", - __func__); - return -1; - } - - if (left >= 2) { - data->capabilities = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes", - __func__, left); - return -1; - } - - return 0; -} - - -static int wpa_parse_wpa_ie_rsn(struct wpa_supplicant *wpa_s, u8 *rsn_ie, - size_t rsn_ie_len, struct wpa_ie_data *data) -{ - struct rsn_ie_hdr *hdr; - u8 *pos; - int left; - int i, count; - - 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; - - 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 = (struct rsn_ie_hdr *) rsn_ie; - - if (hdr->elem_id != RSN_INFO_ELEM || - hdr->len != rsn_ie_len - 2 || - le_to_host16(hdr->version) != RSN_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -1; - } - - pos = (u8 *) (hdr + 1); - left = rsn_ie_len - sizeof(*hdr); - - if (left >= RSN_SELECTOR_LEN) { - data->group_cipher = rsn_selector_to_bitfield(pos); - 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 -1; - } - - if (left >= 2) { - data->pairwise_cipher = 0; - count = pos[0] | (pos[1] << 8); - 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 -1; - } - for (i = 0; i < count; i++) { - data->pairwise_cipher |= rsn_selector_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) { - wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", - __func__); - return -1; - } - - if (left >= 2) { - data->key_mgmt = 0; - count = pos[0] | (pos[1] << 8); - 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 -1; - } - 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 -1; - } - - if (left >= 2) { - data->capabilities = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - } - - if (left >= 2) { - data->num_pmkid = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (left < data->num_pmkid * PMKID_LEN) { - wpa_printf(MSG_DEBUG, "%s: PMKID underflow " - "(num_pmkid=%d left=%d)", - __func__, data->num_pmkid, left); - data->num_pmkid = 0; - } else { - data->pmkid = pos; - pos += data->num_pmkid * PMKID_LEN; - left -= data->num_pmkid * PMKID_LEN; - } - } - - if (left > 0) { - wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", - __func__, left); - } - - return 0; -} - - -int wpa_parse_wpa_ie(struct wpa_supplicant *wpa_s, u8 *wpa_ie, - size_t wpa_ie_len, struct wpa_ie_data *data) -{ - if (wpa_ie_len >= 1 && wpa_ie[0] == RSN_INFO_ELEM) - return wpa_parse_wpa_ie_rsn(wpa_s, wpa_ie, wpa_ie_len, data); - else - return wpa_parse_wpa_ie_wpa(wpa_s, wpa_ie, wpa_ie_len, data); -} - - -static int wpa_gen_wpa_ie_wpa(struct wpa_supplicant *wpa_s, u8 *wpa_ie) -{ - u8 *pos; - struct wpa_ie_hdr *hdr; - - hdr = (struct wpa_ie_hdr *) wpa_ie; - hdr->elem_id = GENERIC_INFO_ELEM; - memcpy(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN); - hdr->version = host_to_le16(WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (wpa_s->group_cipher == WPA_CIPHER_CCMP) { - memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); - } else if (wpa_s->group_cipher == WPA_CIPHER_TKIP) { - memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); - } else if (wpa_s->group_cipher == WPA_CIPHER_WEP104) { - memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN); - } else if (wpa_s->group_cipher == WPA_CIPHER_WEP40) { - memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN); - } else { - wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", - wpa_s->group_cipher); - return -1; - } - pos += WPA_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) { - memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); - } else if (wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) { - memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); - } else if (wpa_s->pairwise_cipher == WPA_CIPHER_NONE) { - memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN); - } else { - wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", - wpa_s->pairwise_cipher); - return -1; - } - pos += WPA_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN); - } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { - memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, - WPA_SELECTOR_LEN); - } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - memcpy(pos, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN); - } else { - wpa_printf(MSG_WARNING, "Invalid key management type (%d).", - wpa_s->key_mgmt); - return -1; - } - pos += WPA_SELECTOR_LEN; - - /* WPA Capabilities; use defaults, so no need to include it */ - - hdr->len = (pos - wpa_ie) - 2; - - return pos - wpa_ie; -} - - -static int wpa_gen_wpa_ie_rsn(struct wpa_supplicant *wpa_s, u8 *rsn_ie) -{ - u8 *pos; - struct rsn_ie_hdr *hdr; - - hdr = (struct rsn_ie_hdr *) rsn_ie; - hdr->elem_id = RSN_INFO_ELEM; - hdr->version = host_to_le16(RSN_VERSION); - pos = (u8 *) (hdr + 1); - - if (wpa_s->group_cipher == WPA_CIPHER_CCMP) { - memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - } else if (wpa_s->group_cipher == WPA_CIPHER_TKIP) { - memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - } else if (wpa_s->group_cipher == WPA_CIPHER_WEP104) { - memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN); - } else if (wpa_s->group_cipher == WPA_CIPHER_WEP40) { - memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN); - } else { - wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", - wpa_s->group_cipher); - return -1; - } - pos += RSN_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) { - memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - } else if (wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) { - memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - } else if (wpa_s->pairwise_cipher == WPA_CIPHER_NONE) { - memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN); - } else { - wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", - wpa_s->pairwise_cipher); - return -1; - } - pos += RSN_SELECTOR_LEN; - - *pos++ = 1; - *pos++ = 0; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN); - } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { - memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, - RSN_SELECTOR_LEN); - } else { - wpa_printf(MSG_WARNING, "Invalid key management type (%d).", - wpa_s->key_mgmt); - return -1; - } - pos += RSN_SELECTOR_LEN; - - /* RSN Capabilities */ - *pos++ = 0; - *pos++ = 0; - - if (wpa_s->cur_pmksa) { - /* PMKID Count (2 octets, little endian) */ - *pos++ = 1; - *pos++ = 0; - /* PMKID */ - memcpy(pos, wpa_s->cur_pmksa->pmkid, PMKID_LEN); - pos += PMKID_LEN; - } - - hdr->len = (pos - rsn_ie) - 2; - - return pos - rsn_ie; -} - - -int wpa_gen_wpa_ie(struct wpa_supplicant *wpa_s, u8 *wpa_ie) -{ - if (wpa_s->proto == WPA_PROTO_RSN) - return wpa_gen_wpa_ie_rsn(wpa_s, wpa_ie); - else - return wpa_gen_wpa_ie_wpa(wpa_s, wpa_ie); -} - - -static void wpa_pmk_to_ptk(u8 *pmk, size_t pmk_len, u8 *addr1, u8 *addr2, - u8 *nonce1, u8 *nonce2, u8 *ptk, size_t ptk_len) -{ - u8 data[2 * ETH_ALEN + 2 * 32]; - - /* PTK = PRF-X(PMK, "Pairwise key expansion", - * Min(AA, SA) || Max(AA, SA) || - * Min(ANonce, SNonce) || Max(ANonce, SNonce)) */ - - if (memcmp(addr1, addr2, ETH_ALEN) < 0) { - memcpy(data, addr1, ETH_ALEN); - memcpy(data + ETH_ALEN, addr2, ETH_ALEN); - } else { - memcpy(data, addr2, ETH_ALEN); - memcpy(data + ETH_ALEN, addr1, ETH_ALEN); - } - - if (memcmp(nonce1, nonce2, 32) < 0) { - memcpy(data + 2 * ETH_ALEN, nonce1, 32); - memcpy(data + 2 * ETH_ALEN + 32, nonce2, 32); - } else { - memcpy(data + 2 * ETH_ALEN, nonce2, 32); - memcpy(data + 2 * ETH_ALEN + 32, nonce1, 32); - } - - sha1_prf(pmk, pmk_len, "Pairwise key expansion", data, sizeof(data), - ptk, ptk_len); - - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); - wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); -} - - -struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *entry; - u8 ssid[MAX_SSID_LEN]; - int ssid_len; - u8 bssid[ETH_ALEN]; - - ssid_len = wpa_drv_get_ssid(wpa_s, ssid); - if (ssid_len < 0) { - wpa_printf(MSG_WARNING, "Could not read SSID from driver."); - return NULL; - } - - if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { - wpa_printf(MSG_WARNING, "Could not read BSSID from driver."); - return NULL; - } - - entry = wpa_s->conf->ssid; - while (entry) { - if (ssid_len == entry->ssid_len && - memcmp(ssid, entry->ssid, ssid_len) == 0 && - (!entry->bssid_set || - memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) - return entry; - entry = entry->next; - } - - return NULL; -} - - -static void wpa_eapol_key_mic(u8 *key, int ver, u8 *buf, size_t len, u8 *mic) -{ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - hmac_md5(key, 16, buf, len, mic); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - u8 hash[SHA1_MAC_LEN]; - hmac_sha1(key, 16, buf, len, hash); - memcpy(mic, hash, MD5_MAC_LEN); - } -} - - -void wpa_supplicant_key_request(struct wpa_supplicant *wpa_s, - int error, int pairwise) -{ - int rlen; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *reply; - unsigned char *rbuf; - struct l2_ethhdr *ethhdr; - int key_info, ver; - u8 bssid[ETH_ALEN]; - - if (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP) - ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; - else - ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; - - if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { - wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key " - "request"); - return; - } - - rlen = sizeof(*ethhdr) + sizeof(*hdr) + sizeof(*reply); - rbuf = malloc(rlen); - if (rbuf == NULL) - return; - - memset(rbuf, 0, rlen); - ethhdr = (struct l2_ethhdr *) rbuf; - memcpy(ethhdr->h_dest, bssid, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_EAPOL); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = htons(sizeof(*reply)); - - reply = (struct wpa_eapol_key *) (hdr + 1); - reply->type = wpa_s->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - key_info = WPA_KEY_INFO_REQUEST | ver; - if (wpa_s->ptk_set) - key_info |= WPA_KEY_INFO_MIC; - if (error) - key_info |= WPA_KEY_INFO_ERROR; - if (pairwise) - key_info |= WPA_KEY_INFO_KEY_TYPE; - reply->key_info = host_to_be16(key_info); - reply->key_length = 0; - memcpy(reply->replay_counter, wpa_s->request_counter, - WPA_REPLAY_COUNTER_LEN); - inc_byte_array(wpa_s->request_counter, WPA_REPLAY_COUNTER_LEN); - - reply->key_data_length = host_to_be16(0); - - if (key_info & WPA_KEY_INFO_MIC) { - wpa_eapol_key_mic(wpa_s->ptk.mic_key, ver, (u8 *) hdr, - rlen - sizeof(*ethhdr), reply->key_mic); - } - - wpa_printf(MSG_INFO, "WPA: Sending EAPOL-Key Request (error=%d " - "pairwise=%d ptk_set=%d len=%d)", - error, pairwise, wpa_s->ptk_set, rlen); - wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key Request", rbuf, rlen); - l2_packet_send(wpa_s->l2, rbuf, rlen); - eapol_sm_notify_tx_eapol_key(wpa_s->eapol); - free(rbuf); -} - - -static void wpa_supplicant_process_1_of_4(struct wpa_supplicant *wpa_s, - unsigned char *src_addr, - struct wpa_eapol_key *key, int ver) -{ - int rlen; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *reply; - unsigned char *rbuf; - struct l2_ethhdr *ethhdr; - struct wpa_ssid *ssid; - struct wpa_ptk *ptk; - u8 buf[8], wpa_ie_buf[80], *wpa_ie, *pmkid = NULL; - int wpa_ie_len; - int abort_cached = 0; - - wpa_s->wpa_state = WPA_4WAY_HANDSHAKE; - wpa_printf(MSG_DEBUG, "WPA: RX message 1 of 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - ssid = wpa_supplicant_get_ssid(wpa_s); - if (ssid == NULL) { - wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of " - "4)."); - return; - } - - if (wpa_s->proto == WPA_PROTO_RSN) { - /* RSN: msg 1/4 should contain PMKID for the selected PMK */ - u8 *pos = (u8 *) (key + 1); - u8 *end = pos + be_to_host16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", - pos, be_to_host16(key->key_data_length)); - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "RSN: key data " - "underflow (ie=%d len=%d)", - pos[0], pos[1]); - break; - } - if (pos[0] == GENERIC_INFO_ELEM && - pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && - memcmp(pos + 2, RSN_KEY_DATA_PMKID, - RSN_SELECTOR_LEN) == 0) { - pmkid = pos + 2 + RSN_SELECTOR_LEN; - wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " - "Authenticator", pmkid, PMKID_LEN); - break; - } else if (pos[0] == GENERIC_INFO_ELEM && - pos[1] == 0) - break; - pos += 2 + pos[1]; - } - } - - if (wpa_s->assoc_wpa_ie) { - /* The driver reported a WPA IE that may be different from the - * one that the Supplicant would use. Message 2/4 has to use - * the exact copy of the WPA IE from the Association Request, - * so use the value reported by the driver. */ - wpa_ie = wpa_s->assoc_wpa_ie; - wpa_ie_len = wpa_s->assoc_wpa_ie_len; - } else { - wpa_ie = wpa_ie_buf; - wpa_ie_len = wpa_gen_wpa_ie(wpa_s, wpa_ie); - if (wpa_ie_len < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to generate " - "WPA IE (for msg 2 of 4)."); - return; - } - wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", - wpa_ie, wpa_ie_len); - } - - rlen = sizeof(*ethhdr) + sizeof(*hdr) + sizeof(*reply) + wpa_ie_len; - rbuf = malloc(rlen); - if (rbuf == NULL) - return; - - memset(rbuf, 0, rlen); - ethhdr = (struct l2_ethhdr *) rbuf; - memcpy(ethhdr->h_dest, src_addr, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_EAPOL); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = htons(sizeof(*reply) + wpa_ie_len); - - reply = (struct wpa_eapol_key *) (hdr + 1); - reply->type = wpa_s->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - reply->key_info = host_to_be16(ver | WPA_KEY_INFO_KEY_TYPE | - WPA_KEY_INFO_MIC); - reply->key_length = key->key_length; - memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - reply->key_data_length = host_to_be16(wpa_ie_len); - memcpy(reply + 1, wpa_ie, wpa_ie_len); - - if (wpa_s->renew_snonce) { - if (hostapd_get_rand(wpa_s->snonce, WPA_NONCE_LEN)) { - wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to get " - "random data for SNonce"); - free(rbuf); - return; - } - wpa_s->renew_snonce = 0; - wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", - wpa_s->snonce, WPA_NONCE_LEN); - } - memcpy(reply->key_nonce, wpa_s->snonce, WPA_NONCE_LEN); - ptk = &wpa_s->tptk; - memcpy(wpa_s->anonce, key->key_nonce, WPA_NONCE_LEN); - if (pmkid && !wpa_s->cur_pmksa) { - /* When using drivers that generate RSN IE, wpa_supplicant may - * not have enough time to get the association information - * event before receiving this 1/4 message, so try to find a - * matching PMKSA cache entry here. */ - wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, src_addr, pmkid); - if (wpa_s->cur_pmksa) { - wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from " - "PMKSA cache"); - } else { - wpa_printf(MSG_DEBUG, "RSN: no matching PMKID found"); - abort_cached = 1; - } - } - - if (pmkid && wpa_s->cur_pmksa && - memcmp(pmkid, wpa_s->cur_pmksa->pmkid, PMKID_LEN) == 0) { - wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN); - memcpy(wpa_s->pmk, wpa_s->cur_pmksa->pmk, PMK_LEN); - wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache", - wpa_s->pmk, PMK_LEN); - eapol_sm_notify_cached(wpa_s->eapol); - } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X && wpa_s->eapol) { - int res, pmk_len; - pmk_len = PMK_LEN; - res = eapol_sm_get_key(wpa_s->eapol, wpa_s->pmk, PMK_LEN); -#ifdef EAP_LEAP - if (res) { - res = eapol_sm_get_key(wpa_s->eapol, wpa_s->pmk, 16); - pmk_len = 16; - } -#endif /* EAP_LEAP */ - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " - "machines", wpa_s->pmk, pmk_len); - wpa_s->pmk_len = pmk_len; - pmksa_cache_add(wpa_s, wpa_s->pmk, pmk_len, src_addr, - wpa_s->own_addr); - if (!wpa_s->cur_pmksa && pmkid && - pmksa_cache_get(wpa_s, src_addr, pmkid)) { - wpa_printf(MSG_DEBUG, "RSN: the new PMK " - "matches with the PMKID"); - abort_cached = 0; - } - } else { - wpa_msg(wpa_s, MSG_WARNING, - "WPA: Failed to get master session key from " - "EAPOL state machines"); - wpa_msg(wpa_s, MSG_WARNING, - "WPA: Key handshake aborted"); - if (wpa_s->cur_pmksa) { - wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA " - "caching attempt"); - wpa_s->cur_pmksa = NULL; - abort_cached = 1; - } else { - free(rbuf); - return; - } - } -#ifdef CONFIG_XSUPPLICANT_IFACE - } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X && - !wpa_s->ext_pmk_received) { - wpa_printf(MSG_INFO, "WPA: Master session has not yet " - "been received from the external IEEE " - "802.1X Supplicant - ignoring WPA " - "EAPOL-Key frame"); - free(rbuf); - return; -#endif /* CONFIG_XSUPPLICANT_IFACE */ - } - - if (abort_cached && wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - /* Send EAPOL-Start to trigger full EAP authentication. */ - wpa_printf(MSG_DEBUG, "RSN: no PMKSA entry found - trigger " - "full EAP authenication"); - wpa_eapol_send(wpa_s, IEEE802_1X_TYPE_EAPOL_START, - (u8 *) "", 0); - free(rbuf); - return; - } - - wpa_pmk_to_ptk(wpa_s->pmk, wpa_s->pmk_len, wpa_s->own_addr, src_addr, - wpa_s->snonce, key->key_nonce, - (u8 *) ptk, sizeof(*ptk)); - /* Supplicant: swap tx/rx Mic keys */ - memcpy(buf, ptk->u.auth.tx_mic_key, 8); - memcpy(ptk->u.auth.tx_mic_key, ptk->u.auth.rx_mic_key, 8); - memcpy(ptk->u.auth.rx_mic_key, buf, 8); - wpa_s->tptk_set = 1; - wpa_eapol_key_mic(wpa_s->tptk.mic_key, ver, (u8 *) hdr, - rlen - sizeof(*ethhdr), reply->key_mic); - wpa_hexdump(MSG_DEBUG, "WPA: EAPOL-Key MIC", reply->key_mic, 16); - - wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); - wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key 2/4", rbuf, rlen); - l2_packet_send(wpa_s->l2, rbuf, rlen); - eapol_sm_notify_tx_eapol_key(wpa_s->eapol); - free(rbuf); -} - - -static void wpa_supplicant_key_neg_complete(struct wpa_supplicant *wpa_s, - u8 *addr, int secure) -{ - wpa_msg(wpa_s, MSG_INFO, "WPA: Key negotiation completed with " - MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), - wpa_cipher_txt(wpa_s->pairwise_cipher), - wpa_cipher_txt(wpa_s->group_cipher)); - eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); - wpa_supplicant_cancel_auth_timeout(wpa_s); - wpa_s->wpa_state = WPA_COMPLETED; - - if (secure) { - /* MLME.SETPROTECTION.request(TA, Tx_Rx) */ - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); - rsn_preauth_candidate_process(wpa_s); - } -} - - -static int wpa_supplicant_install_ptk(struct wpa_supplicant *wpa_s, - unsigned char *src_addr, - struct wpa_eapol_key *key) -{ - int alg, keylen, rsclen; - u8 *key_rsc; - u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - wpa_printf(MSG_DEBUG, "WPA: Installing PTK to the driver."); - - switch (wpa_s->pairwise_cipher) { - case WPA_CIPHER_CCMP: - alg = WPA_ALG_CCMP; - keylen = 16; - rsclen = 6; - break; - case WPA_CIPHER_TKIP: - alg = WPA_ALG_TKIP; - keylen = 32; - rsclen = 6; - break; - case WPA_CIPHER_NONE: - wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: " - "NONE - do not use pairwise keys"); - return 0; - default: - wpa_printf(MSG_WARNING, "WPA: Unsupported pairwise cipher %d", - wpa_s->pairwise_cipher); - return -1; - } - - if (wpa_s->proto == WPA_PROTO_RSN) { - key_rsc = null_rsc; - } else { - key_rsc = key->key_rsc; - wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); - } - - wpa_s->keys_cleared = 0; - if (wpa_drv_set_key(wpa_s, alg, src_addr, 0, 1, key_rsc, rsclen, - (u8 *) &wpa_s->ptk.tk1, keylen) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set PTK to the " - "driver."); - return -1; - } - return 0; -} - - -static int wpa_supplicant_check_group_cipher(struct wpa_supplicant *wpa_s, - int keylen, int maxkeylen, - int *key_rsc_len, int *alg) -{ - switch (wpa_s->group_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16 || maxkeylen < 16) { - wpa_printf(MSG_WARNING, "WPA: Unsupported CCMP Group " - "Cipher key length %d (%d).", - keylen, maxkeylen); - return -1; - } - *key_rsc_len = 6; - *alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - if (keylen != 32 || maxkeylen < 32) { - wpa_printf(MSG_WARNING, "WPA: Unsupported TKIP Group " - "Cipher key length %d (%d).", - keylen, maxkeylen); - return -1; - } - *key_rsc_len = 6; - *alg = WPA_ALG_TKIP; - break; - case WPA_CIPHER_WEP104: - if (keylen != 13 || maxkeylen < 13) { - wpa_printf(MSG_WARNING, "WPA: Unsupported WEP104 Group" - " Cipher key length %d (%d).", - keylen, maxkeylen); - return -1; - } - *key_rsc_len = 0; - *alg = WPA_ALG_WEP; - break; - case WPA_CIPHER_WEP40: - if (keylen != 5 || maxkeylen < 5) { - wpa_printf(MSG_WARNING, "WPA: Unsupported WEP40 Group " - "Cipher key length %d (%d).", - keylen, maxkeylen); - return -1; - } - *key_rsc_len = 0; - *alg = WPA_ALG_WEP; - break; - default: - wpa_printf(MSG_WARNING, "WPA: Unsupport Group Cipher %d", - wpa_s->group_cipher); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_install_gtk(struct wpa_supplicant *wpa_s, - struct wpa_eapol_key *key, int alg, - u8 *gtk, int gtk_len, int keyidx, - int key_rsc_len, int tx) -{ - wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gtk, gtk_len); - wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " - "(keyidx=%d tx=%d).", keyidx, tx); - wpa_hexdump(MSG_DEBUG, "WPA: RSC", key->key_rsc, key_rsc_len); - if (wpa_s->group_cipher == WPA_CIPHER_TKIP) { - /* Swap Tx/Rx keys for Michael MIC */ - u8 tmpbuf[8]; - memcpy(tmpbuf, gtk + 16, 8); - memcpy(gtk + 16, gtk + 24, 8); - memcpy(gtk + 24, tmpbuf, 8); - } - wpa_s->keys_cleared = 0; - if (wpa_s->pairwise_cipher == WPA_CIPHER_NONE) { - if (wpa_drv_set_key(wpa_s, alg, - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, 1, key->key_rsc, key_rsc_len, - gtk, gtk_len) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set " - "GTK to the driver (Group only)."); - return -1; - } - } else if (wpa_drv_set_key(wpa_s, alg, - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, tx, key->key_rsc, key_rsc_len, - gtk, gtk_len) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to " - "the driver."); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_pairwise_gtk(struct wpa_supplicant *wpa_s, - unsigned char *src_addr, - struct wpa_eapol_key *key, - u8 *gtk, int gtk_len, int key_info) -{ - int keyidx, tx, key_rsc_len = 0, alg; - - wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", - gtk, gtk_len); - - keyidx = gtk[0] & 0x3; - tx = !!(gtk[0] & BIT(2)); - if (tx && wpa_s->pairwise_cipher != WPA_CIPHER_NONE) { - /* Ignore Tx bit in GTK IE if a pairwise key is used. One AP - * seemed to set this bit (incorrectly, since Tx is only when - * doing Group Key only APs) and without this workaround, the - * data connection does not work because wpa_supplicant - * configured non-zero keyidx to be used for unicast. */ - wpa_printf(MSG_INFO, "RSN: Tx bit set for GTK IE, but " - "pairwise keys are used - ignore Tx bit"); - tx = 0; - } - gtk += 2; - gtk_len -= 2; - - if (wpa_supplicant_check_group_cipher(wpa_s, gtk_len, gtk_len, - &key_rsc_len, &alg)) { - return -1; - } - - if (wpa_supplicant_install_gtk(wpa_s, key, alg, gtk, gtk_len, keyidx, - key_rsc_len, tx)) { - return -1; - } - - wpa_supplicant_key_neg_complete(wpa_s, src_addr, - key_info & WPA_KEY_INFO_SECURE); - return 0; -} - - -static void wpa_report_ie_mismatch(struct wpa_supplicant *wpa_s, - const char *reason, const u8 *src_addr, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsn_ie, size_t rsn_ie_len) -{ - wpa_msg(wpa_s, MSG_WARNING, "WPA: %s (src=" MACSTR ")", - reason, MAC2STR(src_addr)); - - if (wpa_s->ap_wpa_ie) { - wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", - wpa_s->ap_wpa_ie, wpa_s->ap_wpa_ie_len); - } - if (wpa_ie) { - if (!wpa_s->ap_wpa_ie) { - wpa_printf(MSG_INFO, "WPA: No WPA IE in " - "Beacon/ProbeResp"); - } - wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", - wpa_ie, wpa_ie_len); - } - - if (wpa_s->ap_rsn_ie) { - wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", - wpa_s->ap_rsn_ie, wpa_s->ap_rsn_ie_len); - } - if (rsn_ie) { - if (!wpa_s->ap_rsn_ie) { - wpa_printf(MSG_INFO, "WPA: No RSN IE in " - "Beacon/ProbeResp"); - } - wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", - rsn_ie, rsn_ie_len); - } - - wpa_supplicant_disassociate(wpa_s, REASON_IE_IN_4WAY_DIFFERS); - wpa_supplicant_req_scan(wpa_s, 0, 0); -} - - -static void wpa_supplicant_process_3_of_4(struct wpa_supplicant *wpa_s, - unsigned char *src_addr, - struct wpa_eapol_key *key, - int extra_len, int ver) -{ - int rlen; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *reply; - unsigned char *rbuf; - struct l2_ethhdr *ethhdr; - int key_info, wpa_ie_len = 0, rsn_ie_len = 0, keylen, gtk_len = 0; - u8 *wpa_ie = NULL, *rsn_ie = NULL, *gtk = NULL; - u8 *pos, *end; - u16 len; - struct wpa_ssid *ssid = wpa_s->current_ssid; - - wpa_s->wpa_state = WPA_4WAY_HANDSHAKE; - wpa_printf(MSG_DEBUG, "WPA: RX message 3 of 4-Way Handshake from " - MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - key_info = be_to_host16(key->key_info); - - pos = (u8 *) (key + 1); - len = be_to_host16(key->key_data_length); - end = pos + len; - wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "WPA: key data underflow (ie=%d " - "len=%d)", pos[0], pos[1]); - break; - } - if (*pos == RSN_INFO_ELEM) { - rsn_ie = pos; - rsn_ie_len = pos[1] + 2; - } else if (*pos == GENERIC_INFO_ELEM && pos[1] >= 6 && - memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 - && pos[2 + WPA_SELECTOR_LEN] == 1 && - pos[2 + WPA_SELECTOR_LEN + 1] == 0) { - wpa_ie = pos; - wpa_ie_len = pos[1] + 2; - } else if (pos[0] == GENERIC_INFO_ELEM && - pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, - RSN_SELECTOR_LEN) == 0) { - if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_WARNING, "WPA: GTK IE in " - "unencrypted key data"); - return; - } - gtk = pos + 2 + RSN_SELECTOR_LEN; - gtk_len = pos[1] - RSN_SELECTOR_LEN; - } else if (pos[0] == GENERIC_INFO_ELEM && pos[1] == 0) - break; - - pos += 2 + pos[1]; - } - - if (wpa_s->ap_wpa_ie == NULL && wpa_s->ap_rsn_ie == NULL) { - wpa_printf(MSG_DEBUG, "WPA: No WPA/RSN IE for this AP known. " - "Trying to get from scan results"); - if (wpa_supplicant_get_beacon_ie(wpa_s) < 0) { - wpa_printf(MSG_WARNING, "WPA: Could not find AP from " - "the scan results"); - } else { - wpa_printf(MSG_DEBUG, "WPA: Found the current AP from " - "updated scan results"); - } - } - - if ((wpa_ie && wpa_s->ap_wpa_ie && - (wpa_ie_len != wpa_s->ap_wpa_ie_len || - memcmp(wpa_ie, wpa_s->ap_wpa_ie, wpa_ie_len) != 0)) || - (rsn_ie && wpa_s->ap_rsn_ie && - (rsn_ie_len != wpa_s->ap_rsn_ie_len || - memcmp(rsn_ie, wpa_s->ap_rsn_ie, rsn_ie_len) != 0))) { - wpa_report_ie_mismatch(wpa_s, "IE in 3/4 msg does not match " - "with IE in Beacon/ProbeResp", - src_addr, wpa_ie, wpa_ie_len, - rsn_ie, rsn_ie_len); - return; - } - - if (wpa_s->proto == WPA_PROTO_WPA && - rsn_ie && wpa_s->ap_rsn_ie == NULL && - ssid && (ssid->proto & WPA_PROTO_RSN)) { - wpa_report_ie_mismatch(wpa_s, "Possible downgrade attack " - "detected - RSN was enabled and RSN IE " - "was in msg 3/4, but not in " - "Beacon/ProbeResp", - src_addr, wpa_ie, wpa_ie_len, - rsn_ie, rsn_ie_len); - return; - } - - if (memcmp(wpa_s->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_printf(MSG_WARNING, "WPA: ANonce from message 1 of 4-Way " - "Handshake differs from 3 of 4-Way Handshake - drop" - " packet (src=" MACSTR ")", MAC2STR(src_addr)); - return; - } - - keylen = be_to_host16(key->key_length); - switch (wpa_s->pairwise_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16) { - wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length " - "%d (src=" MACSTR ")", - keylen, MAC2STR(src_addr)); - return; - } - break; - case WPA_CIPHER_TKIP: - if (keylen != 32) { - wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length " - "%d (src=" MACSTR ")", - keylen, MAC2STR(src_addr)); - return; - } - break; - } - - rlen = sizeof(*ethhdr) + sizeof(*hdr) + sizeof(*reply); - rbuf = malloc(rlen); - if (rbuf == NULL) - return; - - memset(rbuf, 0, rlen); - ethhdr = (struct l2_ethhdr *) rbuf; - memcpy(ethhdr->h_dest, src_addr, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_EAPOL); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = htons(sizeof(*reply)); - - reply = (struct wpa_eapol_key *) (hdr + 1); - reply->type = wpa_s->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - reply->key_info = host_to_be16(ver | WPA_KEY_INFO_KEY_TYPE | - WPA_KEY_INFO_MIC | - (key_info & WPA_KEY_INFO_SECURE)); - reply->key_length = key->key_length; - memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - reply->key_data_length = host_to_be16(0); - - memcpy(reply->key_nonce, wpa_s->snonce, WPA_NONCE_LEN); - wpa_eapol_key_mic(wpa_s->ptk.mic_key, ver, (u8 *) hdr, - rlen - sizeof(*ethhdr), reply->key_mic); - - wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); - wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key 4/4", rbuf, rlen); - l2_packet_send(wpa_s->l2, rbuf, rlen); - eapol_sm_notify_tx_eapol_key(wpa_s->eapol); - free(rbuf); - - /* SNonce was successfully used in msg 3/4, so mark it to be renewed - * for the next 4-Way Handshake. If msg 3 is received again, the old - * SNonce will still be used to avoid changing PTK. */ - wpa_s->renew_snonce = 1; - - if (key_info & WPA_KEY_INFO_INSTALL) { - wpa_supplicant_install_ptk(wpa_s, src_addr, key); - } - - if (key_info & WPA_KEY_INFO_SECURE) { - /* MLME.SETPROTECTION.request(TA, Tx_Rx) */ - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - } - wpa_s->wpa_state = WPA_GROUP_HANDSHAKE; - - if (gtk) { - wpa_supplicant_pairwise_gtk(wpa_s, src_addr, key, - gtk, gtk_len, key_info); - } -} - - -static void wpa_supplicant_process_1_of_2(struct wpa_supplicant *wpa_s, - unsigned char *src_addr, - struct wpa_eapol_key *key, - int extra_len, int ver) -{ - int rlen; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *reply; - unsigned char *rbuf; - struct l2_ethhdr *ethhdr; - int key_info, keylen, keydatalen, maxkeylen, keyidx, key_rsc_len = 0; - int alg, tx, rekey; - u8 ek[32], gtk[32]; - u8 *gtk_ie = NULL; - size_t gtk_ie_len = 0; - - rekey = wpa_s->wpa_state == WPA_COMPLETED; - wpa_s->wpa_state = WPA_GROUP_HANDSHAKE; - wpa_printf(MSG_DEBUG, "WPA: RX message 1 of Group Key Handshake from " - MACSTR " (ver=%d)", MAC2STR(src_addr), ver); - - key_info = be_to_host16(key->key_info); - keydatalen = be_to_host16(key->key_data_length); - - if (wpa_s->proto == WPA_PROTO_RSN) { - u8 *pos = (u8 *) (key + 1); - u8 *end = pos + keydatalen; - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "RSN: key data " - "underflow (ie=%d len=%d)", - pos[0], pos[1]); - break; - } - if (pos[0] == GENERIC_INFO_ELEM && - pos + 1 + RSN_SELECTOR_LEN < end && - pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, - RSN_SELECTOR_LEN) == 0) { - if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_WARNING, "WPA: GTK IE " - "in unencrypted key data"); - return; - } - gtk_ie = pos + 2 + RSN_SELECTOR_LEN; - gtk_ie_len = pos[1] - RSN_SELECTOR_LEN; - break; - } else if (pos[0] == GENERIC_INFO_ELEM && - pos[1] == 0) - break; - - pos += 2 + pos[1]; - } - - if (gtk_ie == NULL) { - wpa_printf(MSG_INFO, "WPA: No GTK IE in Group Key " - "message 1/2"); - return; - } - maxkeylen = keylen = gtk_ie_len - 2; - } else { - keylen = be_to_host16(key->key_length); - maxkeylen = keydatalen; - if (keydatalen > extra_len) { - wpa_printf(MSG_INFO, "WPA: Truncated EAPOL-Key packet:" - " key_data_length=%d > extra_len=%d", - keydatalen, extra_len); - return; - } - if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) - maxkeylen -= 8; - } - - if (wpa_supplicant_check_group_cipher(wpa_s, keylen, maxkeylen, - &key_rsc_len, &alg)) { - return; - } - - if (wpa_s->proto == WPA_PROTO_RSN) { - wpa_hexdump(MSG_DEBUG, - "RSN: received GTK in group key handshake", - gtk_ie, gtk_ie_len); - keyidx = gtk_ie[0] & 0x3; - tx = !!(gtk_ie[0] & BIT(2)); - if (gtk_ie_len - 2 > sizeof(gtk)) { - wpa_printf(MSG_INFO, "RSN: Too long GTK in GTK IE " - "(len=%lu)", - (unsigned long) gtk_ie_len - 2); - return; - } - memcpy(gtk, gtk_ie + 2, gtk_ie_len - 2); - } else { - keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> - WPA_KEY_INFO_KEY_INDEX_SHIFT; - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - memcpy(ek, key->key_iv, 16); - memcpy(ek + 16, wpa_s->ptk.encr_key, 16); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen); - memcpy(gtk, key + 1, keylen); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (keydatalen % 8) { - wpa_printf(MSG_WARNING, "WPA: Unsupported " - "AES-WRAP len %d", keydatalen); - return; - } - if (aes_unwrap(wpa_s->ptk.encr_key, maxkeylen / 8, - (u8 *) (key + 1), gtk)) { - wpa_printf(MSG_WARNING, "WPA: AES unwrap " - "failed - could not decrypt GTK"); - return; - } - } - tx = !!(key_info & WPA_KEY_INFO_TXRX); - } - - if (tx && wpa_s->pairwise_cipher != WPA_CIPHER_NONE) { - /* Ignore Tx bit in Group Key message if a pairwise key - * is used. Some APs seem to setting this bit - * (incorrectly, since Tx is only when doing Group Key - * only APs) and without this workaround, the data - * connection does not work because wpa_supplicant - * configured non-zero keyidx to be used for unicast. - */ - wpa_printf(MSG_INFO, "WPA: Tx bit set for GTK, but " - "pairwise keys are used - ignore Tx bit"); - tx = 0; - } - - wpa_supplicant_install_gtk(wpa_s, key, alg, gtk, keylen, keyidx, - key_rsc_len, tx); - - rlen = sizeof(*ethhdr) + sizeof(*hdr) + sizeof(*reply); - rbuf = malloc(rlen); - if (rbuf == NULL) - return; - - memset(rbuf, 0, rlen); - ethhdr = (struct l2_ethhdr *) rbuf; - memcpy(ethhdr->h_dest, src_addr, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_EAPOL); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = htons(sizeof(*reply)); - - reply = (struct wpa_eapol_key *) (hdr + 1); - reply->type = wpa_s->proto == WPA_PROTO_RSN ? - EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; - reply->key_info = - host_to_be16(ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE | - (key_info & WPA_KEY_INFO_KEY_INDEX_MASK)); - reply->key_length = key->key_length; - memcpy(reply->replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - - reply->key_data_length = host_to_be16(0); - - wpa_eapol_key_mic(wpa_s->ptk.mic_key, ver, (u8 *) hdr, - rlen - sizeof(*ethhdr), reply->key_mic); - - wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); - wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key 2/2", rbuf, rlen); - l2_packet_send(wpa_s->l2, rbuf, rlen); - eapol_sm_notify_tx_eapol_key(wpa_s->eapol); - free(rbuf); - - if (rekey) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Group rekeying completed with " - MACSTR " [GTK=%s]", MAC2STR(src_addr), - wpa_cipher_txt(wpa_s->group_cipher)); - wpa_s->wpa_state = WPA_COMPLETED; - } else { - wpa_supplicant_key_neg_complete(wpa_s, src_addr, - key_info & - WPA_KEY_INFO_SECURE); - } -} - - -static int wpa_supplicant_verify_eapol_key_mic(struct wpa_supplicant *wpa_s, - struct wpa_eapol_key *key, - int ver, u8 *buf, size_t len) -{ - u8 mic[16]; - int ok = 0; - - memcpy(mic, key->key_mic, 16); - if (wpa_s->tptk_set) { - memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(wpa_s->tptk.mic_key, ver, buf, len, - key->key_mic); - if (memcmp(mic, key->key_mic, 16) != 0) { - wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " - "when using TPTK - ignoring TPTK"); - } else { - ok = 1; - wpa_s->tptk_set = 0; - wpa_s->ptk_set = 1; - memcpy(&wpa_s->ptk, &wpa_s->tptk, sizeof(wpa_s->ptk)); - } - } - - if (!ok && wpa_s->ptk_set) { - memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(wpa_s->ptk.mic_key, ver, buf, len, - key->key_mic); - if (memcmp(mic, key->key_mic, 16) != 0) { - wpa_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - ok = 1; - } - - if (!ok) { - wpa_printf(MSG_WARNING, "WPA: Could not verify EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - - memcpy(wpa_s->rx_replay_counter, key->replay_counter, - WPA_REPLAY_COUNTER_LEN); - wpa_s->rx_replay_counter_set = 1; - return 0; -} - - -/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ -static int wpa_supplicant_decrypt_key_data(struct wpa_supplicant *wpa_s, - struct wpa_eapol_key *key, int ver) -{ - int keydatalen = be_to_host16(key->key_data_length); - - wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", - (u8 *) (key + 1), keydatalen); - if (!wpa_s->ptk_set) { - wpa_printf(MSG_WARNING, "WPA: PTK not available, " - "cannot decrypt EAPOL-Key key data."); - return -1; - } - - /* Decrypt key data here so that this operation does not need - * to be implemented separately for each message type. */ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - u8 ek[32]; - memcpy(ek, key->key_iv, 16); - memcpy(ek + 16, wpa_s->ptk.encr_key, 16); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - u8 *buf; - if (keydatalen % 8) { - wpa_printf(MSG_WARNING, "WPA: Unsupported " - "AES-WRAP len %d", keydatalen); - return -1; - } - keydatalen -= 8; /* AES-WRAP adds 8 bytes */ - buf = malloc(keydatalen); - if (buf == NULL) { - wpa_printf(MSG_WARNING, "WPA: No memory for " - "AES-UNWRAP buffer"); - return -1; - } - if (aes_unwrap(wpa_s->ptk.encr_key, keydatalen / 8, - (u8 *) (key + 1), buf)) { - free(buf); - wpa_printf(MSG_WARNING, "WPA: AES unwrap failed - " - "could not decrypt EAPOL-Key key data"); - return -1; - } - memcpy(key + 1, buf, keydatalen); - free(buf); - key->key_data_length = host_to_be16(keydatalen); - } - wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", - (u8 *) (key + 1), keydatalen); - return 0; -} - - -static void wpa_sm_rx_eapol(struct wpa_supplicant *wpa_s, - unsigned char *src_addr, unsigned char *buf, - size_t len) -{ - size_t plen, data_len, extra_len; - struct ieee802_1x_hdr *hdr; - struct wpa_eapol_key *key; - int key_info, ver; - - hdr = (struct ieee802_1x_hdr *) buf; - key = (struct wpa_eapol_key *) (hdr + 1); - if (len < sizeof(*hdr) + sizeof(*key)) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame too short, len %lu, " - "expecting at least %lu", - (unsigned long) len, - (unsigned long) sizeof(*hdr) + sizeof(*key)); - return; - } - plen = ntohs(hdr->length); - data_len = plen + sizeof(*hdr); - wpa_printf(MSG_DEBUG, "IEEE 802.1X RX: version=%d type=%d length=%lu", - hdr->version, hdr->type, (unsigned long) plen); - - wpa_drv_poll(wpa_s); - - if (hdr->version < EAPOL_VERSION) { - /* TODO: backwards compatibility */ - } - if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame (type %u) discarded, " - "not a Key frame", hdr->type); - if (wpa_s->cur_pmksa) { - wpa_printf(MSG_DEBUG, "WPA: Cancelling PMKSA caching " - "attempt - attempt full EAP " - "authentication"); - eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 0); - } - return; - } - if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { - wpa_printf(MSG_DEBUG, "WPA: EAPOL frame payload size %lu " - "invalid (frame size %lu)", - (unsigned long) plen, (unsigned long) len); - return; - } - - wpa_printf(MSG_DEBUG, " EAPOL-Key type=%d", key->type); - if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) - { - wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key type (%d) unknown, " - "discarded", key->type); - return; - } - - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len); - if (data_len < len) { - wpa_printf(MSG_DEBUG, "WPA: ignoring %lu bytes after the IEEE " - "802.1X data", (unsigned long) len - data_len); - } - key_info = be_to_host16(key->key_info); - ver = key_info & WPA_KEY_INFO_TYPE_MASK; - if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_printf(MSG_INFO, "WPA: Unsupported EAPOL-Key descriptor " - "version %d.", ver); - return; - } - - if (wpa_s->pairwise_cipher == WPA_CIPHER_CCMP && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_printf(MSG_INFO, "WPA: CCMP is used, but EAPOL-Key " - "descriptor version (%d) is not 2.", ver); - if (wpa_s->group_cipher != WPA_CIPHER_CCMP && - !(key_info & WPA_KEY_INFO_KEY_TYPE)) { - /* Earlier versions of IEEE 802.11i did not explicitly - * require version 2 descriptor for all EAPOL-Key - * packets, so allow group keys to use version 1 if - * CCMP is not used for them. */ - wpa_printf(MSG_INFO, "WPA: Backwards compatibility: " - "allow invalid version for non-CCMP group " - "keys"); - } else - return; - } - - if (wpa_s->rx_replay_counter_set && - memcmp(key->replay_counter, wpa_s->rx_replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { - wpa_printf(MSG_WARNING, "WPA: EAPOL-Key Replay Counter did not" - " increase - dropping packet"); - return; - } - - if (!(key_info & WPA_KEY_INFO_ACK)) { - wpa_printf(MSG_INFO, "WPA: No Ack bit in key_info"); - return; - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - wpa_printf(MSG_INFO, "WPA: EAPOL-Key with Request bit - " - "dropped"); - return; - } - - if ((key_info & WPA_KEY_INFO_MIC) && - wpa_supplicant_verify_eapol_key_mic(wpa_s, key, ver, buf, - data_len)) - return; - - extra_len = data_len - sizeof(*hdr) - sizeof(*key); - - if (be_to_host16(key->key_data_length) > extra_len) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid EAPOL-Key frame - " - "key_data overflow (%d > %lu)", - be_to_host16(key->key_data_length), - (unsigned long) extra_len); - return; - } - - if (wpa_s->proto == WPA_PROTO_RSN && - (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && - wpa_supplicant_decrypt_key_data(wpa_s, key, ver)) - return; - - if (key_info & WPA_KEY_INFO_KEY_TYPE) { - if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { - wpa_printf(MSG_WARNING, "WPA: Ignored EAPOL-Key " - "(Pairwise) with non-zero key index"); - return; - } - if (key_info & WPA_KEY_INFO_MIC) { - /* 3/4 4-Way Handshake */ - wpa_supplicant_process_3_of_4(wpa_s, src_addr, key, - extra_len, ver); - } else { - /* 1/4 4-Way Handshake */ - wpa_supplicant_process_1_of_4(wpa_s, src_addr, key, - ver); - } - } else { - if (key_info & WPA_KEY_INFO_MIC) { - /* 1/2 Group Key Handshake */ - wpa_supplicant_process_1_of_2(wpa_s, src_addr, key, - extra_len, ver); - } else { - wpa_printf(MSG_WARNING, "WPA: EAPOL-Key (Group) " - "without Mic bit - dropped"); - } - } -} - - -void wpa_supplicant_rx_eapol(void *ctx, unsigned char *src_addr, - unsigned char *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - - wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr)); - wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len); - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { - wpa_printf(MSG_DEBUG, "Ignored received EAPOL frame since " - "no key management is configured"); - return; - } - - if (wpa_s->eapol_received == 0) { - /* Timeout for completing IEEE 802.1X and WPA authentication */ - wpa_supplicant_req_auth_timeout( - wpa_s, - (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) ? - 70 : 10, 0); - } - wpa_s->eapol_received++; - - if (wpa_s->countermeasures) { - wpa_printf(MSG_INFO, "WPA: Countermeasures - dropped EAPOL " - "packet"); - return; - } - - /* Source address of the incoming EAPOL frame could be compared to the - * current BSSID. However, it is possible that a centralized - * Authenticator could be using another MAC address than the BSSID of - * an AP, so just allow any address to be used for now. The replies are - * still sent to the current BSSID (if available), though. */ - - memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); - eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len); - wpa_sm_rx_eapol(wpa_s, src_addr, buf, len); -} - - -static int wpa_cipher_bits(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_CCMP: - return 128; - case WPA_CIPHER_TKIP: - return 256; - case WPA_CIPHER_WEP104: - return 104; - case WPA_CIPHER_WEP40: - return 40; - default: - return 0; - } -} - - -static const u8 * wpa_key_mgmt_suite(struct wpa_supplicant *wpa_s) -{ - static const u8 *dummy = (u8 *) "\x00\x00\x00\x00"; - switch (wpa_s->key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_AUTH_KEY_MGMT_UNSPEC_802_1X : - WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); - case WPA_KEY_MGMT_PSK: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X : - WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); - case WPA_KEY_MGMT_WPA_NONE: - return WPA_AUTH_KEY_MGMT_NONE; - default: - return dummy; - } -} - - -static const u8 * wpa_cipher_suite(struct wpa_supplicant *wpa_s, int cipher) -{ - static const u8 *dummy = (u8 *) "\x00\x00\x00\x00"; - switch (cipher) { - case WPA_CIPHER_CCMP: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); - case WPA_CIPHER_TKIP: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); - case WPA_CIPHER_WEP104: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_WEP104 : WPA_CIPHER_SUITE_WEP104); - case WPA_CIPHER_WEP40: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_WEP40 : WPA_CIPHER_SUITE_WEP40); - case WPA_CIPHER_NONE: - return (wpa_s->proto == WPA_PROTO_RSN ? - RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); - default: - return dummy; - } -} - - -#define RSN_SUITE "%02x-%02x-%02x-%d" -#define RSN_SUITE_ARG(s) (s)[0], (s)[1], (s)[2], (s)[3] - -int wpa_get_mib(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) -{ - int len, i; - char pmkid_txt[PMKID_LEN * 2 + 1]; - - if (wpa_s->cur_pmksa) { - char *pos = pmkid_txt; - for (i = 0; i < PMKID_LEN; i++) { - pos += sprintf(pos, "%02x", - wpa_s->cur_pmksa->pmkid[i]); - } - } else - pmkid_txt[0] = '\0'; - - len = snprintf(buf, buflen, - "dot11RSNAConfigVersion=%d\n" - "dot11RSNAConfigPairwiseKeysSupported=5\n" - "dot11RSNAConfigGroupCipherSize=%d\n" - "dot11RSNAConfigPMKLifetime=%d\n" - "dot11RSNAConfigPMKReauthThreshold=%d\n" - "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n" - "dot11RSNAConfigSATimeout=%d\n" - "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" - "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" - "dot11RSNAPMKIDUsed=%s\n" - "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" - "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" - "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" - "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", - RSN_VERSION, - wpa_cipher_bits(wpa_s->group_cipher), - dot11RSNAConfigPMKLifetime, - dot11RSNAConfigPMKReauthThreshold, - dot11RSNAConfigSATimeout, - RSN_SUITE_ARG(wpa_key_mgmt_suite(wpa_s)), - RSN_SUITE_ARG(wpa_cipher_suite(wpa_s, - wpa_s->pairwise_cipher)), - RSN_SUITE_ARG(wpa_cipher_suite(wpa_s, - wpa_s->group_cipher)), - pmkid_txt, - RSN_SUITE_ARG(wpa_key_mgmt_suite(wpa_s)), - RSN_SUITE_ARG(wpa_cipher_suite(wpa_s, - wpa_s->pairwise_cipher)), - RSN_SUITE_ARG(wpa_cipher_suite(wpa_s, - wpa_s->group_cipher))); - return len; -} - - -#ifdef IEEE8021X_EAPOL - -static void rsn_preauth_receive(void *ctx, unsigned char *src_addr, - unsigned char *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - - wpa_printf(MSG_DEBUG, "RX pre-auth from " MACSTR, MAC2STR(src_addr)); - wpa_hexdump(MSG_MSGDUMP, "RX pre-auth", buf, len); - - if (wpa_s->preauth_eapol == NULL || - memcmp(wpa_s->preauth_bssid, "\x00\x00\x00\x00\x00\x00", - ETH_ALEN) == 0 || - memcmp(wpa_s->preauth_bssid, src_addr, ETH_ALEN) != 0) { - wpa_printf(MSG_WARNING, "RSN pre-auth frame received from " - "unexpected source " MACSTR " - dropped", - MAC2STR(src_addr)); - return; - } - - eapol_sm_rx_eapol(wpa_s->preauth_eapol, src_addr, buf, len); -} - - -static void rsn_preauth_eapol_cb(struct eapol_sm *eapol, int success, - void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - u8 pmk[PMK_LEN]; - - wpa_msg(wpa_s, MSG_INFO, "RSN: pre-authentication with " MACSTR - " %s", MAC2STR(wpa_s->preauth_bssid), - success ? "completed successfully" : "failed"); - - if (success) { - int res, pmk_len; - pmk_len = PMK_LEN; - res = eapol_sm_get_key(eapol, pmk, PMK_LEN); -#ifdef EAP_LEAP - if (res) { - res = eapol_sm_get_key(eapol, pmk, 16); - pmk_len = 16; - } -#endif /* EAP_LEAP */ - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from pre-auth", - pmk, pmk_len); - wpa_s->pmk_len = pmk_len; - pmksa_cache_add(wpa_s, pmk, pmk_len, - wpa_s->preauth_bssid, wpa_s->own_addr); - } else { - wpa_msg(wpa_s, MSG_INFO, "RSN: failed to get master " - "session key from pre-auth EAPOL state " - "machines"); - } - } - - rsn_preauth_deinit(wpa_s); - rsn_preauth_candidate_process(wpa_s); -} - - -static void rsn_preauth_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_msg(wpa_s, MSG_INFO, "RSN: pre-authentication with " MACSTR - " timed out", MAC2STR(wpa_s->preauth_bssid)); - rsn_preauth_deinit(wpa_s); - rsn_preauth_candidate_process(wpa_s); -} - - -int rsn_preauth_init(struct wpa_supplicant *wpa_s, u8 *dst) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - if (wpa_s->preauth_eapol) - return -1; - - wpa_msg(wpa_s, MSG_DEBUG, "RSN: starting pre-authentication with " - MACSTR, MAC2STR(dst)); - - wpa_s->l2_preauth = l2_packet_init(wpa_s->ifname, - wpa_drv_get_mac_addr(wpa_s), - ETH_P_RSN_PREAUTH, - rsn_preauth_receive, wpa_s); - if (wpa_s->l2_preauth == NULL) { - wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " - "processing for pre-authentication"); - return -2; - } - - ctx = malloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); - return -4; - } - memset(ctx, 0, sizeof(*ctx)); - ctx->ctx = wpa_s; - ctx->msg_ctx = wpa_s; - ctx->preauth = 1; - ctx->cb = rsn_preauth_eapol_cb; - ctx->cb_ctx = wpa_s; - ctx->scard_ctx = wpa_s->scard; - ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; - ctx->eapol_send = wpa_eapol_send_preauth; - - wpa_s->preauth_eapol = eapol_sm_init(ctx); - if (wpa_s->preauth_eapol == NULL) { - free(ctx); - wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " - "state machines for pre-authentication"); - return -3; - } - memset(&eapol_conf, 0, sizeof(eapol_conf)); - eapol_conf.accept_802_1x_keys = 0; - eapol_conf.required_keys = 0; - eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; - if (wpa_s->current_ssid) - eapol_conf.workaround = wpa_s->current_ssid->eap_workaround; - eapol_sm_notify_config(wpa_s->preauth_eapol, wpa_s->current_ssid, - &eapol_conf); - memcpy(wpa_s->preauth_bssid, dst, ETH_ALEN); - - eapol_sm_notify_portValid(wpa_s->preauth_eapol, TRUE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->preauth_eapol, TRUE); - - eloop_register_timeout(60, 0, rsn_preauth_timeout, wpa_s, NULL); - - return 0; -} - - -void rsn_preauth_deinit(struct wpa_supplicant *wpa_s) -{ - if (!wpa_s->preauth_eapol) - return; - - eloop_cancel_timeout(rsn_preauth_timeout, wpa_s, NULL); - eapol_sm_deinit(wpa_s->preauth_eapol); - wpa_s->preauth_eapol = NULL; - memset(wpa_s->preauth_bssid, 0, ETH_ALEN); - - l2_packet_deinit(wpa_s->l2_preauth); - wpa_s->l2_preauth = NULL; -} - - -static void rsn_preauth_candidate_process(struct wpa_supplicant *wpa_s) -{ - struct rsn_pmksa_candidate *candidate; - - if (wpa_s->pmksa_candidates == NULL) - return; - - /* TODO: drop priority for old candidate entries */ - - wpa_msg(wpa_s, MSG_DEBUG, "RSN: processing PMKSA candidate list"); - if (wpa_s->preauth_eapol || - wpa_s->proto != WPA_PROTO_RSN || - wpa_s->wpa_state != WPA_COMPLETED || - wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X) { - wpa_msg(wpa_s, MSG_DEBUG, "RSN: not in suitable state for new " - "pre-authentication"); - return; /* invalid state for new pre-auth */ - } - - while (wpa_s->pmksa_candidates) { - struct rsn_pmksa_cache *p = NULL; - candidate = wpa_s->pmksa_candidates; - p = pmksa_cache_get(wpa_s, candidate->bssid, NULL); - if (memcmp(wpa_s->bssid, candidate->bssid, ETH_ALEN) != 0 && - p == NULL) { - wpa_msg(wpa_s, MSG_DEBUG, "RSN: PMKSA candidate " - MACSTR " selected for pre-authentication", - MAC2STR(candidate->bssid)); - wpa_s->pmksa_candidates = candidate->next; - rsn_preauth_init(wpa_s, candidate->bssid); - free(candidate); - return; - } - wpa_msg(wpa_s, MSG_DEBUG, "RSN: PMKSA candidate " MACSTR - " does not need pre-authentication anymore", - MAC2STR(candidate->bssid)); - /* Some drivers (e.g., NDIS) expect to get notified about the - * PMKIDs again, so report the existing data now. */ - if (p) - wpa_drv_add_pmkid(wpa_s, candidate->bssid, p->pmkid); - - wpa_s->pmksa_candidates = candidate->next; - free(candidate); - } - wpa_msg(wpa_s, MSG_DEBUG, "RSN: no more pending PMKSA candidates"); -} - - -void pmksa_candidate_add(struct wpa_supplicant *wpa_s, const u8 *bssid, - int prio) -{ - struct rsn_pmksa_candidate *cand, *prev, *pos; - - /* If BSSID already on candidate list, update the priority of the old - * entry. Do not override priority based on normal scan results. */ - prev = NULL; - cand = wpa_s->pmksa_candidates; - while (cand) { - if (memcmp(cand->bssid, bssid, ETH_ALEN) == 0) { - if (prev) - prev->next = cand->next; - else - wpa_s->pmksa_candidates = cand->next; - break; - } - prev = cand; - cand = cand->next; - } - - if (cand) { - if (prio < PMKID_CANDIDATE_PRIO_SCAN) - cand->priority = prio; - } else { - cand = malloc(sizeof(*cand)); - if (cand == NULL) - return; - memset(cand, 0, sizeof(*cand)); - memcpy(cand->bssid, bssid, ETH_ALEN); - cand->priority = prio; - } - - /* Add candidate to the list; order by increasing priority value. i.e., - * highest priority (smallest value) first. */ - prev = NULL; - pos = wpa_s->pmksa_candidates; - while (pos) { - if (cand->priority <= pos->priority) - break; - prev = pos; - pos = pos->next; - } - cand->next = pos; - if (prev) - prev->next = cand; - else - wpa_s->pmksa_candidates = cand; - - wpa_msg(wpa_s, MSG_DEBUG, "RSN: added PMKSA cache " - "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); - rsn_preauth_candidate_process(wpa_s); -} - - -/* TODO: schedule periodic scans if current AP supports preauth */ -void rsn_preauth_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, int count) -{ - struct wpa_scan_result *r; - struct wpa_ie_data ie; - int i; - - if (wpa_s->current_ssid == NULL) - return; - - pmksa_candidate_free(wpa_s); - - for (i = count - 1; i >= 0; i--) { - r = &results[i]; - if (r->ssid_len == wpa_s->current_ssid->ssid_len && - memcmp(r->ssid, wpa_s->current_ssid->ssid, r->ssid_len) == - 0 && - memcmp(r->bssid, wpa_s->bssid, ETH_ALEN) != 0 && - r->rsn_ie_len > 0 && - wpa_parse_wpa_ie(wpa_s, r->rsn_ie, r->rsn_ie_len, &ie) == - 0 && - (ie.capabilities & WPA_CAPABILITY_PREAUTH) && - pmksa_cache_get(wpa_s, r->bssid, NULL) == NULL) { - /* Give less priority to candidates found from normal - * scan results. */ - pmksa_candidate_add(wpa_s, r->bssid, - PMKID_CANDIDATE_PRIO_SCAN); - } - } -} - -#else /* IEEE8021X_EAPOL */ - -static void rsn_preauth_candidate_process(struct wpa_supplicant *wpa_s) -{ -} - -#endif /* IEEE8021X_EAPOL */ diff --git a/contrib/wpa_supplicant/wpa.h b/contrib/wpa_supplicant/wpa.h deleted file mode 100644 index a4f3f55c72f2..000000000000 --- a/contrib/wpa_supplicant/wpa.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef WPA_H -#define WPA_H - -#define BIT(n) (1 << (n)) - -struct ieee802_1x_hdr { - u8 version; - u8 type; - u16 length; - /* followed by length octets of data */ -} __attribute__ ((packed)); - -#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 }; - - -#define IEEE8021X_REPLAY_COUNTER_LEN 8 -#define IEEE8021X_KEY_SIGN_LEN 16 -#define IEEE8021X_KEY_IV_LEN 16 - -#define IEEE8021X_KEY_INDEX_FLAG 0x80 -#define IEEE8021X_KEY_INDEX_MASK 0x03 - -struct ieee802_1x_eapol_key { - u8 type; - u16 key_length; - /* does not repeat within the life of the keying material used to - * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ - u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; - u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ - u8 key_index; /* key flag in the most significant bit: - * 0 = broadcast (default key), - * 1 = unicast (key mapping key); key index is in the - * 7 least significant bits */ - /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as - * the key */ - u8 key_signature[IEEE8021X_KEY_SIGN_LEN]; - - /* followed by key: if packet body length = 44 + key length, then the - * key field (of key_length bytes) contains the key in encrypted form; - * if packet body length = 44, key field is absent and key_length - * represents the number of least significant octets from - * MS-MPPE-Send-Key attribute to be used as the keying material; - * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} __attribute__ ((packed)); - - -#define WPA_NONCE_LEN 32 -#define WPA_REPLAY_COUNTER_LEN 8 - -struct wpa_eapol_key { - u8 type; - u16 key_info; - u16 key_length; - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - u8 key_nonce[WPA_NONCE_LEN]; - u8 key_iv[16]; - u8 key_rsc[8]; - u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[16]; - u16 key_data_length; - /* followed by key_data_length bytes of key_data */ -} __attribute__ ((packed)); - -#define WPA_KEY_INFO_TYPE_MASK (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_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_CAPABILITY_PREAUTH BIT(0) - -#define GENERIC_INFO_ELEM 0xdd -#define RSN_INFO_ELEM 0x30 - -enum { - REASON_UNSPECIFIED = 1, - REASON_DEAUTH_LEAVING = 3, - REASON_INVALID_IE = 13, - REASON_MICHAEL_MIC_FAILURE = 14, - REASON_4WAY_HANDSHAKE_TIMEOUT = 15, - REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, - REASON_IE_IN_4WAY_DIFFERS = 17, - REASON_GROUP_CIPHER_NOT_VALID = 18, - REASON_PAIRWISE_CIPHER_NOT_VALID = 19, - REASON_AKMP_NOT_VALID = 20, - REASON_UNSUPPORTED_RSN_IE_VERSION = 21, - REASON_INVALID_RSN_IE_CAPAB = 22, - REASON_IEEE_802_1X_AUTH_FAILED = 23, - REASON_CIPHER_SUITE_REJECTED = 24 -}; - -#endif /* WPA_H */ diff --git a/contrib/wpa_supplicant/wpa_cli.c b/contrib/wpa_supplicant/wpa_cli.c deleted file mode 100644 index 8582fae27864..000000000000 --- a/contrib/wpa_supplicant/wpa_cli.c +++ /dev/null @@ -1,850 +0,0 @@ -/* - * WPA Supplicant - command line interface for wpa_supplicant daemon - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#include <dirent.h> -#ifdef CONFIG_READLINE -#include <readline/readline.h> -#include <readline/history.h> -#endif /* CONFIG_READLINE */ - -#include "wpa_ctrl.h" -#ifdef CONFIG_NATIVE_WINDOWS -#include "common.h" -#endif /* CONFIG_NATIVE_WINDOWS */ -#include "version.h" - - -static const char *wpa_cli_version = -"wpa_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> and contributors"; - - -static const char *wpa_cli_license = -"This program is free software. You can distribute it and/or modify it\n" -"under the terms of the GNU General Public License version 2.\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license. See README and COPYING for more details.\n"; - -static const char *wpa_cli_full_license = -"This program is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License version 2 as\n" -"published by the Free Software Foundation.\n" -"\n" -"This program is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n" -"\n" -"You should have received a copy of the GNU General Public License\n" -"along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license.\n" -"\n" -"Redistribution and use in source and binary forms, with or without\n" -"modification, are permitted provided that the following conditions are\n" -"met:\n" -"\n" -"1. Redistributions of source code must retain the above copyright\n" -" notice, this list of conditions and the following disclaimer.\n" -"\n" -"2. Redistributions in binary form must reproduce the above copyright\n" -" notice, this list of conditions and the following disclaimer in the\n" -" documentation and/or other materials provided with the distribution.\n" -"\n" -"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" -" names of its contributors may be used to endorse or promote products\n" -" derived from this software without specific prior written permission.\n" -"\n" -"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n"; - -static const char *commands_help = -"commands:\n" -" status [verbose] = get current WPA/EAPOL/EAP status\n" -" mib = get MIB variables (dot1x, dot11)\n" -" help = show this usage help\n" -" interface [ifname] = show interfaces/select interface\n" -" level <debug level> = change debug level\n" -" license = show full wpa_cli license\n" -" logoff = IEEE 802.1X EAPOL state machine logoff\n" -" logon = IEEE 802.1X EAPOL state machine logon\n" -" set = set variables (shows list of variables when run without arguments)\n" -" pmksa = show PMKSA cache\n" -" reassociate = force reassociation\n" -" reconfigure = force wpa_supplicant to re-read its configuration file\n" -" preauthenticate <BSSID> = force preauthentication\n" -" identity <network id> <identity> = configure identity for an SSID\n" -" password <network id> <password> = configure password for an SSID\n" -" otp <network id> <password> = configure one-time-password for an SSID\n" -" terminate = terminate wpa_supplicant\n" -" quit = exit wpa_cli\n"; - -static struct wpa_ctrl *ctrl_conn; -static int wpa_cli_quit = 0; -static int wpa_cli_attached = 0; -static const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; -static char *ctrl_ifname = NULL; - - -static void usage(void) -{ - printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hv] " - "[command..]\n" - " -h = help (show this usage text)\n" - " -v = shown version information\n" - " default path: /var/run/wpa_supplicant\n" - " default interface: first interface found in socket path\n" - "%s", - commands_help); -} - - -static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname) -{ -#ifdef CONFIG_CTRL_IFACE_UDP - ctrl_conn = wpa_ctrl_open(""); - return ctrl_conn; -#else /* CONFIG_CTRL_IFACE_UDP */ - char *cfile; - int flen; - - if (ifname == NULL) - return NULL; - - flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2; - cfile = malloc(flen); - if (cfile == NULL) - return NULL; - snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); - - ctrl_conn = wpa_ctrl_open(cfile); - free(cfile); - return ctrl_conn; -#endif /* CONFIG_CTRL_IFACE_UDP */ -} - - -static void wpa_cli_close_connection(void) -{ - if (ctrl_conn == NULL) - return; - - if (wpa_cli_attached) { - wpa_ctrl_detach(ctrl_conn); - wpa_cli_attached = 0; - } - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; -} - - -static void wpa_cli_msg_cb(char *msg, size_t len) -{ - printf("%s\n", msg); -} - - -static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) -{ - char buf[2048]; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to wpa_supplicant - command dropped.\n"); - return -1; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, - wpa_cli_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - return -2; - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - return -1; - } - if (print) { - buf[len] = '\0'; - printf("%s", buf); - } - return 0; -} - - -static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) -{ - return _wpa_ctrl_command(ctrl, cmd, 1); -} - - -static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - int verbose = argc > 0 && strcmp(argv[0], "verbose") == 0; - return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); -} - - -static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PING"); -} - - -static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "MIB"); -} - - -static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PMKSA"); -} - - -static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s", commands_help); - return 0; -} - - -static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); - return 0; -} - - -static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - wpa_cli_quit = 1; - return 0; -} - - -static void wpa_cli_show_variables(void) -{ - printf("set variables:\n" - " EAPOL::heldPeriod (EAPOL state machine held period, " - "in seconds)\n" - " EAPOL::authPeriod (EAPOL state machine authentication " - "period, in seconds)\n" - " EAPOL::startPeriod (EAPOL state machine start period, in " - "seconds)\n" - " EAPOL::maxStart (EAPOL state machine maximum start " - "attempts)\n"); -} - - -static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - - if (argc == 0) { - wpa_cli_show_variables(); - return 0; - } - - if (argc != 2) { - printf("Invalid SET command: needs two arguments (variable " - "name and value)\n"); - return 0; - } - - if (snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]) >= - sizeof(cmd) - 1) { - printf("Too long SET command.\n"); - return 0; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LOGOFF"); -} - - -static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LOGON"); -} - - -static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "REASSOCIATE"); -} - - -static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - - if (argc != 1) { - printf("Invalid PREAUTH command: needs one argument " - "(BSSID)\n"); - return 0; - } - - if (snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]) >= - sizeof(cmd) - 1) { - printf("Too long PREAUTH command.\n"); - return 0; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - if (argc != 1) { - printf("Invalid LEVEL command: needs one argument (debug " - "level)\n"); - return 0; - } - snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i; - - if (argc < 2) { - printf("Invalid IDENTITY command: needs two arguments " - "(network id and identity)\n"); - return 0; - } - - end = cmd + sizeof(cmd); - pos = cmd; - pos += snprintf(pos, end - pos, "CTRL-RSP-IDENTITY-%s:%s", - argv[0], argv[1]); - for (i = 2; i < argc; i++) - pos += snprintf(pos, end - pos, " %s", argv[i]); - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i; - - if (argc < 2) { - printf("Invalid PASSWORD command: needs two arguments " - "(network id and password)\n"); - return 0; - } - - end = cmd + sizeof(cmd); - pos = cmd; - pos += snprintf(pos, end - pos, "CTRL-RSP-PASSWORD-%s:%s", - argv[0], argv[1]); - for (i = 2; i < argc; i++) - pos += snprintf(pos, end - pos, " %s", argv[i]); - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i; - - if (argc < 2) { - printf("Invalid OTP command: needs two arguments (network " - "id and password)\n"); - return 0; - } - - end = cmd + sizeof(cmd); - pos = cmd; - pos += snprintf(pos, end - pos, "CTRL-RSP-OTP-%s:%s", - argv[0], argv[1]); - for (i = 2; i < argc; i++) - pos += snprintf(pos, end - pos, " %s", argv[i]); - - return wpa_ctrl_command(ctrl, cmd); -} - - -static void wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) -{ - struct dirent *dent; - DIR *dir; - - dir = opendir(ctrl_iface_dir); - if (dir == NULL) { - printf("Control interface directory '%s' could not be " - "openned.\n", ctrl_iface_dir); - return; - } - - printf("Available interfaces:\n"); - while ((dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - printf("%s\n", dent->d_name); - } - closedir(dir); -} - - -static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc < 1) { - wpa_cli_list_interfaces(ctrl); - return 0; - } - - wpa_cli_close_connection(); - free(ctrl_ifname); - ctrl_ifname = strdup(argv[0]); - - if (wpa_cli_open_connection(ctrl_ifname)) { - printf("Connected to interface '%s.\n", ctrl_ifname); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - wpa_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - } - } else { - printf("Could not connect to interface '%s' - re-trying\n", - ctrl_ifname); - } - return 0; -} - - -static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RECONFIGURE"); -} - - -static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "TERMINATE"); -} - - -struct wpa_cli_cmd { - const char *cmd; - int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); -}; - -static struct wpa_cli_cmd wpa_cli_commands[] = { - { "status", wpa_cli_cmd_status }, - { "ping", wpa_cli_cmd_ping }, - { "mib", wpa_cli_cmd_mib }, - { "help", wpa_cli_cmd_help }, - { "interface", wpa_cli_cmd_interface }, - { "level", wpa_cli_cmd_level }, - { "license", wpa_cli_cmd_license }, - { "quit", wpa_cli_cmd_quit }, - { "set", wpa_cli_cmd_set }, - { "logon", wpa_cli_cmd_logon }, - { "logoff", wpa_cli_cmd_logoff }, - { "pmksa", wpa_cli_cmd_pmksa }, - { "reassociate", wpa_cli_cmd_reassociate }, - { "preauthenticate", wpa_cli_cmd_preauthenticate }, - { "identity", wpa_cli_cmd_identity }, - { "password", wpa_cli_cmd_password }, - { "otp", wpa_cli_cmd_otp }, - { "reconfigure", wpa_cli_cmd_reconfigure }, - { "terminate", wpa_cli_cmd_terminate }, - { NULL, NULL } -}; - - -static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - struct wpa_cli_cmd *cmd, *match = NULL; - int count; - - count = 0; - cmd = wpa_cli_commands; - while (cmd->cmd) { - if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) { - match = cmd; - count++; - } - cmd++; - } - - if (count > 1) { - printf("Ambiguous command '%s'; possible commands:", argv[0]); - cmd = wpa_cli_commands; - while (cmd->cmd) { - if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == - 0) { - printf(" %s", cmd->cmd); - } - cmd++; - } - printf("\n"); - } else if (count == 0) { - printf("Unknown command '%s'\n", argv[0]); - } else { - match->handler(ctrl, argc - 1, &argv[1]); - } -} - - -static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read) -{ - int first = 1; - if (ctrl_conn == NULL) - return; - while (wpa_ctrl_pending(ctrl)) { - char buf[256]; - size_t len = sizeof(buf) - 1; - if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { - buf[len] = '\0'; - if (in_read && first) - printf("\n"); - first = 0; - printf("%s\n", buf); - } else { - printf("Could not read pending message.\n"); - break; - } - } -} - - -#ifdef CONFIG_READLINE -static char * wpa_cli_cmd_gen(const char *text, int state) -{ - static int i, len; - const char *cmd; - - if (state == 0) { - i = 0; - len = strlen(text); - } - - while ((cmd = wpa_cli_commands[i].cmd)) { - i++; - if (strncasecmp(cmd, text, len) == 0) - return strdup(cmd); - } - - return NULL; -} - - -static char * wpa_cli_dummy_gen(const char *text, int state) -{ - return NULL; -} - - -static char ** wpa_cli_completion(const char *text, int start, int end) -{ - return rl_completion_matches(text, start == 0 ? - wpa_cli_cmd_gen : wpa_cli_dummy_gen); -} -#endif /* CONFIG_READLINE */ - - -static void wpa_cli_interactive(void) -{ -#define max_args 10 - char cmdbuf[256], *cmd, *argv[max_args], *pos; - int argc; -#ifdef CONFIG_READLINE - char *home, *hfile = NULL; -#endif /* CONFIG_READLINE */ - - printf("\nInteractive mode\n\n"); - -#ifdef CONFIG_READLINE - rl_attempted_completion_function = wpa_cli_completion; - home = getenv("HOME"); - if (home) { - const char *fname = ".wpa_cli_history"; - int hfile_len = strlen(home) + 1 + strlen(fname) + 1; - hfile = malloc(hfile_len); - if (hfile) { - snprintf(hfile, hfile_len, "%s/%s", home, fname); - read_history(hfile); - stifle_history(100); - } - } -#endif /* CONFIG_READLINE */ - - do { - wpa_cli_recv_pending(ctrl_conn, 0); -#ifndef CONFIG_NATIVE_WINDOWS - alarm(1); -#endif /* CONFIG_NATIVE_WINDOWS */ -#ifdef CONFIG_READLINE - cmd = readline("> "); - if (cmd && *cmd) { - HIST_ENTRY *h; - while (next_history()) - ; - h = previous_history(); - if (h == NULL || strcmp(cmd, h->line) != 0) - add_history(cmd); - next_history(); - } -#else /* CONFIG_READLINE */ - printf("> "); - cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); -#endif /* CONFIG_READLINE */ -#ifndef CONFIG_NATIVE_WINDOWS - alarm(0); -#endif /* CONFIG_NATIVE_WINDOWS */ - if (cmd == NULL) - break; - pos = cmd; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - argc = 0; - pos = cmd; - for (;;) { - while (*pos == ' ') - pos++; - if (*pos == '\0') - break; - argv[argc] = pos; - argc++; - if (argc == max_args) - break; - while (*pos != '\0' && *pos != ' ') - pos++; - if (*pos == ' ') - *pos++ = '\0'; - } - if (argc) - wpa_request(ctrl_conn, argc, argv); - - if (cmd != cmdbuf) - free(cmd); - } while (!wpa_cli_quit); - -#ifdef CONFIG_READLINE - if (hfile) { - /* Save command history, excluding lines that may contain - * passwords. */ - HIST_ENTRY *h; - history_set_pos(0); - h = next_history(); - while (h) { - char *p = h->line; - while (*p == ' ' || *p == '\t') - p++; - if (strncasecmp(p, "pa", 2) == 0 || - strncasecmp(p, "o", 1) == 0) { - h = remove_history(where_history()); - if (h) { - free(h->line); - free(h->data); - free(h); - } - h = current_history(); - } else { - h = next_history(); - } - } - write_history(hfile); - free(hfile); - } -#endif /* CONFIG_READLINE */ -} - - -static void wpa_cli_terminate(int sig) -{ - wpa_cli_close_connection(); - exit(0); -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void wpa_cli_alarm(int sig) -{ - if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { - printf("Connection to wpa_supplicant lost - trying to " - "reconnect\n"); - wpa_cli_close_connection(); - } - if (!ctrl_conn) { - ctrl_conn = wpa_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - printf("Connection to wpa_supplicant " - "re-established\n"); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - wpa_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - } - } - } - if (ctrl_conn) - wpa_cli_recv_pending(ctrl_conn, 1); - alarm(1); -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -int main(int argc, char *argv[]) -{ - int interactive; - int warning_displayed = 0; - int c; - -#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 */ - - for (;;) { - c = getopt(argc, argv, "hi:p:v"); - if (c < 0) - break; - switch (c) { - case 'h': - usage(); - return 0; - case 'v': - printf("%s\n", wpa_cli_version); - return 0; - case 'i': - ctrl_ifname = strdup(optarg); - break; - case 'p': - ctrl_iface_dir = optarg; - break; - default: - usage(); - return -1; - } - } - - interactive = argc == optind; - - if (interactive) - printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); - - for (;;) { - if (ctrl_ifname == NULL) { - struct dirent *dent; - DIR *dir = opendir(ctrl_iface_dir); - if (dir) { - while ((dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - printf("Selected interface '%s'\n", - dent->d_name); - ctrl_ifname = strdup(dent->d_name); - break; - } - closedir(dir); - } - } - ctrl_conn = wpa_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - if (warning_displayed) - printf("Connection established.\n"); - break; - } - - if (!interactive) { - perror("Failed to connect to wpa_supplicant - " - "wpa_ctrl_open"); - return -1; - } - - if (!warning_displayed) { - printf("Could not connect to wpa_supplicant - " - "re-trying\n"); - warning_displayed = 1; - } - sleep(1); - continue; - } - - signal(SIGINT, wpa_cli_terminate); - signal(SIGTERM, wpa_cli_terminate); -#ifndef CONFIG_NATIVE_WINDOWS - signal(SIGALRM, wpa_cli_alarm); -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (interactive) { - if (wpa_ctrl_attach(ctrl_conn) == 0) { - wpa_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - } - wpa_cli_interactive(); - } else - wpa_request(ctrl_conn, argc - optind, &argv[optind]); - - free(ctrl_ifname); - wpa_cli_close_connection(); - -#ifdef CONFIG_NATIVE_WINDOWS - WSACleanup(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return 0; -} diff --git a/contrib/wpa_supplicant/wpa_ctrl.c b/contrib/wpa_supplicant/wpa_ctrl.c deleted file mode 100644 index 631c628efbdc..000000000000 --- a/contrib/wpa_supplicant/wpa_ctrl.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * WPA Supplicant - wpa_supplicant control interface library - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/time.h> -#ifndef CONFIG_NATIVE_WINDOWS -#include <sys/socket.h> -#include <sys/un.h> -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "wpa_ctrl.h" -#ifdef CONFIG_NATIVE_WINDOWS -#include "common.h" -#endif /* CONFIG_NATIVE_WINDOWS */ - - -struct wpa_ctrl { - int s; -#ifdef CONFIG_CTRL_IFACE_UDP - struct sockaddr_in local; - struct sockaddr_in dest; -#else /* CONFIG_CTRL_IFACE_UDP */ - struct sockaddr_un local; - struct sockaddr_un dest; -#endif /* CONFIG_CTRL_IFACE_UDP */ -}; - - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; -#ifndef CONFIG_CTRL_IFACE_UDP - static int counter = 0; -#endif /* CONFIG_CTRL_IFACE_UDP */ - - ctrl = malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - memset(ctrl, 0, sizeof(*ctrl)); - -#ifdef CONFIG_CTRL_IFACE_UDP - ctrl->s = socket(PF_INET, SOCK_DGRAM, 0); - if (ctrl->s < 0) { - perror("socket"); - 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); - 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(9877); - if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, - sizeof(ctrl->dest)) < 0) { - perror("connect"); - close(ctrl->s); - free(ctrl); - return NULL; - } -#else /* CONFIG_CTRL_IFACE_UDP */ - ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); - if (ctrl->s < 0) { - free(ctrl); - return NULL; - } - - ctrl->local.sun_family = AF_UNIX; - snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), - "/tmp/wpa_ctrl_%d-%d", getpid(), counter++); - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - close(ctrl->s); - free(ctrl); - return NULL; - } - - ctrl->dest.sun_family = AF_UNIX; - snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s", - ctrl_path); - if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, - sizeof(ctrl->dest)) < 0) { - close(ctrl->s); - unlink(ctrl->local.sun_path); - free(ctrl); - return NULL; - } -#endif /* CONFIG_CTRL_IFACE_UDP */ - - return ctrl; -} - - -void wpa_ctrl_close(struct wpa_ctrl *ctrl) -{ -#ifndef CONFIG_CTRL_IFACE_UDP - unlink(ctrl->local.sun_path); -#endif /* CONFIG_CTRL_IFACE_UDP */ - close(ctrl->s); - free(ctrl); -} - - -int wpa_ctrl_request(struct wpa_ctrl *ctrl, 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; - - if (send(ctrl->s, cmd, cmd_len, 0) < 0) - return -1; - - 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 (res == *reply_len) - res = (*reply_len) - 1; - reply[res] = '\0'; - msg_cb(reply, res); - } - continue; - } - *reply_len = res; - break; - } else { - return -2; - } - } - return 0; -} - - -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 && 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); -} - - -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; - int res; - fd_set rfds; - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - res = 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; -} diff --git a/contrib/wpa_supplicant/wpa_ctrl.h b/contrib/wpa_supplicant/wpa_ctrl.h deleted file mode 100644 index 48b088abea52..000000000000 --- a/contrib/wpa_supplicant/wpa_ctrl.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef WPA_CTRL_H -#define WPA_CTRL_H - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); -void wpa_ctrl_close(struct wpa_ctrl *ctrl); -int wpa_ctrl_request(struct wpa_ctrl *ctrl, char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, - void (*msg_cb)(char *msg, size_t len)); -int wpa_ctrl_attach(struct wpa_ctrl *ctrl); -int wpa_ctrl_detach(struct wpa_ctrl *ctrl); -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); -int wpa_ctrl_pending(struct wpa_ctrl *ctrl); -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); - -#endif /* WPA_CTRL_H */ diff --git a/contrib/wpa_supplicant/wpa_passphrase.c b/contrib/wpa_supplicant/wpa_passphrase.c deleted file mode 100644 index 5a8203b833f4..000000000000 --- a/contrib/wpa_supplicant/wpa_passphrase.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * WPA Supplicant - ASCII passphrase to WPA PSK tool - * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdio.h> -#include <string.h> - -#include "common.h" -#include "sha1.h" - - -int main(int argc, char *argv[]) -{ - unsigned char psk[32]; - int i; - char *ssid, *passphrase; - - if (argc != 3) { - printf("usage: wpa_passphrase <ssid> <passphrase>\n"); - return 1; - } - - ssid = argv[1]; - passphrase = argv[2]; - - if (strlen(passphrase) < 8 || strlen(passphrase) > 63) { - printf("Passphrase must be 8..63 characters\n"); - return 1; - } - - pbkdf2_sha1(passphrase, ssid, strlen(ssid), 4096, psk, 32); - - printf("network={\n"); - printf("\tssid=\"%s\"\n", ssid); - printf("\t#psk=\"%s\"\n", passphrase); - printf("\tpsk="); - for (i = 0; i < 32; i++) - printf("%02x", psk[i]); - printf("\n"); - printf("}\n"); - - return 0; -} diff --git a/contrib/wpa_supplicant/wpa_supplicant.c b/contrib/wpa_supplicant/wpa_supplicant.c deleted file mode 100644 index 0c57143f826e..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant.c +++ /dev/null @@ -1,2483 +0,0 @@ -/* - * WPA Supplicant - * Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <sys/time.h> -#include <time.h> -#include <signal.h> -#include <sys/types.h> -#ifndef CONFIG_NATIVE_WINDOWS -#include <sys/socket.h> -#include <sys/un.h> -#endif /* CONFIG_NATIVE_WINDOWS */ -#include <unistd.h> -#include <ctype.h> -#ifndef CONFIG_NATIVE_WINDOWS -#include <netinet/in.h> -#endif /* CONFIG_NATIVE_WINDOWS */ -#include <fcntl.h> - -#define OPENSSL_DISABLE_OLD_DES_SUPPORT -#include "common.h" -#include "eapol_sm.h" -#include "eap.h" -#include "wpa.h" -#include "driver.h" -#include "eloop.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "l2_packet.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" -#include "pcsc_funcs.h" -#include "version.h" - -static const char *wpa_supplicant_version = -"wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi> and contributors"; - -static const char *wpa_supplicant_license = -"This program is free software. You can distribute it and/or modify it\n" -"under the terms of the GNU General Public License version 2.\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license. See README and COPYING for more details.\n" -#ifdef EAP_TLS_FUNCS -"\nThis product includes software developed by the OpenSSL Project\n" -"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n" -#endif /* EAP_TLS_FUNCS */ -; - -static const char *wpa_supplicant_full_license = -"This program is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License version 2 as\n" -"published by the Free Software Foundation.\n" -"\n" -"This program is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n" -"\n" -"You should have received a copy of the GNU General Public License\n" -"along with this program; if not, write to the Free Software\n" -"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" -"\n" -"Alternatively, this software may be distributed under the terms of the\n" -"BSD license.\n" -"\n" -"Redistribution and use in source and binary forms, with or without\n" -"modification, are permitted provided that the following conditions are\n" -"met:\n" -"\n" -"1. Redistributions of source code must retain the above copyright\n" -" notice, this list of conditions and the following disclaimer.\n" -"\n" -"2. Redistributions in binary form must reproduce the above copyright\n" -" notice, this list of conditions and the following disclaimer in the\n" -" documentation and/or other materials provided with the distribution.\n" -"\n" -"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" -" names of its contributors may be used to endorse or promote products\n" -" derived from this software without specific prior written permission.\n" -"\n" -"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n"; - -extern struct wpa_driver_ops *wpa_supplicant_drivers[]; - -static void wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s); -static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s, - int wait_for_interface); -static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid); -static int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid, - u8 *wpa_ie, int *wpa_ie_len); - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -extern int wpa_debug_timestamp; - - -void wpa_msg(struct wpa_supplicant *wpa_s, int level, char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = malloc(buflen); - if (buf == NULL) { - printf("Failed to allocate message buffer for:\n"); - va_start(ap, fmt); - vprintf(fmt, ap); - printf("\n"); - va_end(ap); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s", buf); - wpa_supplicant_ctrl_iface_send(wpa_s, level, buf, len); - free(buf); -} - - -int wpa_eapol_send(void *ctx, int type, u8 *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - u8 *msg, *dst, bssid[ETH_ALEN]; - size_t msglen; - struct l2_ethhdr *ethhdr; - struct ieee802_1x_hdr *hdr; - int res; - - /* TODO: could add l2_packet_sendmsg that allows fragments to avoid - * extra copy here */ - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { - /* Current SSID is not using IEEE 802.1X/EAP, so drop possible - * EAPOL frames (mainly, EAPOL-Start) from EAPOL state - * machines. */ - wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " - "mode (type=%d len=%lu)", type, - (unsigned long) len); - return -1; - } - - if (wpa_s->cur_pmksa && type == IEEE802_1X_TYPE_EAPOL_START) { - /* Trying to use PMKSA caching - do not send EAPOL-Start frames - * since they will trigger full EAPOL authentication. */ - wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send " - "EAPOL-Start"); - return -1; - } - - if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) { - wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " - "EAPOL frame"); - if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && - memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) { - dst = bssid; - wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR - " from the driver as the EAPOL destination", - MAC2STR(dst)); - } else { - dst = wpa_s->last_eapol_src; - wpa_printf(MSG_DEBUG, "Using the source address of the" - " last received EAPOL frame " MACSTR " as " - "the EAPOL destination", - MAC2STR(dst)); - } - } else { - /* BSSID was already set (from (Re)Assoc event, so use it as - * the EAPOL destination. */ - dst = wpa_s->bssid; - } - - msglen = sizeof(*ethhdr) + sizeof(*hdr) + len; - msg = malloc(msglen); - if (msg == NULL) - return -1; - - ethhdr = (struct l2_ethhdr *) msg; - memcpy(ethhdr->h_dest, dst, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_EAPOL); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = type; - hdr->length = htons(len); - - memcpy((u8 *) (hdr + 1), buf, len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); - res = l2_packet_send(wpa_s->l2, msg, msglen); - free(msg); - return res; -} - - -int wpa_eapol_send_preauth(void *ctx, int type, u8 *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - u8 *msg; - size_t msglen; - struct l2_ethhdr *ethhdr; - struct ieee802_1x_hdr *hdr; - int res; - - /* TODO: could add l2_packet_sendmsg that allows fragments to avoid - * extra copy here */ - - if (wpa_s->l2_preauth == NULL) - return -1; - - msglen = sizeof(*ethhdr) + sizeof(*hdr) + len; - msg = malloc(msglen); - if (msg == NULL) - return -1; - - ethhdr = (struct l2_ethhdr *) msg; - memcpy(ethhdr->h_dest, wpa_s->preauth_bssid, ETH_ALEN); - memcpy(ethhdr->h_source, wpa_s->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_RSN_PREAUTH); - - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - hdr->version = wpa_s->conf->eapol_version; - hdr->type = type; - hdr->length = htons(len); - - memcpy((u8 *) (hdr + 1), buf, len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL (preauth)", msg, msglen); - res = l2_packet_send(wpa_s->l2_preauth, msg, msglen); - free(msg); - return res; -} - - -/** - * wpa_eapol_set_wep_key - set WEP key for the driver - * @ctx: pointer to wpa_supplicant data - * @unicast: 1 = individual unicast key, 0 = broadcast key - * @keyidx: WEP key index (0..3) - * @key: pointer to key data - * @keylen: key length in bytes - * - * Returns 0 on success or < 0 on error. - */ -static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, - u8 *key, size_t keylen) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_s->keys_cleared = 0; - return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, - unicast ? wpa_s->bssid : - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, unicast, (u8 *) "", 0, key, keylen); -} - - -/* Configure default/group WEP key for static WEP */ -static int wpa_set_wep_key(void *ctx, int set_tx, int keyidx, const u8 *key, - size_t keylen) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_s->keys_cleared = 0; - return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, set_tx, (u8 *) "", 0, key, keylen); -} - - -static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - u8 key[32]; - size_t keylen; - wpa_alg alg; - u8 seq[6] = { 0 }; - - /* IBSS/WPA-None uses only one key (Group) for both receiving and - * sending unicast and multicast packets. */ - - if (ssid->mode != IEEE80211_MODE_IBSS) { - wpa_printf(MSG_INFO, "WPA: Invalid mode %d (not IBSS/ad-hoc) " - "for WPA-None", ssid->mode); - return -1; - } - - if (!ssid->psk_set) { - wpa_printf(MSG_INFO, "WPA: No PSK configured for WPA-None"); - return -1; - } - - switch (wpa_s->group_cipher) { - case WPA_CIPHER_CCMP: - memcpy(key, ssid->psk, 16); - keylen = 16; - alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - /* WPA-None uses the same Michael MIC key for both TX and RX */ - memcpy(key, ssid->psk, 16 + 8); - memcpy(key + 16 + 8, ssid->psk + 16, 8); - keylen = 32; - alg = WPA_ALG_TKIP; - break; - default: - wpa_printf(MSG_INFO, "WPA: Invalid group cipher %d for " - "WPA-None", wpa_s->group_cipher); - return -1; - } - - /* TODO: should actually remember the previously used seq#, both for TX - * and RX from each STA.. */ - - return wpa_drv_set_key(wpa_s, alg, (u8 *) "\xff\xff\xff\xff\xff\xff", - 0, 1, seq, 6, key, keylen); -} - - -void wpa_supplicant_notify_eapol_done(void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete"); - eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); - wpa_supplicant_cancel_auth_timeout(wpa_s); -} - - -static struct wpa_blacklist * -wpa_blacklist_get(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct wpa_blacklist *e; - - e = wpa_s->blacklist; - while (e) { - if (memcmp(e->bssid, bssid, ETH_ALEN) == 0) - return e; - e = e->next; - } - - return NULL; -} - - -static int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct wpa_blacklist *e; - - e = wpa_blacklist_get(wpa_s, bssid); - if (e) { - e->count++; - wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count " - "incremented to %d", - MAC2STR(bssid), e->count); - return 0; - } - - e = malloc(sizeof(*e)); - if (e == NULL) - return -1; - memset(e, 0, sizeof(*e)); - memcpy(e->bssid, bssid, ETH_ALEN); - e->count = 1; - e->next = wpa_s->blacklist; - wpa_s->blacklist = e; - wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist", - MAC2STR(bssid)); - - return 0; -} - - -static int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct wpa_blacklist *e, *prev = NULL; - - e = wpa_s->blacklist; - while (e) { - if (memcmp(e->bssid, bssid, ETH_ALEN) == 0) { - if (prev == NULL) { - wpa_s->blacklist = e->next; - } else { - prev->next = e->next; - } - wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " - "blacklist", MAC2STR(bssid)); - free(e); - return 0; - } - prev = e; - e = e->next; - } - return -1; -} - - -static void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) -{ - struct wpa_blacklist *e, *prev; - - e = wpa_s->blacklist; - wpa_s->blacklist = NULL; - while (e) { - prev = e; - e = e->next; - wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " - "blacklist (clear)", MAC2STR(prev->bssid)); - free(prev); - } -} - - -const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len) -{ - static char ssid_txt[MAX_SSID_LEN + 1]; - char *pos; - - if (ssid_len > MAX_SSID_LEN) - ssid_len = MAX_SSID_LEN; - 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 wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) -{ - wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", - sec, usec); - eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); - eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); -} - - -void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) -{ - wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request"); - eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); -} - - -static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", - MAC2STR(wpa_s->bssid)); - wpa_blacklist_add(wpa_s, wpa_s->bssid); - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); -} - - -void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, - int sec, int usec) -{ - wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " - "%d usec", sec, usec); - eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); - eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL); -} - - -void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) -{ - wpa_msg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout"); - eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); - wpa_blacklist_del(wpa_s, wpa_s->bssid); -} - - -static void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) -{ - struct eapol_config eapol_conf; - struct wpa_ssid *ssid = wpa_s->current_ssid; - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); - } - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) - eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); - else - eapol_sm_notify_portControl(wpa_s->eapol, Auto); - - memset(&eapol_conf, 0, sizeof(eapol_conf)); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - eapol_conf.accept_802_1x_keys = 1; - eapol_conf.required_keys = 0; - if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) { - eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST; - } - if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) { - eapol_conf.required_keys |= - EAPOL_REQUIRE_KEY_BROADCAST; - } - } - eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; - eapol_conf.workaround = ssid->eap_workaround; - eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf); -} - - -static void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - int i; - - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) - wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; - else - wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; - free(wpa_s->ap_wpa_ie); - wpa_s->ap_wpa_ie = NULL; - wpa_s->ap_wpa_ie_len = 0; - free(wpa_s->ap_rsn_ie); - wpa_s->ap_rsn_ie = NULL; - wpa_s->ap_rsn_ie_len = 0; - free(wpa_s->assoc_wpa_ie); - wpa_s->assoc_wpa_ie = NULL; - wpa_s->assoc_wpa_ie_len = 0; - wpa_s->pairwise_cipher = WPA_CIPHER_NONE; - wpa_s->group_cipher = WPA_CIPHER_NONE; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i] > 5) { - wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; - wpa_s->group_cipher = WPA_CIPHER_WEP104; - break; - } else if (ssid->wep_key_len[i] > 0) { - wpa_s->pairwise_cipher = WPA_CIPHER_WEP40; - wpa_s->group_cipher = WPA_CIPHER_WEP40; - break; - } - } - - wpa_s->cur_pmksa = NULL; -} - - -static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *ssid; - - if (wpa_s->conf->ap_scan == 1) - return 0; - - ssid = wpa_supplicant_get_ssid(wpa_s); - if (ssid == NULL) { - wpa_printf(MSG_INFO, "No network configuration found for the " - "current AP"); - return -1; - } - - wpa_printf(MSG_DEBUG, "Network configuration found for the current " - "AP"); - if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | - WPA_KEY_MGMT_WPA_NONE)) { - u8 wpa_ie[80]; - int wpa_ie_len; - wpa_supplicant_set_suites(wpa_s, NULL, ssid, - wpa_ie, &wpa_ie_len); - } else { - wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); - } - - wpa_s->current_ssid = ssid; - wpa_supplicant_initiate_eapol(wpa_s); - - return 0; -} - - -static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) -{ - scard_deinit(wpa_s->scard); - wpa_s->scard = NULL; - eapol_sm_register_scard_ctx(wpa_s->eapol, NULL); - l2_packet_deinit(wpa_s->l2); - wpa_s->l2 = NULL; - -#ifdef CONFIG_XSUPPLICANT_IFACE - if (wpa_s->dot1x_s > -1) { - close(wpa_s->dot1x_s); - wpa_s->dot1x_s = -1; - } -#endif /* CONFIG_XSUPPLICANT_IFACE */ - - wpa_supplicant_ctrl_iface_deinit(wpa_s); - if (wpa_s->conf != NULL) { - wpa_config_free(wpa_s->conf); - wpa_s->conf = NULL; - } - - free(wpa_s->assoc_wpa_ie); - wpa_s->assoc_wpa_ie = NULL; - - free(wpa_s->ap_wpa_ie); - wpa_s->ap_wpa_ie = NULL; - free(wpa_s->ap_rsn_ie); - wpa_s->ap_rsn_ie = NULL; - - free(wpa_s->confname); - wpa_s->confname = NULL; - - eapol_sm_deinit(wpa_s->eapol); - wpa_s->eapol = NULL; - - rsn_preauth_deinit(wpa_s); - - pmksa_candidate_free(wpa_s); - pmksa_cache_free(wpa_s); - wpa_blacklist_clear(wpa_s); - - free(wpa_s->scan_results); - wpa_s->scan_results = NULL; - wpa_s->num_scan_results = 0; -} - - -static void wpa_clear_keys(struct wpa_supplicant *wpa_s, u8 *addr) -{ - u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff"; - - if (wpa_s->keys_cleared) { - /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have - * timing issues with keys being cleared just before new keys - * are set or just after association or something similar. This - * shows up in group key handshake failing often because of the - * client not receiving the first encrypted packets correctly. - * Skipping some of the extra key clearing steps seems to help - * in completing group key handshake more reliably. */ - wpa_printf(MSG_DEBUG, "No keys have been configured - " - "skip key clearing"); - return; - } - - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0); - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0); - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0); - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0); - if (addr) { - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, - 0); - } - wpa_s->keys_cleared = 1; -} - - -static void wpa_supplicant_stop_countermeasures(void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - - if (wpa_s->countermeasures) { - wpa_s->countermeasures = 0; - wpa_drv_set_countermeasures(wpa_s, 0); - wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped"); - wpa_supplicant_req_scan(wpa_s, 0, 0); - } -} - - -static void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) -{ - wpa_s->wpa_state = WPA_DISCONNECTED; - memset(wpa_s->bssid, 0, ETH_ALEN); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); -} - - -static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) -{ - struct wpa_ie_data ie; - int i; - - if (wpa_parse_wpa_ie(wpa_s, wpa_s->assoc_wpa_ie, - wpa_s->assoc_wpa_ie_len, &ie) < 0 || - ie.pmkid == NULL) - return; - - for (i = 0; i < ie.num_pmkid; i++) { - wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, NULL, - ie.pmkid + i * PMKID_LEN); - if (wpa_s->cur_pmksa) { - eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); - break; - } - } - - wpa_printf(MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from PMKSA " - "cache", wpa_s->cur_pmksa ? "" : "not "); -} - - -static void wpa_supplicant_add_pmkid_candidate(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - if (data == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No data in PMKID candidate event"); - return; - } - wpa_printf(MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR - " index=%d preauth=%d", - MAC2STR(data->pmkid_candidate.bssid), - data->pmkid_candidate.index, - data->pmkid_candidate.preauth); - - if (!data->pmkid_candidate.preauth) { - wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " - "preauth flag"); - return; - } - - pmksa_candidate_add(wpa_s, data->pmkid_candidate.bssid, - data->pmkid_candidate.index); -} - - -static int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) - return 0; - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA && - wpa_s->current_ssid && - !(wpa_s->current_ssid->eapol_flags & - (EAPOL_FLAG_REQUIRE_KEY_UNICAST | - EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) { - /* IEEE 802.1X, but not using dynamic WEP keys (i.e., either - * plaintext or static WEP keys). */ - return 0; - } - - return 1; -} - - -static void wpa_supplicant_associnfo(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - int l, len; - u8 *p; - - wpa_printf(MSG_DEBUG, "Association info event"); - wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies, - data->assoc_info.req_ies_len); - wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies, - data->assoc_info.resp_ies_len); - if (wpa_s->assoc_wpa_ie) { - free(wpa_s->assoc_wpa_ie); - wpa_s->assoc_wpa_ie = NULL; - wpa_s->assoc_wpa_ie_len = 0; - } - - p = data->assoc_info.req_ies; - l = data->assoc_info.req_ies_len; - - /* Go through the IEs and make a copy of the WPA/RSN IE, if present. */ - while (l >= 2) { - len = p[1] + 2; - if (len > l) { - wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info", - p, l); - break; - } - if ((p[0] == GENERIC_INFO_ELEM && p[1] >= 6 && - (memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) || - (p[0] == RSN_INFO_ELEM && p[1] >= 2)) { - wpa_s->assoc_wpa_ie = malloc(len); - if (wpa_s->assoc_wpa_ie == NULL) - break; - wpa_s->assoc_wpa_ie_len = len; - memcpy(wpa_s->assoc_wpa_ie, p, len); - wpa_hexdump(MSG_DEBUG, "assoc_wpa_ie", - wpa_s->assoc_wpa_ie, - wpa_s->assoc_wpa_ie_len); - wpa_find_assoc_pmkid(wpa_s); - break; - } - l -= len; - p += len; - } - - /* WPA/RSN IE from Beacon/ProbeResp */ - free(wpa_s->ap_wpa_ie); - wpa_s->ap_wpa_ie = NULL; - wpa_s->ap_wpa_ie_len = 0; - free(wpa_s->ap_rsn_ie); - wpa_s->ap_rsn_ie = NULL; - wpa_s->ap_rsn_ie_len = 0; - - p = data->assoc_info.beacon_ies; - l = data->assoc_info.beacon_ies_len; - - /* Go through the IEs and make a copy of the WPA/RSN IEs, if present. - */ - while (l >= 2) { - len = p[1] + 2; - if (len > l) { - wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies", - p, l); - break; - } - if (wpa_s->ap_wpa_ie == NULL && - p[0] == GENERIC_INFO_ELEM && p[1] >= 6 && - memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) { - wpa_s->ap_wpa_ie = malloc(len); - if (wpa_s->ap_wpa_ie) { - memcpy(wpa_s->ap_wpa_ie, p, len); - wpa_s->ap_wpa_ie_len = len; - } - } - - if (wpa_s->ap_rsn_ie == NULL && - p[0] == RSN_INFO_ELEM && p[1] >= 2) { - wpa_s->ap_rsn_ie = malloc(len); - if (wpa_s->ap_rsn_ie) { - memcpy(wpa_s->ap_rsn_ie, p, len); - wpa_s->ap_rsn_ie_len = len; - } - - } - - l -= len; - p += len; - } - -} - - -void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event, - union wpa_event_data *data) -{ - int pairwise; - time_t now; - u8 bssid[ETH_ALEN]; - - switch (event) { - case EVENT_ASSOC: - wpa_s->wpa_state = WPA_ASSOCIATED; - wpa_printf(MSG_DEBUG, "Association event - clear replay " - "counter"); - memset(wpa_s->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); - wpa_s->rx_replay_counter_set = 0; - wpa_s->renew_snonce = 1; - if (wpa_drv_get_bssid(wpa_s, bssid) >= 0 && - memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) { - wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: " - "BSSID=" MACSTR, MAC2STR(bssid)); - memcpy(wpa_s->bssid, bssid, ETH_ALEN); - if (wpa_supplicant_dynamic_keys(wpa_s)) { - wpa_clear_keys(wpa_s, bssid); - } - wpa_supplicant_select_config(wpa_s); - } - wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, - MAC2STR(bssid)); - /* Set portEnabled first to FALSE in order to get EAP state - * machine out of the SUCCESS state and eapSuccess cleared. - * Without this, EAPOL PAE state machine may transit to - * AUTHENTICATING state based on obsolete eapSuccess and then - * trigger BE_AUTH to SUCCESS and PAE to AUTHENTICATED without - * ever giving chance to EAP state machine to reset the state. - */ - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); - wpa_s->eapol_received = 0; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - wpa_supplicant_cancel_auth_timeout(wpa_s); - } else { - /* Timeout for receiving the first EAPOL packet */ - wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); - } - break; - case EVENT_DISASSOC: - if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - /* At least Host AP driver and a Prism3 card seemed to - * be generating streams of disconnected events when - * configuring IBSS for WPA-None. Ignore them for now. - */ - wpa_printf(MSG_DEBUG, "Disconnect event - ignore in " - "IBSS/WPA-None mode"); - break; - } - if (wpa_s->wpa_state >= WPA_ASSOCIATED) - wpa_supplicant_req_scan(wpa_s, 0, 100000); - wpa_blacklist_add(wpa_s, wpa_s->bssid); - wpa_supplicant_mark_disassoc(wpa_s); - wpa_msg(wpa_s, MSG_INFO, "Disconnect event - remove keys"); - if (wpa_supplicant_dynamic_keys(wpa_s)) { - wpa_s->keys_cleared = 0; - wpa_clear_keys(wpa_s, wpa_s->bssid); - } - break; - case EVENT_MICHAEL_MIC_FAILURE: - wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected"); - pairwise = (data && data->michael_mic_failure.unicast); - wpa_supplicant_key_request(wpa_s, 1, pairwise); - time(&now); - if (wpa_s->last_michael_mic_error && - now - wpa_s->last_michael_mic_error <= 60) { - /* initialize countermeasures */ - wpa_s->countermeasures = 1; - wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures " - "started"); - - /* Need to wait for completion of request frame. We do - * not get any callback for the message completion, so - * just wait a short while and hope for the best. */ - usleep(10000); - - wpa_drv_set_countermeasures(wpa_s, 1); - wpa_supplicant_deauthenticate( - wpa_s, REASON_MICHAEL_MIC_FAILURE); - eloop_cancel_timeout( - wpa_supplicant_stop_countermeasures, wpa_s, - NULL); - eloop_register_timeout( - 60, 0, wpa_supplicant_stop_countermeasures, - wpa_s, NULL); - /* TODO: mark the AP rejected for 60 second. STA is - * allowed to associate with another AP.. */ - } - wpa_s->last_michael_mic_error = now; - break; - case EVENT_SCAN_RESULTS: - wpa_supplicant_scan_results(wpa_s); - break; - case EVENT_ASSOCINFO: - wpa_supplicant_associnfo(wpa_s, data); - break; - case EVENT_INTERFACE_STATUS: - if (strcmp(wpa_s->ifname, data->interface_status.ifname) != 0) - break; - switch (data->interface_status.ievent) { - case EVENT_INTERFACE_ADDED: - if (!wpa_s->interface_removed) - break; - wpa_s->interface_removed = 0; - wpa_printf(MSG_DEBUG, "Configured interface was " - "added."); - if (wpa_supplicant_driver_init(wpa_s, 1) < 0) { - wpa_printf(MSG_INFO, "Failed to initialize " - "the driver after interface was " - "added."); - } - break; - case EVENT_INTERFACE_REMOVED: - wpa_printf(MSG_DEBUG, "Configured interface was " - "removed."); - wpa_s->interface_removed = 1; - wpa_supplicant_mark_disassoc(wpa_s); - l2_packet_deinit(wpa_s->l2); - wpa_s->l2 = NULL; - break; - } - break; - case EVENT_PMKID_CANDIDATE: - wpa_supplicant_add_pmkid_candidate(wpa_s, data); - break; - default: - wpa_printf(MSG_INFO, "Unknown event %d", event); - break; - } -} - - -static void wpa_supplicant_terminate(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - for (wpa_s = wpa_s->head; wpa_s; wpa_s = wpa_s->next) { - wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", - sig); - } - eloop_terminate(); -} - - -int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) -{ - struct wpa_config *conf; - int reconf_ctrl; - if (wpa_s->confname == NULL) - return -1; - conf = wpa_config_read(wpa_s->confname); - if (conf == NULL) { - wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration " - "file '%s' - exiting", wpa_s->confname); - return -1; - } - - reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface - || (conf->ctrl_interface && wpa_s->conf->ctrl_interface && - strcmp(conf->ctrl_interface, wpa_s->conf->ctrl_interface) - != 0); - - if (reconf_ctrl) - wpa_supplicant_ctrl_iface_deinit(wpa_s); - - wpa_s->current_ssid = NULL; - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - rsn_preauth_deinit(wpa_s); - wpa_config_free(wpa_s->conf); - wpa_s->conf = conf; - if (reconf_ctrl) - wpa_supplicant_ctrl_iface_init(wpa_s); - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); - return 0; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void wpa_supplicant_reconfig(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig); - for (wpa_s = wpa_s->head; wpa_s; wpa_s = wpa_s->next) { - if (wpa_supplicant_reload_configuration(wpa_s) < 0) { - eloop_terminate(); - } - } -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *ssid; - union wpa_event_data data; - - ssid = wpa_supplicant_get_ssid(wpa_s); - if (ssid == NULL) - return; - - wpa_printf(MSG_DEBUG, "Already associated with a configured network - " - "generating associated event"); - memset(&data, 0, sizeof(data)); - wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); -} - - -void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - struct wpa_ssid *ssid; - - if (wpa_s->conf->ap_scan == 0) { - wpa_supplicant_gen_assoc_event(wpa_s); - return; - } - - if (wpa_s->conf->ap_scan == 2) { - ssid = wpa_s->conf->ssid; - if (ssid == NULL) - return; - wpa_supplicant_associate(wpa_s, NULL, ssid); - return; - } - - if (wpa_s->wpa_state == WPA_DISCONNECTED) - wpa_s->wpa_state = WPA_SCANNING; - - ssid = wpa_s->conf->ssid; - if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) { - while (ssid) { - if (ssid == wpa_s->prev_scan_ssid) { - ssid = ssid->next; - break; - } - ssid = ssid->next; - } - } - while (ssid) { - if (ssid->scan_ssid) - break; - ssid = ssid->next; - } - - wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", - ssid ? "specific": "broadcast"); - if (ssid) { - wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", - ssid->ssid, ssid->ssid_len); - wpa_s->prev_scan_ssid = ssid; - } else - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; - - if (wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL, - ssid ? ssid->ssid_len : 0)) { - wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); - wpa_supplicant_req_scan(wpa_s, 10, 0); - } -} - - -static wpa_cipher cipher_suite2driver(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_NONE: - return CIPHER_NONE; - case WPA_CIPHER_WEP40: - return CIPHER_WEP40; - case WPA_CIPHER_WEP104: - return CIPHER_WEP104; - case WPA_CIPHER_CCMP: - return CIPHER_CCMP; - case WPA_CIPHER_TKIP: - default: - return CIPHER_TKIP; - } -} - - -static wpa_key_mgmt key_mgmt2driver(int key_mgmt) -{ - switch (key_mgmt) { - case WPA_KEY_MGMT_NONE: - return KEY_MGMT_NONE; - case WPA_KEY_MGMT_IEEE8021X_NO_WPA: - return KEY_MGMT_802_1X_NO_WPA; - case WPA_KEY_MGMT_IEEE8021X: - return KEY_MGMT_802_1X; - case WPA_KEY_MGMT_WPA_NONE: - return KEY_MGMT_WPA_NONE; - case WPA_KEY_MGMT_PSK: - default: - return KEY_MGMT_PSK; - } -} - - -static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid, - struct wpa_ie_data *ie) { - if (wpa_s->assoc_wpa_ie == NULL) - return -1; - - if (wpa_parse_wpa_ie(wpa_s, wpa_s->assoc_wpa_ie, - wpa_s->assoc_wpa_ie_len, ie)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE from " - "association info"); - return -1; - } - - wpa_printf(MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set cipher " - "suites"); - if (!(ie->group_cipher & ssid->group_cipher)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group " - "cipher 0x%x (mask 0x%x) - reject", - ie->group_cipher, ssid->group_cipher); - return -1; - } - if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise " - "cipher 0x%x (mask 0x%x) - reject", - ie->pairwise_cipher, ssid->pairwise_cipher); - return -1; - } - if (!(ie->key_mgmt & ssid->key_mgmt)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key " - "management 0x%x (mask 0x%x) - reject", - ie->key_mgmt, ssid->key_mgmt); - return -1; - } - - return 0; -} - - -static int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid, - u8 *wpa_ie, int *wpa_ie_len) -{ - struct wpa_ie_data ie; - int sel, proto; - u8 *ap_ie; - size_t ap_ie_len; - - if (bss && bss->rsn_ie_len && (ssid->proto & WPA_PROTO_RSN)) { - wpa_msg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); - proto = WPA_PROTO_RSN; - ap_ie = bss->rsn_ie; - ap_ie_len = bss->rsn_ie_len; - } else if (bss) { - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); - proto = WPA_PROTO_WPA; - ap_ie = bss->wpa_ie; - ap_ie_len = bss->wpa_ie_len; - } else { - if (ssid->proto & WPA_PROTO_RSN) - proto = WPA_PROTO_RSN; - else - proto = WPA_PROTO_WPA; - ap_ie = NULL; - ap_ie_len = 0; - if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) { - memset(&ie, 0, sizeof(ie)); - ie.group_cipher = ssid->group_cipher; - ie.pairwise_cipher = ssid->pairwise_cipher; - ie.key_mgmt = ssid->key_mgmt; - wpa_printf(MSG_DEBUG, "WPA: Set cipher suites based " - "on configuration"); - } - } - - if (ap_ie && wpa_parse_wpa_ie(wpa_s, ap_ie, ap_ie_len, &ie)) { - wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to parse WPA IE for " - "the selected BSS."); - return -1; - } - wpa_printf(MSG_DEBUG, "WPA: Selected cipher suites: group %d " - "pairwise %d key_mgmt %d", - ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt); - - wpa_s->proto = proto; - - free(wpa_s->ap_wpa_ie); - wpa_s->ap_wpa_ie = NULL; - wpa_s->ap_wpa_ie_len = 0; - if (bss && bss->wpa_ie_len) { - wpa_s->ap_wpa_ie = malloc(bss->wpa_ie_len); - if (wpa_s->ap_wpa_ie == NULL) { - wpa_printf(MSG_INFO, "WPA: malloc failed"); - return -1; - } - memcpy(wpa_s->ap_wpa_ie, bss->wpa_ie, bss->wpa_ie_len); - wpa_s->ap_wpa_ie_len = bss->wpa_ie_len; - } - - free(wpa_s->ap_rsn_ie); - wpa_s->ap_rsn_ie = NULL; - wpa_s->ap_rsn_ie_len = 0; - if (bss && bss->rsn_ie_len) { - wpa_s->ap_rsn_ie = malloc(bss->rsn_ie_len); - if (wpa_s->ap_rsn_ie == NULL) { - wpa_printf(MSG_INFO, "WPA: malloc failed"); - return -1; - } - memcpy(wpa_s->ap_rsn_ie, bss->rsn_ie, bss->rsn_ie_len); - wpa_s->ap_rsn_ie_len = bss->rsn_ie_len; - } - - sel = ie.group_cipher & ssid->group_cipher; - if (sel & WPA_CIPHER_CCMP) { - wpa_s->group_cipher = WPA_CIPHER_CCMP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP"); - } else if (sel & WPA_CIPHER_TKIP) { - wpa_s->group_cipher = WPA_CIPHER_TKIP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP"); - } else if (sel & WPA_CIPHER_WEP104) { - wpa_s->group_cipher = WPA_CIPHER_WEP104; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP104"); - } else if (sel & WPA_CIPHER_WEP40) { - wpa_s->group_cipher = WPA_CIPHER_WEP40; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40"); - } else { - wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher."); - return -1; - } - - sel = ie.pairwise_cipher & ssid->pairwise_cipher; - if (sel & WPA_CIPHER_CCMP) { - wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP"); - } else if (sel & WPA_CIPHER_TKIP) { - wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP"); - } else if (sel & WPA_CIPHER_NONE) { - wpa_s->pairwise_cipher = WPA_CIPHER_NONE; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE"); - } else { - wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " - "cipher."); - return -1; - } - - sel = ie.key_mgmt & ssid->key_mgmt; - if (sel & WPA_KEY_MGMT_IEEE8021X) { - wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X"); - } else if (sel & WPA_KEY_MGMT_PSK) { - wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK"); - } else if (sel & WPA_KEY_MGMT_WPA_NONE) { - wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE"); - } else { - wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated " - "key management type."); - return -1; - } - - *wpa_ie_len = wpa_gen_wpa_ie(wpa_s, wpa_ie); - if (*wpa_ie_len < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE."); - return -1; - } - wpa_hexdump(MSG_DEBUG, "WPA: Own WPA IE", wpa_ie, *wpa_ie_len); - if (wpa_s->assoc_wpa_ie == NULL) { - /* - * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets - * the correct version of the IE even if PMKSA caching is - * aborted (which would remove PMKID from IE generation). - */ - wpa_s->assoc_wpa_ie = malloc(*wpa_ie_len); - if (wpa_s->assoc_wpa_ie) { - memcpy(wpa_s->assoc_wpa_ie, wpa_ie, *wpa_ie_len); - wpa_s->assoc_wpa_ie_len = *wpa_ie_len; - } - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { - wpa_s->pmk_len = PMK_LEN; - memcpy(wpa_s->pmk, ssid->psk, PMK_LEN); - } else if (wpa_s->cur_pmksa) { - wpa_s->pmk_len = wpa_s->cur_pmksa->pmk_len; - memcpy(wpa_s->pmk, wpa_s->cur_pmksa->pmk, wpa_s->pmk_len); - } else { - wpa_s->pmk_len = PMK_LEN; - memset(wpa_s->pmk, 0, PMK_LEN); -#ifdef CONFIG_XSUPPLICANT_IFACE - wpa_s->ext_pmk_received = 0; -#endif /* CONFIG_XSUPPLICANT_IFACE */ - } - - return 0; -} - - -static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid) -{ - u8 wpa_ie[80]; - int wpa_ie_len; - int use_crypt; - int algs = AUTH_ALG_OPEN_SYSTEM; - int cipher_pairwise, cipher_group; - struct wpa_driver_associate_params params; - int wep_keys_set = 0; - struct wpa_driver_capa capa; - - wpa_s->reassociate = 0; - if (bss) { - wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR - " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid), - wpa_ssid_txt(ssid->ssid, ssid->ssid_len), bss->freq); - memset(wpa_s->bssid, 0, ETH_ALEN); - } else { - wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - } - wpa_supplicant_cancel_scan(wpa_s); - - /* Starting new association, so clear the possibly used WPA IE from the - * previous association. */ - free(wpa_s->assoc_wpa_ie); - wpa_s->assoc_wpa_ie = NULL; - wpa_s->assoc_wpa_ie_len = 0; - - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if (ssid->leap) { - if (ssid->non_leap == 0) - algs = AUTH_ALG_LEAP; - else - algs |= AUTH_ALG_LEAP; - } - } - wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs); - if (ssid->auth_alg) { - algs = 0; - if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) - algs |= AUTH_ALG_OPEN_SYSTEM; - if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) - algs |= AUTH_ALG_SHARED_KEY; - if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) - algs |= AUTH_ALG_LEAP; - wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x", - algs); - } - wpa_drv_set_auth_alg(wpa_s, algs); - - if (bss && (bss->wpa_ie_len || bss->rsn_ie_len) && - (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) { - wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, bss->bssid, NULL); - if (wpa_s->cur_pmksa) { - wpa_hexdump(MSG_DEBUG, "RSN: PMKID", - wpa_s->cur_pmksa->pmkid, PMKID_LEN); - eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); - } - if (wpa_supplicant_set_suites(wpa_s, bss, ssid, - wpa_ie, &wpa_ie_len)) { - wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " - "management and encryption suites"); - return; - } - } else if (ssid->key_mgmt & - (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | - WPA_KEY_MGMT_WPA_NONE)) { - if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, - wpa_ie, &wpa_ie_len)) { - wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " - "management and encryption suites (no scan " - "results)"); - return; - } - } else { - wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); - wpa_ie_len = 0; - } - - wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); - use_crypt = 1; - cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher); - cipher_group = cipher_suite2driver(wpa_s->group_cipher); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - int i; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) - use_crypt = 0; - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) { - use_crypt = 1; - wep_keys_set = 1; - wpa_set_wep_key(wpa_s, - i == ssid->wep_tx_keyidx, - i, ssid->wep_key[i], - ssid->wep_key_len[i]); - } - } - } - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if ((ssid->eapol_flags & - (EAPOL_FLAG_REQUIRE_KEY_UNICAST | - EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 && - !wep_keys_set) { - use_crypt = 0; - } else { - /* Assume that dynamic WEP-104 keys will be used and - * set cipher suites in order for drivers to expect - * encryption. */ - cipher_pairwise = cipher_group = CIPHER_WEP104; - } - } - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - /* Set the key before (and later after) association */ - wpa_supplicant_set_wpa_none_key(wpa_s, ssid); - } - - wpa_drv_set_drop_unencrypted(wpa_s, use_crypt); - wpa_s->wpa_state = WPA_ASSOCIATING; - memset(¶ms, 0, sizeof(params)); - if (bss) { - params.bssid = bss->bssid; - params.ssid = bss->ssid; - params.ssid_len = bss->ssid_len; - params.freq = bss->freq; - } else { - params.ssid = ssid->ssid; - params.ssid_len = ssid->ssid_len; - } - params.wpa_ie = wpa_ie; - params.wpa_ie_len = wpa_ie_len; - params.pairwise_suite = cipher_pairwise; - params.group_suite = cipher_group; - params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt); - params.auth_alg = algs; - params.mode = ssid->mode; - if (wpa_drv_associate(wpa_s, ¶ms) < 0) { - wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " - "failed"); - /* try to continue anyway; new association will be tried again - * after timeout */ - } - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - /* Set the key after the association just in case association - * cleared the previously configured key. */ - wpa_supplicant_set_wpa_none_key(wpa_s, ssid); - /* No need to timeout authentication since there is no key - * management. */ - wpa_supplicant_cancel_auth_timeout(wpa_s); - } else { - /* Timeout for IEEE 802.11 authentication and association */ - wpa_supplicant_req_auth_timeout(wpa_s, 5, 0); - } - - if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 && - capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) { - /* Set static WEP keys again */ - int i; - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) { - wpa_set_wep_key(wpa_s, - i == ssid->wep_tx_keyidx, - i, ssid->wep_key[i], - ssid->wep_key_len[i]); - } - } - } - - wpa_s->current_ssid = ssid; - wpa_supplicant_initiate_eapol(wpa_s); -} - - -void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, - int reason_code) -{ - u8 *addr = NULL; - wpa_s->wpa_state = WPA_DISCONNECTED; - if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) { - wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code); - addr = wpa_s->bssid; - } - wpa_clear_keys(wpa_s, addr); - wpa_s->current_ssid = NULL; - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); -} - - -void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, - int reason_code) -{ - u8 *addr = NULL; - wpa_s->wpa_state = WPA_DISCONNECTED; - if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) { - wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, reason_code); - addr = wpa_s->bssid; - } - wpa_clear_keys(wpa_s, addr); - wpa_s->current_ssid = NULL; - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); -} - - -static void wpa_supplicant_imsi_identity(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - int aka = 0; - u8 *pos = ssid->eap_methods; - - while (pos && *pos != EAP_TYPE_NONE) { - if (*pos == EAP_TYPE_AKA) { - aka = 1; - break; - } - pos++; - } - - if (ssid->identity == NULL && wpa_s->imsi) { - ssid->identity = malloc(1 + wpa_s->imsi_len); - if (ssid->identity) { - ssid->identity[0] = aka ? '0' : '1'; - memcpy(ssid->identity + 1, wpa_s->imsi, - wpa_s->imsi_len); - ssid->identity_len = 1 + wpa_s->imsi_len; - wpa_hexdump_ascii(MSG_DEBUG, "permanent identity from " - "IMSI", ssid->identity, - ssid->identity_len); - } - } -} - - -static void wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - char buf[100]; - size_t len; - - if (ssid->pcsc == NULL) - return; - if (wpa_s->scard != NULL) { - wpa_supplicant_imsi_identity(wpa_s, ssid); - return; - } - wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM - " - "initialize PCSC"); - wpa_s->scard = scard_init(SCARD_TRY_BOTH, ssid->pin); - if (wpa_s->scard == NULL) { - wpa_printf(MSG_WARNING, "Failed to initialize SIM " - "(pcsc-lite)"); - /* TODO: what to do here? */ - return; - } - eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); - - len = sizeof(buf); - if (scard_get_imsi(wpa_s->scard, buf, &len)) { - wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); - /* TODO: what to do here? */ - return; - } - - wpa_hexdump_ascii(MSG_DEBUG, "IMSI", (u8 *) buf, len); - free(wpa_s->imsi); - wpa_s->imsi = malloc(len); - if (wpa_s->imsi) { - memcpy(wpa_s->imsi, buf, len); - wpa_s->imsi_len = len; - wpa_supplicant_imsi_identity(wpa_s, ssid); - } -} - - -static struct wpa_scan_result * -wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, - struct wpa_scan_result *results, int num, - struct wpa_ssid **selected_ssid) -{ - struct wpa_ssid *ssid; - struct wpa_scan_result *bss, *selected = NULL; - int i; - struct wpa_blacklist *e; - - wpa_printf(MSG_DEBUG, "Selecting BSS from priority group %d", - group->priority); - - bss = NULL; - ssid = NULL; - /* First, try to find WPA-enabled AP */ - for (i = 0; i < num && !selected; i++) { - bss = &results[i]; - wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " - "wpa_ie_len=%lu rsn_ie_len=%lu", - i, MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, bss->ssid_len), - (unsigned long) bss->wpa_ie_len, - (unsigned long) bss->rsn_ie_len); - if ((e = wpa_blacklist_get(wpa_s, bss->bssid)) && - e->count > 1) { - wpa_printf(MSG_DEBUG, " skip - blacklisted"); - continue; - } - - if (bss->wpa_ie_len == 0 && bss->rsn_ie_len == 0) { - wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE"); - continue; - } - - for (ssid = group; ssid; ssid = ssid->pnext) { - struct wpa_ie_data ie; - if (bss->ssid_len != ssid->ssid_len || - memcmp(bss->ssid, ssid->ssid, - bss->ssid_len) != 0) { - wpa_printf(MSG_DEBUG, " skip - " - "SSID mismatch"); - continue; - } - if (ssid->bssid_set && - memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, " skip - " - "BSSID mismatch"); - continue; - } - if (!(((ssid->proto & WPA_PROTO_RSN) && - wpa_parse_wpa_ie(wpa_s, bss->rsn_ie, - bss->rsn_ie_len, &ie) == 0) || - ((ssid->proto & WPA_PROTO_WPA) && - wpa_parse_wpa_ie(wpa_s, bss->wpa_ie, - bss->wpa_ie_len, &ie) == 0))) { - wpa_printf(MSG_DEBUG, " skip - " - "could not parse WPA/RSN IE"); - continue; - } - if (!(ie.proto & ssid->proto)) { - wpa_printf(MSG_DEBUG, " skip - " - "proto mismatch"); - continue; - } - if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { - wpa_printf(MSG_DEBUG, " skip - " - "PTK cipher mismatch"); - continue; - } - if (!(ie.group_cipher & ssid->group_cipher)) { - wpa_printf(MSG_DEBUG, " skip - " - "GTK cipher mismatch"); - continue; - } - if (!(ie.key_mgmt & ssid->key_mgmt)) { - wpa_printf(MSG_DEBUG, " skip - " - "key mgmt mismatch"); - continue; - } - - selected = bss; - *selected_ssid = ssid; - wpa_printf(MSG_DEBUG, " selected"); - break; - } - } - - /* If no WPA-enabled AP found, try to find non-WPA AP, if configuration - * allows this. */ - for (i = 0; i < num && !selected; i++) { - bss = &results[i]; - if ((e = wpa_blacklist_get(wpa_s, bss->bssid)) && - e->count > 1) { - continue; - } - for (ssid = group; ssid; ssid = ssid->pnext) { - if (bss->ssid_len == ssid->ssid_len && - memcmp(bss->ssid, ssid->ssid, bss->ssid_len) == 0 - && - (!ssid->bssid_set || - memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) && - ((ssid->key_mgmt & WPA_KEY_MGMT_NONE) || - (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA))) - { - selected = bss; - *selected_ssid = ssid; - wpa_printf(MSG_DEBUG, " selected non-WPA AP " - MACSTR " ssid='%s'", - MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, - bss->ssid_len)); - break; - } - } - } - - return selected; -} - - -static int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s) -{ -#define SCAN_AP_LIMIT 128 - struct wpa_scan_result *results, *tmp; - int num; - - results = malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result)); - if (results == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate memory for scan " - "results"); - return -1; - } - - num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT); - wpa_printf(MSG_DEBUG, "Scan results: %d", num); - if (num < 0) { - wpa_printf(MSG_DEBUG, "Failed to get scan results"); - free(results); - return -1; - } - if (num > SCAN_AP_LIMIT) { - wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)", - num, SCAN_AP_LIMIT); - num = SCAN_AP_LIMIT; - } - - /* Free unneeded memory for unused scan result entries */ - tmp = realloc(results, num * sizeof(struct wpa_scan_result)); - if (tmp || num == 0) { - results = tmp; - } - - free(wpa_s->scan_results); - wpa_s->scan_results = results; - wpa_s->num_scan_results = num; - - return 0; -} - - -static void wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s) -{ - int num, prio; - struct wpa_scan_result *selected = NULL; - struct wpa_ssid *ssid; - struct wpa_scan_result *results; - - if (wpa_supplicant_get_scan_results(wpa_s) < 0) { - wpa_printf(MSG_DEBUG, "Failed to get scan results - try " - "scanning again"); - wpa_supplicant_req_scan(wpa_s, 1, 0); - return; - } - results = wpa_s->scan_results; - num = wpa_s->num_scan_results; - - while (selected == NULL) { - for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { - selected = wpa_supplicant_select_bss( - wpa_s, wpa_s->conf->pssid[prio], results, num, - &ssid); - if (selected) - break; - } - - if (selected == NULL && wpa_s->blacklist) { - wpa_printf(MSG_DEBUG, "No APs found - clear blacklist " - "and try again"); - wpa_blacklist_clear(wpa_s); - } else if (selected == NULL) { - break; - } - } - - if (selected) { - if (wpa_s->reassociate || - memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0) { - wpa_supplicant_scard_init(wpa_s, ssid); - wpa_supplicant_associate(wpa_s, selected, ssid); - } else { - wpa_printf(MSG_DEBUG, "Already associated with the " - "selected AP."); - } - rsn_preauth_scan_results(wpa_s, results, num); - } else { - wpa_printf(MSG_DEBUG, "No suitable AP found."); - wpa_supplicant_req_scan(wpa_s, 5, 0); - } -} - - -static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) -{ - int i, ret = 0; - struct wpa_scan_result *results, *curr = NULL; - - results = wpa_s->scan_results; - if (results == NULL) { - return -1; - } - - for (i = 0; i < wpa_s->num_scan_results; i++) { - if (memcmp(results[i].bssid, wpa_s->bssid, ETH_ALEN) == 0) { - curr = &results[i]; - break; - } - } - - if (curr) { - free(wpa_s->ap_wpa_ie); - wpa_s->ap_wpa_ie_len = curr->wpa_ie_len; - if (curr->wpa_ie_len) { - wpa_s->ap_wpa_ie = malloc(wpa_s->ap_wpa_ie_len); - if (wpa_s->ap_wpa_ie) { - memcpy(wpa_s->ap_wpa_ie, curr->wpa_ie, - curr->wpa_ie_len); - } else { - ret = -1; - } - } else { - wpa_s->ap_wpa_ie = NULL; - } - - free(wpa_s->ap_rsn_ie); - wpa_s->ap_rsn_ie_len = curr->rsn_ie_len; - if (curr->rsn_ie_len) { - wpa_s->ap_rsn_ie = malloc(wpa_s->ap_rsn_ie_len); - if (wpa_s->ap_rsn_ie) { - memcpy(wpa_s->ap_rsn_ie, curr->rsn_ie, - curr->rsn_ie_len); - } else { - ret = -1; - } - } else { - wpa_s->ap_rsn_ie = NULL; - } - } else { - ret = -1; - } - - return ret; -} - - -int wpa_supplicant_get_beacon_ie(struct wpa_supplicant *wpa_s) -{ - if (wpa_get_beacon_ie(wpa_s) == 0) { - return 0; - } - - /* No WPA/RSN IE found in the cached scan results. Try to get updated - * scan results from the driver. */ - if (wpa_supplicant_get_scan_results(wpa_s) < 0) { - return -1; - } - - return wpa_get_beacon_ie(wpa_s); -} - - -#ifdef CONFIG_XSUPPLICANT_IFACE -static void wpa_supplicant_dot1x_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - u8 buf[128]; - int res; - - res = recv(sock, buf, sizeof(buf), 0); - wpa_printf(MSG_DEBUG, "WPA: Receive from dot1x (Xsupplicant) socket " - "==> %d", res); - if (res < 0) { - perror("recv"); - return; - } - - if (res != PMK_LEN) { - wpa_printf(MSG_WARNING, "WPA: Invalid master key length (%d) " - "from dot1x", res); - return; - } - - wpa_hexdump(MSG_DEBUG, "WPA: Master key (dot1x)", buf, PMK_LEN); - if (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - memcpy(wpa_s->pmk, buf, PMK_LEN); - wpa_s->ext_pmk_received = 1; - } else { - wpa_printf(MSG_INFO, "WPA: Not in IEEE 802.1X mode - dropping " - "dot1x PMK update (%d)", wpa_s->key_mgmt); - } -} - - -static int wpa_supplicant_802_1x_init(struct wpa_supplicant *wpa_s) -{ - int s; - struct sockaddr_un addr; - - s = socket(AF_LOCAL, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_LOCAL; - addr.sun_path[0] = '\0'; - snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, - "wpa_supplicant"); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - close(s); - return -1; - } - - wpa_s->dot1x_s = s; - eloop_register_read_sock(s, wpa_supplicant_dot1x_receive, wpa_s, - NULL); - return 0; -} -#endif /* CONFIG_XSUPPLICANT_IFACE */ - - -static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, - const char *name) -{ - int i; - - if (wpa_s == NULL) - return -1; - - if (wpa_supplicant_drivers[0] == NULL) { - wpa_printf(MSG_ERROR, "No driver interfaces build into " - "wpa_supplicant."); - return -1; - } - - if (name == NULL) { - /* default to first driver in the list */ - wpa_s->driver = wpa_supplicant_drivers[0]; - return 0; - } - - for (i = 0; wpa_supplicant_drivers[i]; i++) { - if (strcmp(name, wpa_supplicant_drivers[i]->name) == 0) { - wpa_s->driver = wpa_supplicant_drivers[i]; - return 0; - } - } - - printf("Unsupported driver '%s'.\n", name); - return -1; -} - - -static void wpa_supplicant_fd_workaround(void) -{ - int s, i; - /* When started from pcmcia-cs scripts, wpa_supplicant might start with - * fd 0, 1, and 2 closed. This will cause some issues because many - * places in wpa_supplicant are still printing out to stdout. As a - * workaround, make sure that fd's 0, 1, and 2 are not used for other - * sockets. */ - for (i = 0; i < 3; i++) { - s = open("/dev/null", O_RDWR); - if (s > 2) { - close(s); - break; - } - } -} - - -static int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s, - int wait_for_interface) -{ - static int interface_count = 0; - - for (;;) { - wpa_s->l2 = l2_packet_init(wpa_s->ifname, - wpa_drv_get_mac_addr(wpa_s), - ETH_P_EAPOL, - wpa_supplicant_rx_eapol, wpa_s); - if (wpa_s->l2) - break; - else if (!wait_for_interface) - return -1; - printf("Waiting for interface..\n"); - sleep(5); - } - - if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { - fprintf(stderr, "Failed to get own L2 address\n"); - return -1; - } - - wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR, - MAC2STR(wpa_s->own_addr)); - - if (wpa_drv_set_wpa(wpa_s, 1) < 0) { - fprintf(stderr, "Failed to enable WPA in the driver.\n"); - return -1; - } - - wpa_clear_keys(wpa_s, NULL); - - /* Make sure that TKIP countermeasures are not left enabled (could - * happen if wpa_supplicant is killed during countermeasures. */ - wpa_drv_set_countermeasures(wpa_s, 0); - - wpa_drv_set_drop_unencrypted(wpa_s, 1); - - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; - wpa_supplicant_req_scan(wpa_s, interface_count, 100000); - interface_count++; - - return 0; -} - - -static void usage(void) -{ - int i; - printf("%s\n\n%s\n" - "usage:\n" - " wpa_supplicant [-BddehLqqvw] -i<ifname> -c<config file> " - "[-D<driver>] \\\n" - " [-P<pid file>] " - "[-N -i<ifname> -c<conf> [-D<driver>] ...]\n" - "\n" - "drivers:\n", - wpa_supplicant_version, wpa_supplicant_license); - - for (i = 0; wpa_supplicant_drivers[i]; i++) { - printf(" %s = %s\n", - wpa_supplicant_drivers[i]->name, - wpa_supplicant_drivers[i]->desc); - } - - printf("options:\n" - " -B = run daemon in the background\n" - " -d = increase debugging verbosity (-dd even more)\n" - " -K = include keys (passwords, etc.) in debug output\n" - " -t = include timestamp in debug messages\n" -#ifdef CONFIG_XSUPPLICANT_IFACE -#ifdef IEEE8021X_EAPOL - " -e = use external IEEE 802.1X Supplicant (e.g., " - "xsupplicant)\n" - " (this disables the internal Supplicant)\n" -#endif /* IEEE8021X_EAPOL */ -#endif /* CONFIG_XSUPPLICANT_IFACE */ - " -h = show this help text\n" - " -L = show license (GPL and BSD)\n" - " -q = decrease debugging verbosity (-qq even less)\n" - " -v = show version\n" - " -w = wait for interface to be added, if needed\n" - " -N = start describing new interface\n"); -} - - -static void license(void) -{ - printf("%s\n\n%s\n", - wpa_supplicant_version, wpa_supplicant_full_license); -} - - -static struct wpa_supplicant * wpa_supplicant_alloc(void) -{ - struct wpa_supplicant *wpa_s; - - wpa_s = malloc(sizeof(*wpa_s)); - if (wpa_s == NULL) - return NULL; - memset(wpa_s, 0, sizeof(*wpa_s)); - wpa_s->ctrl_sock = -1; -#ifdef CONFIG_XSUPPLICANT_IFACE - wpa_s->dot1x_s = -1; -#endif /* CONFIG_XSUPPLICANT_IFACE */ - - return wpa_s; -} - - -static int wpa_supplicant_init(struct wpa_supplicant *wpa_s, - const char *confname, const char *driver, - const char *ifname) -{ - wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " - "'%s'", ifname, confname, driver ? driver : "default"); - - if (wpa_supplicant_set_driver(wpa_s, driver) < 0) { - return -1; - } - - if (confname) { - wpa_s->confname = rel2abs_path(confname); - if (wpa_s->confname == NULL) { - wpa_printf(MSG_ERROR, "Failed to get absolute path " - "for configuration file '%s'.", confname); - return -1; - } - wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'", - confname, wpa_s->confname); - wpa_s->conf = wpa_config_read(wpa_s->confname); - if (wpa_s->conf == NULL) { - printf("Failed to read configuration file '%s'.\n", - wpa_s->confname); - return -1; - } - } - - if (wpa_s->conf == NULL || wpa_s->conf->ssid == NULL) { - usage(); - printf("\nNo networks (SSID) configured.\n"); - return -1; - } - - if (ifname == NULL) { - usage(); - printf("\nInterface name is required.\n"); - return -1; - } - if (strlen(ifname) >= sizeof(wpa_s->ifname)) { - printf("Too long interface name '%s'.\n", ifname); - return -1; - } - strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); - - return 0; -} - - -static int wpa_supplicant_init2(struct wpa_supplicant *wpa_s, - int disable_eapol, int wait_for_interface) -{ - const char *ifname; - - wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'", - wpa_s->ifname); - - if (!disable_eapol) { - struct eapol_ctx *ctx; - ctx = malloc(sizeof(*ctx)); - if (ctx == NULL) { - printf("Failed to allocate EAPOL context.\n"); - return -1; - } - memset(ctx, 0, sizeof(*ctx)); - ctx->ctx = wpa_s; - ctx->msg_ctx = wpa_s; - ctx->preauth = 0; - ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; - ctx->eapol_send = wpa_eapol_send; - ctx->set_wep_key = wpa_eapol_set_wep_key; - wpa_s->eapol = eapol_sm_init(ctx); - if (wpa_s->eapol == NULL) { - free(ctx); - printf("Failed to initialize EAPOL state machines.\n"); - return -1; - } - } - - /* RSNA Supplicant Key Management - INITIALIZE */ - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - - /* Initialize driver interface and register driver event handler before - * L2 receive handler so that association events are processed before - * EAPOL-Key packets if both become available for the same select() - * call. */ - wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); - if (wpa_s->drv_priv == NULL) { - fprintf(stderr, "Failed to initialize driver interface\n"); - return -1; - } - - ifname = wpa_drv_get_ifname(wpa_s); - if (ifname && strcmp(ifname, wpa_s->ifname) != 0) { - wpa_printf(MSG_DEBUG, "Driver interface replaced interface " - "name with '%s'", ifname); - strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); - } - - wpa_s->renew_snonce = 1; - if (wpa_supplicant_driver_init(wpa_s, wait_for_interface) < 0) { - return -1; - } - - if (wpa_supplicant_ctrl_iface_init(wpa_s)) { - printf("Failed to initialize control interface '%s'.\n" - "You may have another wpa_supplicant process already " - "running or the file was\n" - "left by an unclean termination of wpa_supplicant in " - "which case you will need\n" - "to manually remove this file before starting " - "wpa_supplicant again.\n", - wpa_s->conf->ctrl_interface); - return -1; - } - -#ifdef CONFIG_XSUPPLICANT_IFACE - if (disable_eapol) - wpa_supplicant_802_1x_init(wpa_s); -#endif /* CONFIG_XSUPPLICANT_IFACE */ - - return 0; -} - - -static void wpa_supplicant_deinit(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->drv_priv) { - if (wpa_drv_set_wpa(wpa_s, 0) < 0) { - fprintf(stderr, "Failed to disable WPA in the " - "driver.\n"); - } - - wpa_drv_set_drop_unencrypted(wpa_s, 0); - wpa_drv_set_countermeasures(wpa_s, 0); - wpa_clear_keys(wpa_s, NULL); - - wpa_drv_deinit(wpa_s); - } - wpa_supplicant_cleanup(wpa_s); -} - - -int main(int argc, char *argv[]) -{ - struct wpa_supplicant *head, *wpa_s; - int c; - const char *confname, *driver, *ifname; - char *pid_file = NULL; - int daemonize = 0, wait_for_interface = 0, disable_eapol = 0, exitcode; - -#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 */ - - head = wpa_s = wpa_supplicant_alloc(); - if (wpa_s == NULL) - return -1; - wpa_s->head = head; - - wpa_supplicant_fd_workaround(); - eloop_init(head); - - ifname = confname = driver = NULL; - - for (;;) { - c = getopt(argc, argv, "Bc:D:dehi:KLNP:qtvw"); - if (c < 0) - break; - switch (c) { - case 'B': - daemonize++; - break; - case 'c': - confname = optarg; - break; - case 'D': - driver = optarg; - break; - case 'd': - wpa_debug_level--; - break; -#ifdef CONFIG_XSUPPLICANT_IFACE -#ifdef IEEE8021X_EAPOL - case 'e': - disable_eapol++; - break; -#endif /* IEEE8021X_EAPOL */ -#endif /* CONFIG_XSUPPLICANT_IFACE */ - case 'h': - usage(); - return -1; - case 'i': - ifname = optarg; - break; - case 'K': - wpa_debug_show_keys++; - break; - case 'L': - license(); - return -1; - case 'P': - pid_file = rel2abs_path(optarg); - break; - case 'q': - wpa_debug_level++; - break; - case 't': - wpa_debug_timestamp++; - break; - case 'v': - printf("%s\n", wpa_supplicant_version); - return -1; - case 'w': - wait_for_interface++; - break; - case 'N': - if (wpa_supplicant_init(wpa_s, confname, driver, - ifname)) - return -1; - wpa_s->next = wpa_supplicant_alloc(); - wpa_s = wpa_s->next; - if (wpa_s == NULL) - return -1; - wpa_s->head = head; - ifname = confname = driver = NULL; - break; - default: - usage(); - return -1; - } - } - - if (wpa_supplicant_init(wpa_s, confname, driver, ifname)) - return -1; - - exitcode = 0; - - if (wait_for_interface && daemonize) { - wpa_printf(MSG_DEBUG, "Daemonize.."); - if (daemon(0, 0)) { - perror("daemon"); - exitcode = -1; - goto cleanup; - } - } - - for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) { - if (wpa_supplicant_init2(wpa_s, disable_eapol, - wait_for_interface)) { - exitcode = -1; - goto cleanup; - } - } - - if (!wait_for_interface && daemonize) { - wpa_printf(MSG_DEBUG, "Daemonize.."); - if (daemon(0, 0)) { - perror("daemon"); - exitcode = -1; - goto cleanup; - } - } - - if (pid_file) { - FILE *f = fopen(pid_file, "w"); - if (f) { - fprintf(f, "%u\n", getpid()); - fclose(f); - } - } - - eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL); - eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL); -#ifndef CONFIG_NATIVE_WINDOWS - eloop_register_signal(SIGHUP, wpa_supplicant_reconfig, NULL); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eloop_run(); - - for (wpa_s = head; wpa_s; wpa_s = wpa_s->next) { - wpa_supplicant_deauthenticate(wpa_s, REASON_DEAUTH_LEAVING); - } - -cleanup: - wpa_s = head; - while (wpa_s) { - struct wpa_supplicant *prev; - wpa_supplicant_deinit(wpa_s); - prev = wpa_s; - wpa_s = wpa_s->next; - free(prev); - } - - eloop_destroy(); - - if (pid_file) { - unlink(pid_file); - free(pid_file); - } - -#ifdef CONFIG_NATIVE_WINDOWS - WSACleanup(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return exitcode; -} diff --git a/contrib/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa_supplicant/wpa_supplicant.conf deleted file mode 100644 index e8be91a19c7b..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant.conf +++ /dev/null @@ -1,505 +0,0 @@ -##### Example wpa_supplicant configuration file ############################### -# Empty lines and lines starting with # are ignored - -# NOTE! This file may contain password information and should probably be made -# readable only by root user on multiuser systems. - -# global configuration (shared by all network blocks) -# -# Interface for separate control program. If this is specified, wpa_supplicant -# will create this directory and a UNIX domain socket for listening to requests -# from external programs (CLI/GUI, etc.) for status information and -# configuration. The socket file will be named based on the interface name, so -# multiple wpa_supplicant processes can be run at the same time if more than -# one interface is used. -# /var/run/wpa_supplicant is the recommended directory for sockets and by -# default, wpa_cli will use it when trying to connect with wpa_supplicant. -ctrl_interface=/var/run/wpa_supplicant - -# Access control for the control interface can be configured by setting the -# directory to allow only members of a group to use sockets. This way, it is -# possible to run wpa_supplicant as root (since it needs to change network -# configuration and open raw sockets) and still allow GUI/CLI components to be -# run as non-root users. However, since the control interface can be used to -# change the network configuration, this access needs to be protected in many -# cases. By default, wpa_supplicant is configured to use gid 0 (root). If you -# want to allow non-root users to use the control interface, add a new group -# and change this value to match with that group. Add users that should have -# control interface access to this group. If this variable is commented out or -# not included in the configuration file, group will not be changed from the -# value it got by default when the directory or socket was created. -# -# This variable can be a group name or gid. -#ctrl_interface_group=wheel -ctrl_interface_group=0 - -# IEEE 802.1X/EAPOL version -# wpa_supplicant was implemented based on IEEE 802-1X-REV-d8 which defines -# EAPOL version 2. However, there are many APs that do not handle the new -# version number correctly (they seem to drop the frames completely). In order -# to make wpa_supplicant interoperate with these APs, the version number is set -# to 1 by default. This configuration value can be used to set it to the new -# version (2). -eapol_version=1 - -# AP scanning/selection -# By default, wpa_supplicant requests driver to perform AP scanning and then -# uses the scan results to select a suitable AP. Another alternative is to -# allow the driver to take care of AP scanning and selection and use -# wpa_supplicant just to process EAPOL frames based on IEEE 802.11 association -# information from the driver. -# 1: wpa_supplicant initiates scanning and AP selection -# 0: driver takes care of scanning, AP selection, and IEEE 802.11 association -# parameters (e.g., WPA IE generation); this mode can also be used with -# non-WPA drivers when using IEEE 802.1X mode; do not try to associate with -# APs (i.e., external program needs to control association) -# 2: like 0, but associate with APs using security policy and SSID (but not -# BSSID); this can be used, e.g., with ndiswrapper and NDIS driver to -# enable operation with hidden SSIDs and optimized roaming; in this mode, -# only the first network block in the configuration file is used and this -# configuration should have explicit security policy (i.e., only one option -# in the lists) for key_mgmt, pairwise, group, proto variables -ap_scan=1 - -# EAP fast re-authentication -# By default, fast re-authentication is enabled for all EAP methods that -# support it. This variable can be used to disable fast re-authentication. -# Normally, there is no need to disable this. -fast_reauth=1 - -# network block -# -# Each network (usually AP's sharing the same SSID) is configured as a separate -# block in this configuration file. The network blocks are in preference order -# (the first match is used). -# -# network block fields: -# -# ssid: SSID (mandatory); either as an ASCII string with double quotation or -# as hex string; network name -# -# scan_ssid: -# 0 = do not scan this SSID with specific Probe Request frames (default) -# 1 = scan with SSID-specific Probe Request frames (this can be used to -# find APs that do not accept broadcast SSID or use multiple SSIDs; -# this will add latency to scanning, so enable this only when needed) -# -# bssid: BSSID (optional); if set, this network block is used only when -# associating with the AP using the configured BSSID -# -# priority: priority group (integer) -# By default, all networks will get same priority group (0). If some of the -# networks are more desirable, this field can be used to change the order in -# which wpa_supplicant goes through the networks when selecting a BSS. The -# priority groups will be iterated in decreasing priority (i.e., the larger the -# priority value, the sooner the network is matched against the scan results). -# Within each priority group, networks will be selected based on security -# policy, signal strength, etc. -# Please note that AP scanning with scan_ssid=1 is not using this priority to -# select the order for scanning. Instead, it uses the order the networks are in -# the configuration file. -# -# mode: IEEE 802.11 operation mode -# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default) -# 1 = IBSS (ad-hoc, peer-to-peer) -# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP) -# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In addition, ap_scan has -# to be set to 2 for IBSS. WPA-None requires following network block options: -# proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or CCMP, but not -# both), and psk must also be set. -# -# proto: list of accepted protocols -# WPA = WPA/IEEE 802.11i/D3.0 -# RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN) -# If not set, this defaults to: WPA RSN -# -# key_mgmt: list of accepted authenticated key management protocols -# WPA-PSK = WPA pre-shared key (this requires 'psk' field) -# WPA-EAP = WPA using EAP authentication (this can use an external -# program, e.g., Xsupplicant, for IEEE 802.1X EAP Authentication -# IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically -# generated WEP keys -# NONE = WPA is not used; plaintext or static WEP could be used -# If not set, this defaults to: WPA-PSK WPA-EAP -# -# auth_alg: list of allowed IEEE 802.11 authentication algorithms -# OPEN = Open System authentication (required for WPA/WPA2) -# SHARED = Shared Key authentication (requires static WEP keys) -# LEAP = LEAP/Network EAP (only used with LEAP) -# If not set, automatic selection is used (Open System with LEAP enabled if -# LEAP is allowed as one of the EAP methods). -# -# pairwise: list of accepted pairwise (unicast) ciphers for WPA -# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] -# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] -# NONE = Use only Group Keys (deprecated, should not be included if APs support -# pairwise keys) -# If not set, this defaults to: CCMP TKIP -# -# group: list of accepted group (broadcast/multicast) ciphers for WPA -# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] -# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] -# WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key -# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11] -# If not set, this defaults to: CCMP TKIP WEP104 WEP40 -# -# psk: WPA preshared key; 256-bit pre-shared key -# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e., -# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be -# generated using the passphrase and SSID). ASCII passphrase must be between -# 8 and 63 characters (inclusive). -# This field is not needed, if WPA-EAP is used. -# Note: Separate tool, wpa_passphrase, can be used to generate 256-bit keys -# from ASCII passphrase. This process uses lot of CPU and wpa_supplicant -# startup and reconfiguration time can be optimized by generating the PSK only -# only when the passphrase or SSID has actually changed. -# -# eapol_flags: IEEE 802.1X/EAPOL options (bit field) -# Dynamic WEP key require for non-WPA mode -# bit0 (1): require dynamically generated unicast WEP key -# bit1 (2): require dynamically generated broadcast WEP key -# (3 = require both keys; default) -# -# Following fields are only used with internal EAP implementation. -# eap: space-separated list of accepted EAP methods -# MD5 = EAP-MD5 (unsecure and does not generate keying material -> -# cannot be used with WPA; to be used as a Phase 2 method -# with EAP-PEAP or EAP-TTLS) -# MSCHAPV2 = EAP-MSCHAPv2 (cannot be used separately with WPA; to be used -# as a Phase 2 method with EAP-PEAP or EAP-TTLS) -# OTP = EAP-OTP (cannot be used separately with WPA; to be used -# as a Phase 2 method with EAP-PEAP or EAP-TTLS) -# GTC = EAP-GTC (cannot be used separately with WPA; to be used -# as a Phase 2 method with EAP-PEAP or EAP-TTLS) -# TLS = EAP-TLS (client and server certificate) -# PEAP = EAP-PEAP (with tunnelled EAP authentication) -# TTLS = EAP-TTLS (with tunnelled EAP or PAP/CHAP/MSCHAP/MSCHAPV2 -# authentication) -# If not set, all compiled in methods are allowed. -# -# identity: Identity string for EAP -# anonymous_identity: Anonymous identity string for EAP (to be used as the -# unencrypted identity with EAP types that support different tunnelled -# identity, e.g., EAP-TTLS) -# password: Password string for EAP -# ca_cert: File path to CA certificate file. This file can have one or more -# trusted CA certificates. If ca_cert is not included, server certificate -# will not be verified. This is insecure and the CA file should always be -# configured. -# client_cert: File path to client certificate file (PEM/DER) -# private_key: File path to client private key file (PEM/DER/PFX) -# When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be -# commented out. Both the private key and certificate will be read from -# the PKCS#12 file in this case. -# private_key_passwd: Password for private key file -# dh_file: File path to DH/DSA parameters file (in PEM format) -# This is an optional configuration file for setting parameters for an -# ephemeral DH key exchange. In most cases, the default RSA -# authentication does not use this configuration. However, it is possible -# setup RSA to use ephemeral DH key exchange. In addition, ciphers with -# DSA keys always use ephemeral DH keys. This can be used to achieve -# forward secrecy. If the file is in DSA parameters format, it will be -# automatically converted into DH params. -# subject_match: Substring to be matched against the subject of the -# authentication server certificate. If this string is set, the server -# sertificate is only accepted if it contains this string in the subject. -# The subject string is in following format: -# /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@example.com -# phase1: Phase1 (outer authentication, i.e., TLS tunnel) parameters -# (string with field-value pairs, e.g., "peapver=0" or -# "peapver=1 peaplabel=1") -# 'peapver' can be used to force which PEAP version (0 or 1) is used. -# 'peaplabel=1' can be used to force new label, "client PEAP encryption", -# to be used during key derivation when PEAPv1 or newer. Most existing -# PEAPv1 implementation seem to be using the old label, "client EAP -# encryption", and wpa_supplicant is now using that as the default value. -# Some servers, e.g., Radiator, may require peaplabel=1 configuration to -# interoperate with PEAPv1; see eap_testing.txt for more details. -# 'peap_outer_success=0' can be used to terminate PEAP authentication on -# tunneled EAP-Success. This is required with some RADIUS servers that -# implement draft-josefsson-pppext-eap-tls-eap-05.txt (e.g., -# Lucent NavisRadius v4.4.0 with PEAP in "IETF Draft 5" mode) -# include_tls_length=1 can be used to force wpa_supplicant to include -# TLS Message Length field in all TLS messages even if they are not -# fragmented. -# sim_min_num_chal=3 can be used to configure EAP-SIM to require three -# challenges (by default, it accepts 2 or 3) -# phase2: Phase2 (inner authentication with TLS tunnel) parameters -# (string with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or -# "autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS) -# Following certificate/private key fields are used in inner Phase2 -# authentication when using EAP-TTLS or EAP-PEAP. -# ca_cert2: File path to CA certificate file. This file can have one or more -# trusted CA certificates. If ca_cert2 is not included, server -# certificate will not be verified. This is insecure and the CA file -# should always be configured. -# client_cert2: File path to client certificate file -# private_key2: File path to client private key file -# private_key2_passwd: Password for private key file -# dh_file2: File path to DH/DSA parameters file (in PEM format) -# subject_match2: Substring to be matched against the subject of the -# authentication server certificate. -# -# EAP-PSK variables: -# eappsk: 16-byte (128-bit, 32 hex digits) pre-shared key in hex format -# nai: user NAI -# server_nai: authentication server NAI -# -# EAP-FAST variables: -# pac_file: File path for the PAC entries. wpa_supplicant will need to be able -# to create this file and write updates to it when PAC is being -# provisioned or refreshed. -# phase1: fast_provisioning=1 option enables in-line provisioning of EAP-FAST -# credentials (PAC) -# -# wpa_supplicant supports number of "EAP workarounds" to work around -# interoperability issues with incorrectly behaving authentication servers. -# These are enabled by default because some of the issues are present in large -# number of authentication servers. Strict EAP conformance mode can be -# configured by disabling workarounds with eap_workaround=0. - -# Example blocks: - -# Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers -network={ - ssid="simple" - psk="very secret passphrase" - priority=5 -} - -# Same as previous, but request SSID-specific scanning (for APs that reject -# broadcast SSID) -network={ - ssid="second ssid" - scan_ssid=1 - psk="very secret passphrase" - priority=2 -} - -# Only WPA-PSK is used. Any valid cipher combination is accepted. -network={ - ssid="example" - proto=WPA - key_mgmt=WPA-PSK - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb - priority=2 -} - -# Only WPA-EAP is used. Both CCMP and TKIP is accepted. An AP that used WEP104 -# or WEP40 as the group cipher will not be accepted. -network={ - ssid="example" - proto=RSN - key_mgmt=WPA-EAP - pairwise=CCMP TKIP - group=CCMP TKIP - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - priority=1 -} - -# EAP-PEAP/MSCHAPv2 configuration for RADIUS servers that use the new peaplabel -# (e.g., Radiator) -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=PEAP - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase1="peaplabel=1" - phase2="auth=MSCHAPV2" - priority=10 -} - -# EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the -# unencrypted use. Real identity is sent only within an encrypted TLS tunnel. -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - priority=2 -} - -# EAP-TTLS/MSCHAPv2 configuration with anonymous identity for the unencrypted -# use. Real identity is sent only within an encrypted TLS tunnel. -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase2="auth=MSCHAPV2" -} - -# WPA-EAP, EAP-TTLS with different CA certificate used for outer and inner -# authentication. -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - # Phase1 / outer authentication - anonymous_identity="anonymous@example.com" - ca_cert="/etc/cert/ca.pem" - # Phase 2 / inner authentication - phase2="autheap=TLS" - ca_cert2="/etc/cert/ca2.pem" - client_cert2="/etc/cer/user.pem" - private_key2="/etc/cer/user.prv" - private_key2_passwd="password" - priority=2 -} - -# Both WPA-PSK and WPA-EAP is accepted. Only CCMP is accepted as pairwise and -# group cipher. -network={ - ssid="example" - bssid=00:11:22:33:44:55 - proto=WPA RSN - key_mgmt=WPA-PSK WPA-EAP - pairwise=CCMP - group=CCMP - psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb -} - -# Special characters in SSID, so use hex string. Default to WPA-PSK, WPA-EAP -# and all valid ciphers. -network={ - ssid=00010203 - psk=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -} - - -# EAP-SIM with a GSM SIM or USIM -network={ - ssid="eap-sim-test" - key_mgmt=WPA-EAP - eap=SIM - pin="1234" - pcsc="" -} - - -# EAP-PSK -network={ - ssid="eap-psk-test" - key_mgmt=WPA-EAP - eap=PSK - identity="eap_psk_user" - eappsk=06b4be19da289f475aa46a33cb793029 - nai="eap_psk_user@example.com" - server_nai="as@example.com" -} - - -# IEEE 802.1X/EAPOL with dynamically generated WEP keys (i.e., no WPA) using -# EAP-TLS for authentication and key generation; require both unicast and -# broadcast WEP keys. -network={ - ssid="1x-test" - key_mgmt=IEEE8021X - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - eapol_flags=3 -} - - -# LEAP with dynamic WEP keys -network={ - ssid="leap-example" - key_mgmt=IEEE8021X - eap=LEAP - identity="user" - password="foobar" -} - -# EAP-FAST with WPA (WPA or WPA2) -network={ - ssid="eap-fast-test" - key_mgmt=WPA-EAP - eap=FAST - anonymous_identity="FAST-000102030405" - identity="username" - password="password" - phase1="fast_provisioning=1" - pac_file="/etc/wpa_supplicant.eap-fast-pac" -} - -# Plaintext connection (no WPA, no IEEE 802.1X) -network={ - ssid="plaintext-test" - key_mgmt=NONE -} - - -# Shared WEP key connection (no WPA, no IEEE 802.1X) -network={ - ssid="static-wep-test" - key_mgmt=NONE - wep_key0="abcde" - wep_key1=0102030405 - wep_key2="1234567890123" - wep_tx_keyidx=0 - priority=5 -} - - -# Shared WEP key connection (no WPA, no IEEE 802.1X) using Shared Key -# IEEE 802.11 authentication -network={ - ssid="static-wep-test2" - key_mgmt=NONE - wep_key0="abcde" - wep_key1=0102030405 - wep_key2="1234567890123" - wep_tx_keyidx=0 - priority=5 - auth_alg=SHARED -} - - -# IBSS/ad-hoc network with WPA-None/TKIP. -network={ - ssid="test adhoc" - mode=1 - proto=WPA - key_mgmt=WPA-NONE - pairwise=NONE - group=TKIP - psk="secret passphrase" -} - - -# Catch all example that allows more or less all configuration modes -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk="very secret passphrase" - eap=TTLS PEAP TLS - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - phase1="peaplabel=0" -} diff --git a/contrib/wpa_supplicant/wpa_supplicant.h b/contrib/wpa_supplicant/wpa_supplicant.h deleted file mode 100644 index e5ad182fc1d6..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef WPA_SUPPLICANT_H -#define WPA_SUPPLICANT_H - -/* Driver wrappers are not supposed to directly touch the internal data - * structure used in wpa_supplicant, so that definition is not provided here. - */ -struct wpa_supplicant; - -typedef enum { - EVENT_ASSOC, EVENT_DISASSOC, EVENT_MICHAEL_MIC_FAILURE, - EVENT_SCAN_RESULTS, EVENT_ASSOCINFO, EVENT_INTERFACE_STATUS, - EVENT_PMKID_CANDIDATE -} wpa_event_type; - -union wpa_event_data { - struct { - /* Optional request information data: IEs included in AssocReq - * and AssocResp. If these are not returned by the driver, - * WPA Supplicant will generate the WPA/RSN IE. */ - u8 *req_ies, *resp_ies; - size_t req_ies_len, resp_ies_len; - - /* Optional Beacon/ProbeResp data: IEs included in Beacon or - * Probe Response frames from the current AP (i.e., the one - * that the client just associated with). This information is - * used to update WPA/RSN IE for the AP. If this field is not - * set, the results from previous scan will be used. If no - * data for the new AP is found, scan results will be requested - * again (without scan request). At this point, the driver is - * expected to provide WPA/RSN IE for the AP (if WPA/WPA2 is - * used). */ - u8 *beacon_ies; /* beacon or probe resp IEs */ - size_t beacon_ies_len; - } assoc_info; - struct { - int unicast; - } michael_mic_failure; - struct { - char ifname[20]; - enum { - EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED - } ievent; - } interface_status; - struct { - u8 bssid[ETH_ALEN]; - int index; /* smaller the index, higher the priority */ - int preauth; - } pmkid_candidate; -}; - -/** - * wpa_supplicant_event - report a driver event for wpa_supplicant - * @wpa_s: pointer to wpa_supplicant data; this is the @ctx variable registered - * with wpa_driver_events_init() - * @event: event type (defined above) - * @data: possible extra data for the event - * - * Driver wrapper code should call this function whenever an event is received - * from the driver. - */ -void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event, - union wpa_event_data *data); - -/** - * wpa_msg - conditional printf for default target and ctrl_iface monitors - * @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(struct wpa_supplicant *wpa_s, int level, char *fmt, ...) -__attribute__ ((format (printf, 3, 4))); - -const char * wpa_ssid_txt(u8 *ssid, size_t ssid_len); - -#endif /* WPA_SUPPLICANT_H */ diff --git a/contrib/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa_supplicant/wpa_supplicant_i.h deleted file mode 100644 index 508fe0912eb3..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant_i.h +++ /dev/null @@ -1,470 +0,0 @@ -#ifndef WPA_SUPPLICANT_I_H -#define WPA_SUPPLICANT_I_H - -#include "driver.h" - -#ifdef EAPOL_TEST -#include <netinet/in.h> - -struct hostapd_radius_server { - struct in_addr addr; - int port; - u8 *shared_secret; - size_t shared_secret_len; -}; -#endif /* EAPOL_TEST */ - -#define PMKID_LEN 16 -struct rsn_pmksa_cache { - struct rsn_pmksa_cache *next; - u8 pmkid[PMKID_LEN]; - u8 pmk[PMK_LEN]; - size_t pmk_len; - time_t expiration; - int akmp; /* WPA_KEY_MGMT_* */ - u8 aa[ETH_ALEN]; -}; - -struct rsn_pmksa_candidate { - struct rsn_pmksa_candidate *next; - u8 bssid[ETH_ALEN]; - int priority; -}; - - -struct wpa_ptk { - u8 mic_key[16]; /* EAPOL-Key MIC Key (MK) */ - u8 encr_key[16]; /* EAPOL-Key Encryption Key (EK) */ - 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; -} __attribute__ ((packed)); - - -struct wpa_blacklist { - struct wpa_blacklist *next; - u8 bssid[ETH_ALEN]; - int count; -}; - - -struct wpa_supplicant { - struct wpa_supplicant *head; - struct wpa_supplicant *next; - struct l2_packet_data *l2; - unsigned char own_addr[ETH_ALEN]; - char ifname[100]; -#ifdef CONFIG_XSUPPLICANT_IFACE - int dot1x_s; /* socket for connection to Xsupplicant */ - int ext_pmk_received; /* 1 = PMK was received from Xsupplicant */ -#endif /* CONFIG_XSUPPLICANT_IFACE */ - - u8 pmk[PMK_LEN]; - size_t pmk_len; - u8 snonce[WPA_NONCE_LEN]; - u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ - struct wpa_ptk ptk, tptk; - int ptk_set, tptk_set; - int renew_snonce; - char *confname; - struct wpa_config *conf; - u8 request_counter[WPA_REPLAY_COUNTER_LEN]; - int countermeasures; - time_t last_michael_mic_error; - u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN]; - int rx_replay_counter_set; - u8 bssid[ETH_ALEN]; - int reassociate; /* reassociation requested */ - struct wpa_ssid *current_ssid; - u8 *ap_wpa_ie, *ap_rsn_ie; - size_t ap_wpa_ie_len, ap_rsn_ie_len; - u8 *assoc_wpa_ie; - size_t assoc_wpa_ie_len; - - /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ - int proto; - int pairwise_cipher; - int group_cipher; - int key_mgmt; - - void *drv_priv; /* private data used by driver_ops */ - - struct wpa_ssid *prev_scan_ssid; /* previously scanned SSID; - * NULL = not yet initialized (start - * with broadcast SSID) - * BROADCAST_SSID_SCAN = broadcast - * SSID was used in the previous scan - */ -#define BROADCAST_SSID_SCAN ((struct wpa_ssid *) 1) - - struct wpa_scan_result *scan_results; - int num_scan_results; - - struct wpa_driver_ops *driver; - int interface_removed; /* whether the network interface has been - * removed */ - struct eapol_sm *eapol; - - int ctrl_sock; /* UNIX domain socket for control interface or -1 if - * not used */ - struct wpa_ctrl_dst *ctrl_dst; - - enum { - WPA_DISCONNECTED, WPA_SCANNING, WPA_ASSOCIATING, - WPA_ASSOCIATED, WPA_4WAY_HANDSHAKE, WPA_GROUP_HANDSHAKE, - WPA_COMPLETED - } wpa_state; - - struct rsn_pmksa_cache *pmksa; /* PMKSA cache */ - int pmksa_count; /* number of entries in PMKSA cache */ - struct rsn_pmksa_cache *cur_pmksa; /* current PMKSA entry */ - struct rsn_pmksa_candidate *pmksa_candidates; - - struct l2_packet_data *l2_preauth; - u8 preauth_bssid[ETH_ALEN]; /* current RSN pre-auth peer or - * 00:00:00:00:00:00 if no pre-auth is - * in progress */ - struct eapol_sm *preauth_eapol; - - int eapol_received; /* number of EAPOL packets received after the - * previous association event */ - - u8 *imsi; - size_t imsi_len; - struct scard_data *scard; - - unsigned char last_eapol_src[ETH_ALEN]; - - int keys_cleared; - - struct wpa_blacklist *blacklist; - -#ifdef EAPOL_TEST - u8 radius_identifier; - struct radius_msg *last_recv_radius; - struct in_addr own_ip_addr; - struct radius_client_data *radius; - - /* RADIUS Authentication and Accounting servers in priority order */ - struct hostapd_radius_server *auth_servers, *auth_server; - int num_auth_servers; - struct hostapd_radius_server *acct_servers, *acct_server; - int num_acct_servers; - - int radius_retry_primary_interval; - int radius_acct_interim_interval; - - u8 *last_eap_radius; /* last received EAP Response from Authentication - * Server */ - size_t last_eap_radius_len; - - u8 authenticator_pmk[PMK_LEN]; - size_t authenticator_pmk_len; - int radius_access_accept_received; - int radius_access_reject_received; - int auth_timed_out; - - u8 *eap_identity; - size_t eap_identity_len; -#endif /* EAPOL_TEST */ -}; - - -/* wpa_supplicant.c */ -void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx); - -void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); - -void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s); - -void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, - int reason_code); -void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, - int reason_code); - -void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, - int sec, int usec); - -void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s); - -int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s); - -int wpa_supplicant_get_beacon_ie(struct wpa_supplicant *wpa_s); - - -/* wpa.c */ -void wpa_supplicant_key_request(struct wpa_supplicant *wpa_s, - int error, int pairwise); - -struct wpa_ie_data { - int proto; - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int capabilities; - int num_pmkid; - u8 *pmkid; -}; - -int wpa_parse_wpa_ie(struct wpa_supplicant *wpa_s, u8 *wpa_ie, - size_t wpa_ie_len, struct wpa_ie_data *data); - -int wpa_gen_wpa_ie(struct wpa_supplicant *wpa_s, u8 *wpa_ie); - -void wpa_supplicant_rx_eapol(void *ctx, unsigned char *src_addr, - unsigned char *buf, size_t len); - -struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s); - -void pmksa_cache_free(struct wpa_supplicant *wpa_s); -struct rsn_pmksa_cache * pmksa_cache_get(struct wpa_supplicant *wpa_s, - u8 *aa, u8 *pmkid); -int pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len); -void pmksa_candidate_free(struct wpa_supplicant *wpa_s); - -int wpa_get_mib(struct wpa_supplicant *wpa_s, char *buf, size_t buflen); - -struct wpa_scan_result; -#ifdef IEEE8021X_EAPOL -int rsn_preauth_init(struct wpa_supplicant *wpa_s, u8 *dst); -void rsn_preauth_deinit(struct wpa_supplicant *wpa_s); -void rsn_preauth_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, int count); -void pmksa_candidate_add(struct wpa_supplicant *wpa_s, const u8 *bssid, - int prio); -#else /* IEEE8021X_EAPOL */ -static inline int rsn_preauth_init(struct wpa_supplicant *wpa_s, u8 *dst) -{ - return -1; -} - -static inline void rsn_preauth_deinit(struct wpa_supplicant *wpa_s) -{ -} -static inline void rsn_preauth_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, - int count) -{ -} - -static inline void pmksa_candidate_add(struct wpa_supplicant *wpa_s, - const u8 *bssid, - int prio) -{ -} -#endif /* IEEE8021X_EAPOL */ - -void wpa_supplicant_notify_eapol_done(void *ctx); - -/** - * wpa_eapol_send - send IEEE 802.1X EAPOL packet to the Authenticator - * @ctx: pointer to wpa_supplicant data - * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) - * @buf: EAPOL payload (after IEEE 802.1X header) - * @len: EAPOL payload length - * - * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame - * to the current Authenticator or in case of pre-authentication, to the peer - * of the authentication. - */ -int wpa_eapol_send(void *ctx, int type, u8 *buf, size_t len); -int wpa_eapol_send_preauth(void *ctx, int type, u8 *buf, size_t len); - - -/* driver_ops */ -static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s, - const char *ifname) -{ - if (wpa_s->driver->init) { - return wpa_s->driver->init(wpa_s, ifname); - } - return NULL; -} - -static inline void wpa_drv_deinit(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->deinit) - wpa_s->driver->deinit(wpa_s->drv_priv); -} - -static inline int wpa_drv_set_drop_unencrypted(struct wpa_supplicant *wpa_s, - int enabled) -{ - if (wpa_s->driver->set_drop_unencrypted) { - return wpa_s->driver->set_drop_unencrypted(wpa_s->drv_priv, - enabled); - } - return -1; -} - -static inline int wpa_drv_set_countermeasures(struct wpa_supplicant *wpa_s, - int enabled) -{ - if (wpa_s->driver->set_countermeasures) { - return wpa_s->driver->set_countermeasures(wpa_s->drv_priv, - enabled); - } - return -1; -} - -static inline int wpa_drv_set_auth_alg(struct wpa_supplicant *wpa_s, - int auth_alg) -{ - if (wpa_s->driver->set_auth_alg) { - return wpa_s->driver->set_auth_alg(wpa_s->drv_priv, - auth_alg); - } - return -1; -} - -static inline int wpa_drv_set_wpa(struct wpa_supplicant *wpa_s, int enabled) -{ - if (wpa_s->driver->set_wpa) { - return wpa_s->driver->set_wpa(wpa_s->drv_priv, enabled); - } - return 0; -} - -static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s, - struct wpa_driver_associate_params *params) -{ - if (wpa_s->driver->associate) { - return wpa_s->driver->associate(wpa_s->drv_priv, params); - } - return -1; -} - -static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s, const u8 *ssid, - size_t ssid_len) -{ - if (wpa_s->driver->scan) { - return wpa_s->driver->scan(wpa_s->drv_priv, ssid, ssid_len); - } - return -1; -} - -static inline int wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, - size_t max_size) -{ - if (wpa_s->driver->get_scan_results) { - return wpa_s->driver->get_scan_results(wpa_s->drv_priv, - results, max_size); - } - return -1; -} - -static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid) -{ - if (wpa_s->driver->get_bssid) { - return wpa_s->driver->get_bssid(wpa_s->drv_priv, bssid); - } - return -1; -} - -static inline int wpa_drv_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid) -{ - if (wpa_s->driver->get_ssid) { - return wpa_s->driver->get_ssid(wpa_s->drv_priv, ssid); - } - return -1; -} - -static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - if (wpa_s->driver->set_key) { - return wpa_s->driver->set_key(wpa_s->drv_priv, alg, addr, - key_idx, set_tx, seq, seq_len, - key, key_len); - } - return -1; -} - -static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s, - const u8 *addr, int reason_code) -{ - if (wpa_s->driver->deauthenticate) { - return wpa_s->driver->deauthenticate(wpa_s->drv_priv, addr, - reason_code); - } - return -1; -} - -static inline int wpa_drv_disassociate(struct wpa_supplicant *wpa_s, - const u8 *addr, int reason_code) -{ - if (wpa_s->driver->disassociate) { - return wpa_s->driver->disassociate(wpa_s->drv_priv, addr, - reason_code); - } - return -1; -} - -static inline int wpa_drv_add_pmkid(struct wpa_supplicant *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - if (wpa_s->driver->add_pmkid) { - return wpa_s->driver->add_pmkid(wpa_s->drv_priv, bssid, pmkid); - } - return -1; -} - -static inline int wpa_drv_remove_pmkid(struct wpa_supplicant *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - if (wpa_s->driver->remove_pmkid) { - return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, bssid, - pmkid); - } - return -1; -} - -static inline int wpa_drv_flush_pmkid(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->flush_pmkid) { - return wpa_s->driver->flush_pmkid(wpa_s->drv_priv); - } - return -1; -} - -static inline int wpa_drv_get_capa(struct wpa_supplicant *wpa_s, - struct wpa_driver_capa *capa) -{ - if (wpa_s->driver->get_capa) { - return wpa_s->driver->get_capa(wpa_s->drv_priv, capa); - } - return -1; -} - -static inline void wpa_drv_poll(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->poll) { - wpa_s->driver->poll(wpa_s->drv_priv); - } -} - -static inline const char * wpa_drv_get_ifname(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->get_ifname) { - return wpa_s->driver->get_ifname(wpa_s->drv_priv); - } - return NULL; -} - -static inline const u8 * wpa_drv_get_mac_addr(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->get_mac_addr) { - return wpa_s->driver->get_mac_addr(wpa_s->drv_priv); - } - return NULL; -} - -#endif /* WPA_SUPPLICANT_I_H */ |