Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp3011958pxj; Mon, 17 May 2021 15:32:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz0AjZR1N6VseW0P0OC169eTXGmPDcH5CX8QPlI4Jv6iDvzcRmLzwlx8wGG7a3xOK4S3ONk X-Received: by 2002:aa7:cd8b:: with SMTP id x11mr2815876edv.87.1621290745763; Mon, 17 May 2021 15:32:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621290745; cv=none; d=google.com; s=arc-20160816; b=tu5up2IO7RuM1Aa11VVf6uDStgN9pScrQBQ8/rwGQKvBH+xqYYEyTGSUS5ZD4dnK1d 8It7PMRsFPdZz5DDdhCknYocpt6MuHWaRwuiOJR72y+ThA2RWv9+KzxExR7emIBkhrcC aiZwx+s7m2YilBWUJjT2BBwj2mdPuy5LmT+aKEfxwtDtF+H7qMZJ9XaCZRnYsN4+buP/ vGeP+08iXDU3UtVAhTjzA70qopeJDw/2eKf//xCOHNft2uMZXGmbh/cRSbo2fkly74L3 F7pnLfsk1oKgglcCYybELDlRqdgo5DzpK5LjmyRqEMY1WdKBRhZhVL1iFiZ7cNYi+y6F xiWA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=R890joToRR/eOkJEYPbQ2O8nx0IxECTNY3A1yqJGCH4=; b=F0W8wzjaD+yK0IfXoD1ruNnPaPTytjUpPMeenIWsQwD0Ld4Fn0OlDF06DhibgV5XpW TbcWcQkQMTrA/3IKqV/+8caayyap3DWt55vZvQldEd+ZFrDEhgADa3Obt6BwUSt8ToCG nAdXlFwobe65LfLeLo95zP56uWVCXA7YtFe0yWiEXzn6ucxGvoeycQ0OGPrsQzOQyC0L V7UcbkIgg4N3x2Mf7vF7hQG+DZLYn14w+nB8G+LapWnDaEQaIz/Q7VDFBaRyPC3Cky4y FCTpkbCCJMC0MuTZvU54mMaivoZFr4XlZ2HJek4wu+ma47RkFRueVzDhWLk7wWorIrn8 iZhA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Olch9LSk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id v21si13178704edq.476.2021.05.17.15.32.03; Mon, 17 May 2021 15:32:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Olch9LSk; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238418AbhEQOPm (ORCPT + 99 others); Mon, 17 May 2021 10:15:42 -0400 Received: from mail.kernel.org ([198.145.29.99]:46534 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238467AbhEQOM4 (ORCPT ); Mon, 17 May 2021 10:12:56 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 995F261361; Mon, 17 May 2021 14:08:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1621260499; bh=qV9+df8TPeAHAIA3wa/PLMlE/O/clMfwETcUrlBGups=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Olch9LSkQenef/f/w2+uDo/C0cNBD5g2WYRF2XQMDrR5A74kR3ZhOPHwZRBQrBlNM pJQwfwKFACaq600Ckq0vtnRQRCn0GUbzbOanMdAcpzz6IqOR5Iq8F7ZK6VVkerntWT jAa8oYcsFWZLl9eR2ZeHWW2YWaKBi5rykCG0styA= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Felix Fietkau , Sasha Levin Subject: [PATCH 5.12 063/363] mt76: mt7615: fix key set/delete issues Date: Mon, 17 May 2021 15:58:49 +0200 Message-Id: <20210517140304.736184179@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210517140302.508966430@linuxfoundation.org> References: <20210517140302.508966430@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Felix Fietkau [ Upstream commit 730d6d0da8d8f5905faafe645a5b3c08ac3f5a8f ] There were multiple issues in the current key set/remove code: - deleting a key with the previous key index deletes the current key - BIP key would only be uploaded correctly initially and corrupted on rekey Rework the code to better keep track of multiple keys and check for the key index before deleting the current key Signed-off-by: Felix Fietkau Signed-off-by: Sasha Levin --- drivers/net/wireless/mediatek/mt76/mt76.h | 1 + .../net/wireless/mediatek/mt76/mt7615/mac.c | 97 ++++++++++--------- .../net/wireless/mediatek/mt76/mt7615/main.c | 18 ++-- 3 files changed, 65 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 8bf45497cfca..36a430f09f64 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -222,6 +222,7 @@ struct mt76_wcid { u16 idx; u8 hw_key_idx; + u8 hw_key_idx2; u8 sta:1; u8 ext_phy:1; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index d73841480544..8dccb589b756 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1037,7 +1037,7 @@ EXPORT_SYMBOL_GPL(mt7615_mac_set_rates); static int mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, struct ieee80211_key_conf *key, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4; @@ -1054,22 +1054,22 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, memcpy(data + 16, key->key + 24, 8); memcpy(data + 24, key->key + 16, 8); } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && wcid->cipher) - memmove(data + 16, data, 16); - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) + if (cipher_mask == BIT(cipher)) memcpy(data, key->key, key->keylen); - else if (cipher == MT_CIPHER_BIP_CMAC_128) + else if (cipher != MT_CIPHER_BIP_CMAC_128) + memcpy(data, key->key, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memcpy(data + 16, key->key, 16); } } else { - if (wcid->cipher & ~BIT(cipher)) { - if (cipher != MT_CIPHER_BIP_CMAC_128) - memmove(data, data + 16, 16); + if (cipher == MT_CIPHER_BIP_CMAC_128) memset(data + 16, 0, 16); - } else { + else if (cipher_mask) + memset(data, 0, 16); + if (!cipher_mask) memset(data, 0, sizeof(data)); - } } + mt76_wr_copy(dev, addr, data, sizeof(data)); return 0; @@ -1077,7 +1077,7 @@ mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid, static int mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, int keyidx, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1; @@ -1087,20 +1087,23 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, w0 = mt76_rr(dev, addr); w1 = mt76_rr(dev, addr + 4); - if (cmd == SET_KEY) { - w0 |= MT_WTBL_W0_RX_KEY_VALID | - FIELD_PREP(MT_WTBL_W0_RX_IK_VALID, - cipher == MT_CIPHER_BIP_CMAC_128); - if (cipher != MT_CIPHER_BIP_CMAC_128 || - !wcid->cipher) - w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); - } else { - if (!(wcid->cipher & ~BIT(cipher))) - w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | - MT_WTBL_W0_KEY_IDX); - if (cipher == MT_CIPHER_BIP_CMAC_128) - w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cipher_mask) + w0 |= MT_WTBL_W0_RX_KEY_VALID; + else + w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX); + if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128)) + w0 |= MT_WTBL_W0_RX_IK_VALID; + else + w0 &= ~MT_WTBL_W0_RX_IK_VALID; + + if (cmd == SET_KEY && + (cipher != MT_CIPHER_BIP_CMAC_128 || + cipher_mask == BIT(cipher))) { + w0 &= ~MT_WTBL_W0_KEY_IDX; + w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx); } + mt76_wr(dev, MT_WTBL_RICR0, w0); mt76_wr(dev, MT_WTBL_RICR1, w1); @@ -1113,24 +1116,25 @@ mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid, static void mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid, - enum mt7615_cipher_type cipher, + enum mt7615_cipher_type cipher, u16 cipher_mask, enum set_key_cmd cmd) { u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx); - if (cmd == SET_KEY) { - if (cipher != MT_CIPHER_BIP_CMAC_128 || !wcid->cipher) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); - } else { - if (cipher != MT_CIPHER_BIP_CMAC_128 && - wcid->cipher & BIT(MT_CIPHER_BIP_CMAC_128)) - mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, - FIELD_PREP(MT_WTBL_W2_KEY_TYPE, - MT_CIPHER_BIP_CMAC_128)); - else if (!(wcid->cipher & ~BIT(cipher))) - mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + if (!cipher_mask) { + mt76_clear(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE); + return; } + + if (cmd != SET_KEY) + return; + + if (cipher == MT_CIPHER_BIP_CMAC_128 && + cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128)) + return; + + mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE, + FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher)); } int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, @@ -1139,25 +1143,30 @@ int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev, enum set_key_cmd cmd) { enum mt7615_cipher_type cipher; + u16 cipher_mask = wcid->cipher; int err; cipher = mt7615_mac_get_cipher(key->cipher); if (cipher == MT_CIPHER_NONE) return -EOPNOTSUPP; - mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cmd); - err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cmd); + if (cmd == SET_KEY) + cipher_mask |= BIT(cipher); + else + cipher_mask &= ~BIT(cipher); + + mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask, cmd); + err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask, + cmd); if (err < 0) return err; - err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, key->keyidx, cmd); + err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask, + key->keyidx, cmd); if (err < 0) return err; - if (cmd == SET_KEY) - wcid->cipher |= BIT(cipher); - else - wcid->cipher &= ~BIT(cipher); + wcid->cipher = cipher_mask; return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index 6107e827b383..d334491667a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -334,7 +334,8 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct mt7615_sta *msta = sta ? (struct mt7615_sta *)sta->drv_priv : &mvif->sta; struct mt76_wcid *wcid = &msta->wcid; - int idx = key->keyidx, err; + int idx = key->keyidx, err = 0; + u8 *wcid_keyidx = &wcid->hw_key_idx; /* The hardware does not support per-STA RX GTK, fallback * to software mode for these. @@ -349,6 +350,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* fall back to sw encryption for unsupported ciphers */ switch (key->cipher) { case WLAN_CIPHER_SUITE_AES_CMAC: + wcid_keyidx = &wcid->hw_key_idx2; key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE; break; case WLAN_CIPHER_SUITE_TKIP: @@ -366,12 +368,13 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, mt7615_mutex_acquire(dev); - if (cmd == SET_KEY) { - key->hw_key_idx = wcid->idx; - wcid->hw_key_idx = idx; - } else if (idx == wcid->hw_key_idx) { - wcid->hw_key_idx = -1; - } + if (cmd == SET_KEY) + *wcid_keyidx = idx; + else if (idx == *wcid_keyidx) + *wcid_keyidx = -1; + else + goto out; + mt76_wcid_key_setup(&dev->mt76, wcid, cmd == SET_KEY ? key : NULL); @@ -380,6 +383,7 @@ static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, else err = __mt7615_mac_wtbl_set_key(dev, wcid, key, cmd); +out: mt7615_mutex_release(dev); return err; -- 2.30.2