From patchwork Sun Aug 12 11:28:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Kondratiev X-Patchwork-Id: 1309561 Return-Path: X-Original-To: patchwork-linux-wireless@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 8BB653FC23 for ; Sun, 12 Aug 2012 11:28:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751367Ab2HLL2X (ORCPT ); Sun, 12 Aug 2012 07:28:23 -0400 Received: from wolverine02.qualcomm.com ([199.106.114.251]:3550 "EHLO wolverine02.qualcomm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751178Ab2HLL2W (ORCPT ); Sun, 12 Aug 2012 07:28:22 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=qca.qualcomm.com; i=@qca.qualcomm.com; q=dns/txt; s=qcdkim; t=1344770903; x=1376306903; h=cc:from:to:subject:date:message-id:in-reply-to: references:mime-version; bh=W4+vfQZ7ovFW2ZiKAICG+4j+W/GtEjOVrM/6dIEFSrw=; b=yKGXgJNAKz5HeR02aiepSo6X1hBQILw/SDjOmYzGJLTcE1WGZct6JepW /9kKFSxldWF9p4dQzDSdgfxq+35uG0vkmrgtV1qugx9i5lnH9gRuQtmQi DMi1OwF0sl46ALwqIo4WvZMS7yzi8CqtCvtgOhzM0Q8XHoQh/wi7GQuxw w=; X-IronPort-AV: E=McAfee;i="5400,1158,6800"; a="222143015" Received: from ironmsg04-l.qualcomm.com ([172.30.48.19]) by wolverine02.qualcomm.com with ESMTP; 12 Aug 2012 04:28:23 -0700 Cc: Vladimir Kondratiev , , "Luis R . Rodriguez" X-IronPort-AV: E=Sophos;i="4.77,754,1336374000"; d="scan'208";a="280477945" Received: from nasanexhc04.na.qualcomm.com ([172.30.48.17]) by Ironmsg04-L.qualcomm.com with ESMTP/TLS/RC4-SHA; 12 Aug 2012 04:28:23 -0700 Received: from lx-vladimir.qi.qualcomm.com (172.30.48.1) by qcmail1.qualcomm.com (172.30.48.17) with Microsoft SMTP Server (TLS) id 14.2.309.2; Sun, 12 Aug 2012 04:28:21 -0700 From: Vladimir Kondratiev To: "John W . Linville" , Johannes Berg Subject: [PATCH v2] cfg80211: Support for 4-way handshake offloading for WPA2-Personal Date: Sun, 12 Aug 2012 14:28:04 +0300 Message-ID: <1344770884-17102-2-git-send-email-qca_vkondrat@qca.qualcomm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1344770884-17102-1-git-send-email-qca_vkondrat@qca.qualcomm.com> References: <1344770884-17102-1-git-send-email-qca_vkondrat@qca.qualcomm.com> MIME-Version: 1.0 X-Originating-IP: [172.30.48.1] Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org Traditionally, WPA supplicant handle 4-way handshake and do all key derivation. First, PSK calculated from the passphrase and SSID. Finally, PTK supplied to the driver with add_key() For firmware to implement offload, it need PSK. In case of WPA2-Personal, PSK is available on the connect()/start_ap() time. In case of WPS2-Enterprise, the PSK will be available only after the EAP authentication, this is not addressed with this patch. Based on code from Rishi Panjwani Signed-off-by: Vladimir Kondratiev --- include/linux/ieee80211.h | 2 ++ include/linux/nl80211.h | 19 +++++++++++++++++++ include/net/cfg80211.h | 10 ++++++++++ net/wireless/nl80211.c | 16 ++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index e02fc68..95aafb3 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1787,6 +1787,8 @@ enum ieee80211_sa_query_action { #define WLAN_PMKID_LEN 16 +#define WLAN_PSK_LEN 32 + #define WLAN_OUI_WFA 0x506f9a #define WLAN_OUI_TYPE_WFA_P2P 9 #define WLAN_OUI_MICROSOFT 0x0050f2 diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 2f38788..64f01a3 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1251,6 +1251,21 @@ enum nl80211_commands { * was used to provide the hint. For the different types of * allowed user regulatory hints see nl80211_user_reg_hint_type. * + * @NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_STA: This is a flag that indicates to + * WPA supplicant that 4-way handshake has been offloaded to the firmware + * in the STA mode. + * In this case, WPA supplicant will provide driver with PSK for + * connect() + * + * @NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_AP: This is a flag that indicates to + * WPA supplicant that 4-way handshake has been offloaded to the firmware + * in the AP mode. + * In this case, WPA supplicant will provide driver with PSK for + * start_ap() + * + * @NL80211_ATTR_PSK: The PSK calculated by WPA supplicant + * length is WLAN_PSK_LEN (32) bytes + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1506,6 +1521,10 @@ enum nl80211_attrs { NL80211_ATTR_USER_REG_HINT_TYPE, + NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_STA, + NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_AP, + NL80211_ATTR_PSK, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3d254e1..2b70ee2 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -438,6 +438,7 @@ struct cfg80211_beacon_data { * @privacy: the BSS uses privacy * @auth_type: Authentication type (algorithm) * @inactivity_timeout: time in seconds to determine station's inactivity. + * @psk: The PSK that has been calculated by WPA supplicant */ struct cfg80211_ap_settings { struct ieee80211_channel *channel; @@ -453,6 +454,7 @@ struct cfg80211_ap_settings { bool privacy; enum nl80211_auth_type auth_type; int inactivity_timeout; + const u8 *psk; }; /** @@ -1307,6 +1309,7 @@ struct cfg80211_ibss_params { * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask * will be used in ht_capa. Un-supported values will be ignored. * @ht_capa_mask: The bits of ht_capa which are to be used. + * @psk: The PSK that has been calculated by WPA supplicant */ struct cfg80211_connect_params { struct ieee80211_channel *channel; @@ -1324,6 +1327,7 @@ struct cfg80211_connect_params { int bg_scan_period; struct ieee80211_ht_cap ht_capa; struct ieee80211_ht_cap ht_capa_mask; + const u8 *psk; }; /** @@ -1898,6 +1902,10 @@ struct cfg80211_ops { * responds to probe-requests in hardware. * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX. * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call. + * @WIPHY_FLAG_4WAY_HANDSHAKE_OFFLOAD_STA: Device supports + * 4-way handshake offload in STA mode. + * @WIPHY_FLAG_4WAY_HANDSHAKE_OFFLOAD_AP: Device supports + * 4-way handshake offload in AP mode. */ enum wiphy_flags { WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), @@ -1921,6 +1929,8 @@ enum wiphy_flags { WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19), WIPHY_FLAG_OFFCHAN_TX = BIT(20), WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21), + WIPHY_FLAG_4WAY_HANDSHAKE_OFFLOAD_STA = BIT(22), + WIPHY_FLAG_4WAY_HANDSHAKE_OFFLOAD_AP = BIT(23), }; /** diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 97026f3..c74f01f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -355,6 +355,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, [NL80211_ATTR_WDEV] = { .type = NLA_U64 }, [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_STA] = { .type = NLA_FLAG }, + [NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_AP] = { .type = NLA_FLAG }, + [NL80211_ATTR_PSK] = { .type = NLA_BINARY, + .len = WLAN_PSK_LEN }, }; /* policy for the key attributes */ @@ -914,6 +918,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) && nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP)) goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_4WAY_HANDSHAKE_OFFLOAD_STA) && + nla_put_flag(msg, NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_STA)) + goto nla_put_failure; + if ((dev->wiphy.flags & WIPHY_FLAG_4WAY_HANDSHAKE_OFFLOAD_AP) && + nla_put_flag(msg, NL80211_ATTR_4WAY_HANDSHAKE_OFFLOAD_AP)) + goto nla_put_failure; if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * dev->wiphy.n_cipher_suites, @@ -2576,6 +2586,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) params.channel_type)) return -EINVAL; + if (info->attrs[NL80211_ATTR_PSK]) + params.psk = nla_data(info->attrs[NL80211_ATTR_PSK]); + mutex_lock(&rdev->devlist_mtx); err = cfg80211_can_use_chan(rdev, wdev, params.channel, CHAN_MODE_SHARED); @@ -5640,6 +5653,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) sizeof(connect.ht_capa)); } + if (info->attrs[NL80211_ATTR_PSK]) + connect.psk = nla_data(info->attrs[NL80211_ATTR_PSK]); + err = cfg80211_connect(rdev, dev, &connect, connkeys); if (err) kfree(connkeys);