1 /* 2 * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <gpxe/net80211.h> 22 #include <gpxe/sha1.h> 23 #include <gpxe/wpa.h> 24 #include <errno.h> 25 26 /** @file 27 * 28 * Frontend for WPA using a pre-shared key. 29 */ 30 31 /** 32 * Initialise WPA-PSK state 33 * 34 * @v dev 802.11 device 35 * @ret rc Return status code 36 */ 37 static int wpa_psk_init ( struct net80211_device *dev ) 38 { 39 return wpa_make_rsn_ie ( dev, &dev->rsn_ie ); 40 } 41 42 /** 43 * Start WPA-PSK authentication 44 * 45 * @v dev 802.11 device 46 * @ret rc Return status code 47 */ 48 static int wpa_psk_start ( struct net80211_device *dev ) 49 { 50 char passphrase[64+1]; 51 u8 pmk[WPA_PMK_LEN]; 52 int len; 53 struct wpa_common_ctx *ctx = dev->handshaker->priv; 54 55 len = fetch_string_setting ( netdev_settings ( dev->netdev ), 56 &net80211_key_setting, passphrase, 57 64 + 1 ); 58 59 if ( len <= 0 ) { 60 DBGC ( ctx, "WPA-PSK %p: no passphrase provided!\n", ctx ); 61 net80211_deauthenticate ( dev, -EACCES ); 62 return -EACCES; 63 } 64 65 pbkdf2_sha1 ( passphrase, len, dev->essid, strlen ( dev->essid ), 66 4096, pmk, WPA_PMK_LEN ); 67 68 DBGC ( ctx, "WPA-PSK %p: derived PMK from passphrase `%s':\n", ctx, 69 passphrase ); 70 DBGC_HD ( ctx, pmk, WPA_PMK_LEN ); 71 72 return wpa_start ( dev, ctx, pmk, WPA_PMK_LEN ); 73 } 74 75 /** 76 * Step WPA-PSK authentication 77 * 78 * @v dev 802.11 device 79 * @ret rc Return status code 80 */ 81 static int wpa_psk_step ( struct net80211_device *dev ) 82 { 83 struct wpa_common_ctx *ctx = dev->handshaker->priv; 84 85 switch ( ctx->state ) { 86 case WPA_SUCCESS: 87 return 1; 88 case WPA_FAILURE: 89 return -EACCES; 90 default: 91 return 0; 92 } 93 } 94 95 /** 96 * Do-nothing function; you can't change a WPA key post-authentication 97 * 98 * @v dev 802.11 device 99 * @ret rc Return status code 100 */ 101 static int wpa_psk_no_change_key ( struct net80211_device *dev __unused ) 102 { 103 return 0; 104 } 105 106 /** 107 * Disable handling of received WPA authentication frames 108 * 109 * @v dev 802.11 device 110 */ 111 static void wpa_psk_stop ( struct net80211_device *dev ) 112 { 113 wpa_stop ( dev ); 114 } 115 116 /** WPA-PSK security handshaker */ 117 struct net80211_handshaker wpa_psk_handshaker __net80211_handshaker = { 118 .protocol = NET80211_SECPROT_PSK, 119 .init = wpa_psk_init, 120 .start = wpa_psk_start, 121 .step = wpa_psk_step, 122 .change_key = wpa_psk_no_change_key, 123 .stop = wpa_psk_stop, 124 .priv_len = sizeof ( struct wpa_common_ctx ), 125 }; 126