176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modify it under the terms of the GNU General Public License as 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * published by the Free Software Foundation; either version 2 of the 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * License, or any later version. 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is distributed in the hope that it will be useful, but 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WITHOUT ANY WARRANTY; without even the implied warranty of 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * General Public License for more details. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You should have received a copy of the GNU General Public License 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * along with this program; if not, write to the Free Software 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/net80211.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/sha1.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/wpa.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h> 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** @file 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Frontend for WPA using a pre-shared key. 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Initialise WPA-PSK state 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dev 802.11 device 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int wpa_psk_init ( struct net80211_device *dev ) 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return wpa_make_rsn_ie ( dev, &dev->rsn_ie ); 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Start WPA-PSK authentication 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dev 802.11 device 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int wpa_psk_start ( struct net80211_device *dev ) 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman char passphrase[64+1]; 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 pmk[WPA_PMK_LEN]; 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int len; 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct wpa_common_ctx *ctx = dev->handshaker->priv; 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman len = fetch_string_setting ( netdev_settings ( dev->netdev ), 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman &net80211_key_setting, passphrase, 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 64 + 1 ); 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( len <= 0 ) { 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( ctx, "WPA-PSK %p: no passphrase provided!\n", ctx ); 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman net80211_deauthenticate ( dev, -EACCES ); 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -EACCES; 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pbkdf2_sha1 ( passphrase, len, dev->essid, strlen ( dev->essid ), 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4096, pmk, WPA_PMK_LEN ); 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( ctx, "WPA-PSK %p: derived PMK from passphrase `%s':\n", ctx, 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman passphrase ); 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC_HD ( ctx, pmk, WPA_PMK_LEN ); 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return wpa_start ( dev, ctx, pmk, WPA_PMK_LEN ); 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Step WPA-PSK authentication 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dev 802.11 device 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int wpa_psk_step ( struct net80211_device *dev ) 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct wpa_common_ctx *ctx = dev->handshaker->priv; 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman switch ( ctx->state ) { 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case WPA_SUCCESS: 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 1; 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman case WPA_FAILURE: 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -EACCES; 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman default: 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Do-nothing function; you can't change a WPA key post-authentication 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dev 802.11 device 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int wpa_psk_no_change_key ( struct net80211_device *dev __unused ) 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Disable handling of received WPA authentication frames 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v dev 802.11 device 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void wpa_psk_stop ( struct net80211_device *dev ) 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman wpa_stop ( dev ); 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** WPA-PSK security handshaker */ 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct net80211_handshaker wpa_psk_handshaker __net80211_handshaker = { 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .protocol = NET80211_SECPROT_PSK, 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .init = wpa_psk_init, 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .start = wpa_psk_start, 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .step = wpa_psk_step, 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .change_key = wpa_psk_no_change_key, 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .stop = wpa_psk_stop, 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .priv_len = sizeof ( struct wpa_common_ctx ), 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 126