From patchwork Mon Mar 5 14:37:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amitkumar Karwar X-Patchwork-Id: 10259163 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2734D60365 for ; Mon, 5 Mar 2018 14:49:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 178DA28A77 for ; Mon, 5 Mar 2018 14:49:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0C75328A90; Mon, 5 Mar 2018 14:49:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DDB4028A77 for ; Mon, 5 Mar 2018 14:49:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932084AbeCEOtd (ORCPT ); Mon, 5 Mar 2018 09:49:33 -0500 Received: from mail-pg0-f66.google.com ([74.125.83.66]:45693 "EHLO mail-pg0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752440AbeCEOt1 (ORCPT ); Mon, 5 Mar 2018 09:49:27 -0500 Received: by mail-pg0-f66.google.com with SMTP id i133so6889823pgc.12 for ; Mon, 05 Mar 2018 06:49:27 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=qqo8iXYlbIVA98rtIJGPdlxU4MLxCq9ABx5FYDzPnws=; b=UPHFZfIvAOq50foniIit55wLY5HvX0bpLn48Ed7TmOr0isRnHPbPY1TgXL6JwfmE8B AojH1ISntW8Ji2p4Rc9fXYoJ52vVy0Fqncw25wywI6AOuqBLR2iZVKUa7a675AMiPKHx x7npSklQSU351Z+CLuuO6T9/aZbRgJEUKYU6jkTwS0VWPaCXF8Z6CqlrKfvLWTjxhjz7 93hrwEh2mMElEQvn9MfojaD29QwK6HP9iBq8ZaaP3g50JCyfxeX6ENuvfsbae102VTJf ISPcSkzidlq6ghiL+ubLfuVU2UkAJ/n3D92CVG1elwKrRyC9pWetYTP1HgbHta6c0lbc Y0rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=qqo8iXYlbIVA98rtIJGPdlxU4MLxCq9ABx5FYDzPnws=; b=rD4O9vZvmIURuP6RrhNfnF2DgSsE6pMIK6QctxfBRZyjdXU8oYndrQztubz1h8HDvQ IXXNOwK6TuwTEVvH7aLyAoroIxPUKLbVHdnYDlJ0k3r22898RteQV4TzGZNe16mZfg3y lXYsWX9duQ91xlDMJ1JHFsqbZ97aDPXa+elP9Bui/R8dCaS/CakATGBGYXzA27Zytcz7 GWWlKri3g6Pe9ENZrxvByW/8AJ3GNKK0EmgMtyywM6Lu3eM/Jid8uW6hFx9OqpvDHbUD o/zwhM4+2pv944aK15cN6j0g5+LCR2FlkLnGTSmCm6Qtk/i2W+judE3lkxHBWCdOv7MN p3ew== X-Gm-Message-State: APf1xPDPyJdzEOhHbd1vv+9n6ZnL/L4UZlQrjZCH/z7/mP7S2azXSDxM cXnnHeacIlvtya5sox6qOwk= X-Google-Smtp-Source: AG47ELvvuC3VTKQlsOYCCsLgPoquNRUem/vmFANOn8g57ipXNHDKpsggK4z/vf6G1oVCvtjLWsDjOA== X-Received: by 10.99.176.68 with SMTP id z4mr12139601pgo.74.1520261366784; Mon, 05 Mar 2018 06:49:26 -0800 (PST) Received: from cpu185.redpinesignals.com ([203.196.161.90]) by smtp.gmail.com with ESMTPSA id i1sm29164845pfi.116.2018.03.05.06.49.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 05 Mar 2018 06:49:25 -0800 (PST) From: Amitkumar Karwar To: Kalle Valo Cc: linux-wireless@vger.kernel.org, Amitkumar Karwar , Siva Rebbagondla Subject: [PATCH 10/10] rsi: drop RX broadcast/multicast packets with invalid PN Date: Mon, 5 Mar 2018 20:07:00 +0530 Message-Id: <1520260620-4694-11-git-send-email-amitkarwar@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1520260620-4694-1-git-send-email-amitkarwar@gmail.com> References: <1520260620-4694-1-git-send-email-amitkarwar@gmail.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Siva Rebbagondla This patch adds a check to drop received broadcast/multicast frames if PN is invalid (i.e. not greater than last PN). bc_mc_pn variable added for each interface Signed-off-by: Siva Rebbagondla Signed-off-by: Amitkumar Karwar --- drivers/net/wireless/rsi/rsi_91x_mac80211.c | 166 ++++++++++++++++++++++++++-- drivers/net/wireless/rsi/rsi_main.h | 3 + 2 files changed, 160 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 70b2d61..f73c0f0 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -522,6 +522,9 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw, mutex_unlock(&common->mutex); return -EINVAL; } + memset(vif_info->rx_bcmc_pn, 0, IEEE80211_CCMP_PN_LEN); + vif_info->rx_pn_valid = false; + vif_info->key = NULL; if ((vif->type == NL80211_IFTYPE_AP) || (vif->type == NL80211_IFTYPE_P2P_GO)) { @@ -1035,6 +1038,8 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, struct rsi_hw *adapter = hw->priv; struct rsi_common *common = adapter->priv; struct security_info *secinfo = &common->secinfo; + struct vif_priv *vif_info = (struct vif_priv *)vif->drv_priv; + struct ieee80211_key_seq seq; int status; mutex_lock(&common->mutex); @@ -1047,10 +1052,41 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, return status; } - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { secinfo->ptk_cipher = key->cipher; - else + } else { secinfo->gtk_cipher = key->cipher; + ieee80211_get_key_rx_seq(key, 0, &seq); + switch (key->cipher) { + case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + memcpy(vif_info->rx_bcmc_pn, seq.ccmp.pn, + IEEE80211_CCMP_PN_LEN); + vif_info->rx_pn_valid = true; + vif_info->key = key; + break; + case WLAN_CIPHER_SUITE_TKIP: + vif_info->rx_bcmc_pn[0] = seq.tkip.iv16 & 0xff; + vif_info->rx_bcmc_pn[1] = + (seq.tkip.iv16 >> 8) & 0xff; + vif_info->rx_bcmc_pn[2] = seq.tkip.iv32 & 0xff; + vif_info->rx_bcmc_pn[3] = + (seq.tkip.iv32 >> 8) & 0xff; + vif_info->rx_bcmc_pn[4] = + (seq.tkip.iv32 >> 16) & 0xff; + vif_info->rx_bcmc_pn[5] = + (seq.tkip.iv32 >> 24) & 0xff; + vif_info->rx_pn_valid = true; + vif_info->key = key; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + memcpy(vif_info->rx_bcmc_pn, + seq.aes_cmac.pn, IEEE80211_CMAC_PN_LEN); + vif_info->rx_pn_valid = true; + vif_info->key = key; + break; + } + } key->hw_key_idx = key->keyidx; key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; @@ -1063,6 +1099,9 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, secinfo->security_enable = false; rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__); memset(key, 0, sizeof(struct ieee80211_key_conf)); + memset(vif_info->rx_bcmc_pn, 0, IEEE80211_CCMP_PN_LEN); + vif_info->rx_pn_valid = false; + vif_info->key = NULL; status = rsi_hal_key_config(hw, vif, key, sta); break; @@ -1277,6 +1316,103 @@ static void rsi_perform_cqm(struct rsi_common *common, return; } +struct dot11_ccmp_hdr { + u8 pn0; + u8 pn1; + u8 reserved; + u8 keyid_info; + u8 pn2; + u8 pn3; + u8 pn4; + u8 pn5; +}; + +struct dot11_tkip_hdr { + u8 tsc1; + u8 wep_seed; + u8 tsc0; + u8 keyid_info; + u8 tsc2; + u8 tsc3; + u8 tsc4; + u8 tsc5; +}; + +static int rsi_validate_pn(struct rsi_hw *adapter, struct ieee80211_hdr *hdr) +{ + struct ieee80211_vif *vif; + struct ieee80211_bss_conf *bss; + struct vif_priv *vif_info = NULL; + u8 cur_pn[IEEE80211_CCMP_PN_LEN]; + u8 *last_pn; + int i, hdrlen; + + if (!is_broadcast_ether_addr(hdr->addr1) && + !is_multicast_ether_addr(hdr->addr1)) + return 1; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + for (i = 0; i < adapter->sc_nvifs; i++) { + vif = adapter->vifs[i]; + + if (!vif) + continue; + if (vif->type != NL80211_IFTYPE_STATION && + vif->type != NL80211_IFTYPE_P2P_CLIENT) + continue; + bss = &vif->bss_conf; + if (!bss->assoc) + continue; + if (!ether_addr_equal(bss->bssid, hdr->addr2)) + continue; + vif_info = (struct vif_priv *)vif->drv_priv; + if (!vif_info->key) { + vif_info = NULL; + continue; + } + if (!vif_info->rx_pn_valid) { + vif_info = NULL; + continue; + } + } + if (!vif_info) + return 1; + last_pn = vif_info->rx_bcmc_pn; + if (vif_info->key->cipher == WLAN_CIPHER_SUITE_CCMP) { + struct dot11_ccmp_hdr *ccmp = + (struct dot11_ccmp_hdr *)&((u8 *)hdr)[hdrlen]; + + cur_pn[0] = ccmp->pn0; + cur_pn[1] = ccmp->pn1; + cur_pn[2] = ccmp->pn2; + cur_pn[3] = ccmp->pn3; + cur_pn[4] = ccmp->pn4; + cur_pn[5] = ccmp->pn5; + } else { + struct dot11_tkip_hdr *tkip = + (struct dot11_tkip_hdr *)&((u8 *)hdr)[hdrlen]; + + cur_pn[0] = tkip->tsc0; + cur_pn[1] = tkip->tsc1; + cur_pn[2] = tkip->tsc2; + cur_pn[3] = tkip->tsc3; + cur_pn[4] = tkip->tsc4; + cur_pn[5] = tkip->tsc5; + } + for (i = (IEEE80211_CCMP_PN_LEN - 1); i >= 0; i--) + if (last_pn[i] ^ cur_pn[i]) + break; + if (i < 0) + return -1; + + if (last_pn[i] >= cur_pn[i]) + return -1; + + memcpy(vif_info->rx_bcmc_pn, cur_pn, IEEE80211_CCMP_PN_LEN); + + return 0; +} + /** * rsi_fill_rx_status() - This function fills rx status in * ieee80211_rx_status structure. @@ -1287,10 +1423,10 @@ static void rsi_perform_cqm(struct rsi_common *common, * * Return: None. */ -static void rsi_fill_rx_status(struct ieee80211_hw *hw, - struct sk_buff *skb, - struct rsi_common *common, - struct ieee80211_rx_status *rxs) +static int rsi_fill_rx_status(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct rsi_common *common, + struct ieee80211_rx_status *rxs) { struct rsi_hw *adapter = common->priv; struct ieee80211_vif *vif; @@ -1323,6 +1459,17 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw, memmove(skb->data + 4, skb->data, hdrlen); skb_pull(skb, 4); } else { + if (skb->len < (hdrlen + IEEE80211_CCMP_HDR_LEN)) { + rsi_dbg(ERR_ZONE, "Invalid encrypted packet\n"); + dev_kfree_skb(skb); + return -EINVAL; + } + if (rsi_validate_pn(adapter, hdr) < 0) { + rsi_dbg(INFO_ZONE, + "Invalid RX PN; Dropping\n"); + dev_kfree_skb(skb); + return -EINVAL; + } memmove(skb->data + 8, skb->data, hdrlen); skb_pull(skb, 8); rxs->flag |= RX_FLAG_MMIC_STRIPPED; @@ -1341,14 +1488,14 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw, } } if (!bss) - return; + return -1; /* CQM only for connected AP beacons, the RSSI is a weighted avg */ if (bss->assoc && !(memcmp(bss->bssid, hdr->addr2, ETH_ALEN))) { if (ieee80211_is_beacon(hdr->frame_control)) rsi_perform_cqm(common, hdr->addr2, rxs->signal, vif); } - return; + return 0; } /** @@ -1371,7 +1518,8 @@ void rsi_indicate_pkt_to_os(struct rsi_common *common, } /* filling in the ieee80211_rx_status flags */ - rsi_fill_rx_status(hw, skb, common, rx_status); + if (rsi_fill_rx_status(hw, skb, common, rx_status)) + return; ieee80211_rx_irqsafe(hw, skb); } diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 9e09dd5..566379c 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -191,6 +191,9 @@ struct vif_priv { bool sgi; u16 seq_start; int vap_id; + struct ieee80211_key_conf *key; + u8 rx_bcmc_pn[IEEE80211_CCMP_PN_LEN]; + bool rx_pn_valid; }; struct rsi_event {