1526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt/* 2526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * WPA Supplicant - PS3 Linux wireless extension driver interface 3526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Copyright 2007, 2008 Sony Corporation 4526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 5526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * This program is free software; you can redistribute it and/or modify 6526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * it under the terms of the GNU General Public License version 2 as 7526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * published by the Free Software Foundation. 8526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 9526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 10526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * license. 11526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * 12526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt * See README and COPYING for more details. 13526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt */ 14526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 15526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "includes.h" 16526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include <sys/ioctl.h> 17526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wireless_copy.h" 18526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "common.h" 19526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "wpa_common.h" 20526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "driver.h" 21526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "eloop.h" 22526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "driver_wext.h" 23526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt#include "ieee802_11_defs.h" 24526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 25526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_ps3_set_wpa_key(struct wpa_driver_wext_data *drv, 26526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_driver_associate_params *params) 27526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 28526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret, i; 29526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct iwreq iwr; 30526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt char *buf, *str; 31526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 32526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!params->psk && !params->passphrase) { 33526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "%s:no PSK error", __func__); 34526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -EINVAL; 35526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 36526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 37526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 38526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (params->psk) { 39526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* includes null */ 40526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.data.length = PMK_LEN * 2 + 1; 41526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(iwr.u.data.length); 42526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!buf) 43526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -ENOMEM; 44526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt str = buf; 45526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < PMK_LEN; i++) { 46526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt str += snprintf(str, iwr.u.data.length - (str - buf), 47526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt "%02x", params->psk[i]); 48526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 49526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else if (params->passphrase) { 50526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* including quotations and null */ 51526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.data.length = strlen(params->passphrase) + 3; 52526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf = os_malloc(iwr.u.data.length); 53526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!buf) 54526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -ENOMEM; 55526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[0] = '"'; 56526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memcpy(buf + 1, params->passphrase, iwr.u.data.length - 3); 57526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[iwr.u.data.length - 2] = '"'; 58526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt buf[iwr.u.data.length - 1] = '\0'; 59526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 60526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return -EINVAL; 61526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.data.pointer = (caddr_t) buf; 62526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 63526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = ioctl(drv->ioctl_sock, SIOCIWFIRSTPRIV, &iwr); 64526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_free(buf); 65526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 66526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 67526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 68526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 69526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_ps3_set_wep_keys(struct wpa_driver_wext_data *drv, 70526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_driver_associate_params *params) 71526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 72526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret, i; 73526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct iwreq iwr; 74526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 75526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt for (i = 0; i < 4; i++) { 76526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_memset(&iwr, 0, sizeof(iwr)); 77526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ); 78526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.encoding.flags = i + 1; 79526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (params->wep_key_len[i]) { 80526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.encoding.pointer = (caddr_t) params->wep_key[i]; 81526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.encoding.length = params->wep_key_len[i]; 82526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } else 83526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt iwr.u.encoding.flags = IW_ENCODE_NOKEY | 84526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IW_ENCODE_DISABLED; 85526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 86526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ioctl(drv->ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { 87526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt perror("ioctl[SIOCSIWENCODE]"); 88526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 89526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 90526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 91526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 92526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 93526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 94526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_ps3_associate(void *priv, 95526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_driver_associate_params *params) 96526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 97526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt struct wpa_driver_wext_data *drv = priv; 98526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret, value; 99526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 100526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: <-", __func__); 101526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 102526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* clear BSSID */ 103526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (!params->bssid && 104526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_driver_wext_set_bssid(drv, NULL) < 0) 105526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 106526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 107526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_driver_wext_set_mode(drv, params->mode) < 0) 108526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 109526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 110526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (params->wpa_ie == NULL || params->wpa_ie_len == 0) 111526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt value = IW_AUTH_WPA_VERSION_DISABLED; 112526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else if (params->wpa_ie[0] == WLAN_EID_RSN) 113526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt value = IW_AUTH_WPA_VERSION_WPA2; 114526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt else 115526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt value = IW_AUTH_WPA_VERSION_WPA; 116526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 117526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IW_AUTH_WPA_VERSION, value) < 0) 118526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 119526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt value = wpa_driver_wext_cipher2wext(params->pairwise_suite); 120526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 121526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IW_AUTH_CIPHER_PAIRWISE, value) < 0) 122526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 123526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt value = wpa_driver_wext_cipher2wext(params->group_suite); 124526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, 125526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt IW_AUTH_CIPHER_GROUP, value) < 0) 126526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 127526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt value = wpa_driver_wext_keymgmt2wext(params->key_mgmt_suite); 128526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (wpa_driver_wext_set_auth_param(drv, IW_AUTH_KEY_MGMT, value) < 0) 129526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 130526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 131526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* set selected BSSID */ 132526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (params->bssid && 133526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_driver_wext_set_bssid(drv, params->bssid) < 0) 134526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = -1; 135526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 136526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt switch (params->group_suite) { 137526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CIPHER_NONE: 138526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = 0; 139526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 140526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CIPHER_WEP40: 141526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CIPHER_WEP104: 142526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = wpa_driver_ps3_set_wep_keys(drv, params); 143526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 144526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CIPHER_TKIP: 145526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt case CIPHER_CCMP: 146526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = wpa_driver_ps3_set_wpa_key(drv, params); 147526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt break; 148526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 149526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 150526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* start to associate */ 151526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = wpa_driver_wext_set_ssid(drv, params->ssid, params->ssid_len); 152526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 153526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s: ->", __func__); 154526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 155526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 156526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 157526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 158526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtstatic int wpa_driver_ps3_get_capa(void *priv, struct wpa_driver_capa *capa) 159526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt{ 160526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt int ret; 161526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s:<-", __func__); 162526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 163526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt ret = wpa_driver_wext_get_capa(priv, capa); 164526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt if (ret) { 165526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_INFO, "%s: base wext returns error %d", 166526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt __func__, ret); 167526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return ret; 168526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt } 169526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt /* PS3 hypervisor does association and 4way handshake by itself */ 170526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt capa->flags |= WPA_DRIVER_FLAGS_4WAY_HANDSHAKE; 171526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt wpa_printf(MSG_DEBUG, "%s:->", __func__); 172526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt return 0; 173526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt} 174526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt 175526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidtconst struct wpa_driver_ops wpa_driver_ps3_ops = { 176526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .name = "ps3", 177526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .desc = "PLAYSTATION3 Linux wireless extension driver", 178526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .get_bssid = wpa_driver_wext_get_bssid, 179526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .get_ssid = wpa_driver_wext_get_ssid, 180526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .scan = wpa_driver_wext_scan, 181526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .get_scan_results2 = wpa_driver_wext_get_scan_results, 182526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .associate = wpa_driver_ps3_associate, /* PS3 */ 183526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .init = wpa_driver_wext_init, 184526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .deinit = wpa_driver_wext_deinit, 185526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt .get_capa = wpa_driver_ps3_get_capa, /* PS3 */ 186526fc2a7dc09b4450086cdec313a5c44d36b10fdDmitry Shmidt}; 187