iPXE
wpa_psk.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  */
00019 
00020 FILE_LICENCE ( GPL2_OR_LATER );
00021 
00022 #include <string.h>
00023 #include <ipxe/net80211.h>
00024 #include <ipxe/sha1.h>
00025 #include <ipxe/wpa.h>
00026 #include <errno.h>
00027 
00028 /** @file
00029  *
00030  * Frontend for WPA using a pre-shared key.
00031  */
00032 
00033 /**
00034  * Initialise WPA-PSK state
00035  *
00036  * @v dev       802.11 device
00037  * @ret rc      Return status code
00038  */
00039 static int wpa_psk_init ( struct net80211_device *dev )
00040 {
00041         return wpa_make_rsn_ie ( dev, &dev->rsn_ie );
00042 }
00043 
00044 /**
00045  * Start WPA-PSK authentication
00046  *
00047  * @v dev       802.11 device
00048  * @ret rc      Return status code
00049  */
00050 static int wpa_psk_start ( struct net80211_device *dev )
00051 {
00052         char passphrase[64+1];
00053         u8 pmk[WPA_PMK_LEN];
00054         int len;
00055         struct wpa_common_ctx *ctx = dev->handshaker->priv;
00056 
00057         len = fetch_string_setting ( netdev_settings ( dev->netdev ),
00058                                      &net80211_key_setting, passphrase,
00059                                      64 + 1 );
00060 
00061         if ( len <= 0 ) {
00062                 DBGC ( ctx, "WPA-PSK %p: no passphrase provided!\n", ctx );
00063                 net80211_deauthenticate ( dev, -EACCES );
00064                 return -EACCES;
00065         }
00066 
00067         pbkdf2_sha1 ( passphrase, len, dev->essid, strlen ( dev->essid ),
00068                       4096, pmk, WPA_PMK_LEN );
00069 
00070         DBGC ( ctx, "WPA-PSK %p: derived PMK from passphrase `%s':\n", ctx,
00071                passphrase );
00072         DBGC_HD ( ctx, pmk, WPA_PMK_LEN );
00073 
00074         return wpa_start ( dev, ctx, pmk, WPA_PMK_LEN );
00075 }
00076 
00077 /**
00078  * Step WPA-PSK authentication
00079  *
00080  * @v dev       802.11 device
00081  * @ret rc      Return status code
00082  */
00083 static int wpa_psk_step ( struct net80211_device *dev )
00084 {
00085         struct wpa_common_ctx *ctx = dev->handshaker->priv;
00086 
00087         switch ( ctx->state ) {
00088         case WPA_SUCCESS:
00089                 return 1;
00090         case WPA_FAILURE:
00091                 return -EACCES;
00092         default:
00093                 return 0;
00094         }
00095 }
00096 
00097 /**
00098  * Do-nothing function; you can't change a WPA key post-authentication
00099  *
00100  * @v dev       802.11 device
00101  * @ret rc      Return status code
00102  */
00103 static int wpa_psk_no_change_key ( struct net80211_device *dev __unused )
00104 {
00105         return 0;
00106 }
00107 
00108 /**
00109  * Disable handling of received WPA authentication frames
00110  *
00111  * @v dev       802.11 device
00112  */
00113 static void wpa_psk_stop ( struct net80211_device *dev )
00114 {
00115         wpa_stop ( dev );
00116 }
00117 
00118 /** WPA-PSK security handshaker */
00119 struct net80211_handshaker wpa_psk_handshaker __net80211_handshaker = {
00120         .protocol = NET80211_SECPROT_PSK,
00121         .init = wpa_psk_init,
00122         .start = wpa_psk_start,
00123         .step = wpa_psk_step,
00124         .change_key = wpa_psk_no_change_key,
00125         .stop = wpa_psk_stop,
00126         .priv_len = sizeof ( struct wpa_common_ctx ),
00127 };