From patchwork Fri Jun 7 14:49:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10982175 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9B2C376 for ; Fri, 7 Jun 2019 14:50:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 89FB528564 for ; Fri, 7 Jun 2019 14:50:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7E1B72882F; Fri, 7 Jun 2019 14:50: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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 3868D28830 for ; Fri, 7 Jun 2019 14:50:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729323AbfFGOue (ORCPT ); Fri, 7 Jun 2019 10:50:34 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42486 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728486AbfFGOue (ORCPT ); Fri, 7 Jun 2019 10:50:34 -0400 Received: by mail-wr1-f65.google.com with SMTP id x17so2449480wrl.9 for ; Fri, 07 Jun 2019 07:50:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vcJMY+fqzbzAsxP+j3GnSWwHUteH8OqWbcpKZgatReo=; b=CZvlAiz3/tzc0J+yK6zjz21aKF5BPmxTt6qoB9PW1Yy0vRpVdqsicmFntJ4+afYK9B 5+WCgfi/CcIVy1mRQ8MwEJk+K3tpzpt9G2WM9Uw3Rsc4rYc+6fQRn3xkeD77lBJX8umh chRJ3knrqwH3YGfvNnx2MuT4CxAYFNTBEBSdESyNZyW2owmYgVBQrGZfM6eRJiJLrnXO Hg+mMsjeYovYgWVQSvmBjW/0bKbM2FsAYCLSWFP0SP05sxTcnDrXRDmBBTor2dh1QlXG dzCO/Ddu3MVzWX68hZcTxKzZ/ED1+ddSPqU4t+3hiffiGE5ay8wyAjZsZ3OEzV5FjZv8 Jo0g== 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:mime-version:content-transfer-encoding; bh=vcJMY+fqzbzAsxP+j3GnSWwHUteH8OqWbcpKZgatReo=; b=NXjvGZBwVQUu7pSAwJjYNmnrB0j/DoivprxkWyYlS/ilC8uLwCUot2fLDG1/1OzrlM eT+g78/uiY5DxW3oZZVXtQPkZ3pO8S1/5g2O2QbmGsVuMv9FvYF15/DVrSz4IpwEAP0f 6f9ps2VzTrOZ66maadSH1hKAulD6mlreQD/1czuJjCX4MYR0LIMHL6OKbqEuopJ3h0bo yCN7IErVoHYb2nFVxIpwnfSsjDvTzFhhVI36XFaic4L4/+B91oMkB2KZe1BuqPkUz6k8 Fca+01vHGS4WTBirTNQkdWk0OgL+nWlauIPB3oCFmgn+InwS/jSh9aV/VLFlz/c2LZ/9 Y3Ug== X-Gm-Message-State: APjAAAUEjchxjA94Ckf9qKQzqkZ/Gs4oqBTJLGhrERAXasQMepeePqD2 ZwRnJjQIe3aI9MM90LN3/cNm35REE4GmYQ== X-Google-Smtp-Source: APXvYqydF0s3UC9VVMUOwUe559EMfYIIyoRPoUa0LkLSDywz1iTI7f7ge76HX9sY9OnVNY5dSFie1Q== X-Received: by 2002:adf:dc09:: with SMTP id t9mr34406067wri.69.1559919032627; Fri, 07 Jun 2019 07:50:32 -0700 (PDT) Received: from localhost.localdomain (aaubervilliers-681-1-126-188.w90-88.abo.wanadoo.fr. [90.88.7.188]) by smtp.gmail.com with ESMTPSA id t13sm4129354wra.81.2019.06.07.07.50.31 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Fri, 07 Jun 2019 07:50:31 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: herbert@gondor.apana.org.au, ebiggers@kernel.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, davem@davemloft.net, Ard Biesheuvel Subject: [RFC PATCH 1/3] net/mac80211: switch to skcipher interface for arc4 Date: Fri, 7 Jun 2019 16:49:42 +0200 Message-Id: <20190607144944.13485-2-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190607144944.13485-1-ard.biesheuvel@linaro.org> References: <20190607144944.13485-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 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 The mac80211 WEP code uses the cipher interface, and invokes it byte by byte. This is rather inefficient, and since the cipher interface in general is not really suitable for use outside of the crypto subsystem, move this code to use the skcipher interface instead. Given that the only driver that provides a RC4 cipher also provides a skcipher implementation, this is guaranteed to work. (Note that ARC4_BLOCK_SIZE is #define'd as 1 so ecb(arc4) behaves as a stream cipher, as is required in this case) Signed-off-by: Ard Biesheuvel --- net/mac80211/ieee80211_i.h | 6 +- net/mac80211/key.h | 1 + net/mac80211/tkip.c | 8 +- net/mac80211/tkip.h | 4 +- net/mac80211/wep.c | 81 +++++++++++++++----- net/mac80211/wep.h | 4 +- net/mac80211/wpa.c | 4 +- 7 files changed, 75 insertions(+), 33 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 073a8235ae1b..c0773cf685b6 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1258,8 +1258,10 @@ struct ieee80211_local { struct rate_control_ref *rate_ctrl; - struct crypto_cipher *wep_tx_tfm; - struct crypto_cipher *wep_rx_tfm; + struct crypto_skcipher *wep_tx_tfm; + struct crypto_skcipher *wep_rx_tfm; + struct skcipher_request *wep_tx_req; + struct skcipher_request *wep_rx_req; u32 wep_iv; /* see iface.c */ diff --git a/net/mac80211/key.h b/net/mac80211/key.h index f06fbd03d235..ee5e7f30a1f1 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index b3622823bad2..23dd962633fe 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -222,7 +222,7 @@ EXPORT_SYMBOL(ieee80211_get_tkip_p2k); * @payload_len is the length of payload (_not_ including IV/ICV length). * @ta is the transmitter addresses. */ -int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_encrypt_data(struct skcipher_request *req, struct ieee80211_key *key, struct sk_buff *skb, u8 *payload, size_t payload_len) @@ -231,7 +231,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, ieee80211_get_tkip_p2k(&key->conf, skb, rc4key); - return ieee80211_wep_encrypt_data(tfm, rc4key, 16, + return ieee80211_wep_encrypt_data(req, rc4key, 16, payload, payload_len); } @@ -239,7 +239,7 @@ int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, * beginning of the buffer containing IEEE 802.11 header payload, i.e., * including IV, Ext. IV, real data, Michael MIC, ICV. @payload_len is the * length of payload, including IV, Ext. IV, MIC, ICV. */ -int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_decrypt_data(struct skcipher_request *req, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, @@ -297,7 +297,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, tkip_mixing_phase2(tk, &rx_ctx->ctx, iv16, rc4key); - res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); + res = ieee80211_wep_decrypt_data(req, rc4key, 16, pos, payload_len - 12); done: if (res == TKIP_DECRYPT_OK) { /* diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index a1bcbfbefe7c..e66aac448786 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h @@ -13,7 +13,7 @@ #include #include "key.h" -int ieee80211_tkip_encrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_encrypt_data(struct skcipher_request *req, struct ieee80211_key *key, struct sk_buff *skb, u8 *payload, size_t payload_len); @@ -24,7 +24,7 @@ enum { TKIP_DECRYPT_INVALID_KEYIDX = -2, TKIP_DECRYPT_REPLAY = -3, }; -int ieee80211_tkip_decrypt_data(struct crypto_cipher *tfm, +int ieee80211_tkip_decrypt_data(struct skcipher_request *req, struct ieee80211_key *key, u8 *payload, size_t payload_len, u8 *ta, u8 *ra, int only_iv, int queue, diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index bfe9ed9f4c48..0336afb70c2b 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -27,31 +27,64 @@ int ieee80211_wep_init(struct ieee80211_local *local) { + int err; + /* start WEP IV from a random value */ get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN); - local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, 0); + local->wep_tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_tx_tfm)) { local->wep_rx_tfm = ERR_PTR(-EINVAL); return PTR_ERR(local->wep_tx_tfm); } - local->wep_rx_tfm = crypto_alloc_cipher("arc4", 0, 0); + local->wep_rx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(local->wep_rx_tfm)) { - crypto_free_cipher(local->wep_tx_tfm); - local->wep_tx_tfm = ERR_PTR(-EINVAL); - return PTR_ERR(local->wep_rx_tfm); + err = PTR_ERR(local->wep_rx_tfm); + goto free_tx_tfm; + } + + local->wep_tx_req = skcipher_request_alloc(local->wep_tx_tfm, + GFP_KERNEL); + if (!local->wep_tx_req) { + err = -ENOMEM; + goto free_rx_tfm; + } + + local->wep_rx_req = skcipher_request_alloc(local->wep_rx_tfm, + GFP_KERNEL); + if (!local->wep_rx_req) { + err = -ENOMEM; + goto free_tx_req; } return 0; + +free_tx_req: + skcipher_request_free(local->wep_tx_req); + local->wep_tx_req = NULL; +free_rx_tfm: + crypto_free_skcipher(local->wep_rx_tfm); + local->wep_rx_tfm = ERR_PTR(-EINVAL); +free_tx_tfm: + crypto_free_skcipher(local->wep_tx_tfm); + local->wep_tx_tfm = ERR_PTR(-EINVAL); + + return err; } void ieee80211_wep_free(struct ieee80211_local *local) { + if (local->wep_tx_req) + skcipher_request_free(local->wep_tx_req); + if (local->wep_rx_req) + skcipher_request_free(local->wep_rx_req); if (!IS_ERR(local->wep_tx_tfm)) - crypto_free_cipher(local->wep_tx_tfm); + crypto_free_skcipher(local->wep_tx_tfm); if (!IS_ERR(local->wep_rx_tfm)) - crypto_free_cipher(local->wep_rx_tfm); + crypto_free_skcipher(local->wep_rx_tfm); } static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) @@ -131,21 +164,24 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, /* Perform WEP encryption using given key. data buffer must have tailroom * for 4-byte ICV. data_len must not include this ICV. Note: this function * does _not_ add IV. data = RC4(data | CRC32(data)) */ -int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_encrypt_data(struct skcipher_request *req, u8 *rc4key, size_t klen, u8 *data, size_t data_len) { + struct scatterlist sg; __le32 icv; - int i; - if (IS_ERR(tfm)) + if (!req) return -1; icv = cpu_to_le32(~crc32_le(~0, data, data_len)); put_unaligned(icv, (__le32 *)(data + data_len)); - crypto_cipher_setkey(tfm, rc4key, klen); - for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++) - crypto_cipher_encrypt_one(tfm, data + i, data + i); + crypto_skcipher_setkey(crypto_skcipher_reqtfm(req), rc4key, klen); + sg_init_one(&sg, data, data_len + IEEE80211_WEP_ICV_LEN); + skcipher_request_set_crypt(req, &sg, &sg, + data_len + IEEE80211_WEP_ICV_LEN, NULL); + if (crypto_skcipher_encrypt(req) < 0) + return -1; return 0; } @@ -184,7 +220,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, /* Add room for ICV */ skb_put(skb, IEEE80211_WEP_ICV_LEN); - return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3, + return ieee80211_wep_encrypt_data(local->wep_tx_req, rc4key, keylen + 3, iv + IEEE80211_WEP_IV_LEN, len); } @@ -192,18 +228,21 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, /* Perform WEP decryption using given key. data buffer includes encrypted * payload, including 4-byte ICV, but _not_ IV. data_len must not include ICV. * Return 0 on success and -1 on ICV mismatch. */ -int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_decrypt_data(struct skcipher_request *req, u8 *rc4key, size_t klen, u8 *data, size_t data_len) { + struct scatterlist sg; __le32 crc; - int i; - if (IS_ERR(tfm)) + if (!req) return -1; - crypto_cipher_setkey(tfm, rc4key, klen); - for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++) - crypto_cipher_decrypt_one(tfm, data + i, data + i); + crypto_skcipher_setkey(crypto_skcipher_reqtfm(req), rc4key, klen); + sg_init_one(&sg, data, data_len + IEEE80211_WEP_ICV_LEN); + skcipher_request_set_crypt(req, &sg, &sg, + data_len + IEEE80211_WEP_ICV_LEN, NULL); + if (crypto_skcipher_decrypt(req) < 0) + return -1; crc = cpu_to_le32(~crc32_le(~0, data, data_len)); if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0) @@ -256,7 +295,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, /* Copy rest of the WEP key (the secret part) */ memcpy(rc4key + 3, key->conf.key, key->conf.keylen); - if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, + if (ieee80211_wep_decrypt_data(local->wep_rx_req, rc4key, klen, skb->data + hdrlen + IEEE80211_WEP_IV_LEN, len)) ret = -1; diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 9615749d1f65..6a392b1ed4b7 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h @@ -18,12 +18,12 @@ int ieee80211_wep_init(struct ieee80211_local *local); void ieee80211_wep_free(struct ieee80211_local *local); -int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_encrypt_data(struct skcipher_request *req, u8 *rc4key, size_t klen, u8 *data, size_t data_len); int ieee80211_wep_encrypt(struct ieee80211_local *local, struct sk_buff *skb, const u8 *key, int keylen, int keyidx); -int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, +int ieee80211_wep_decrypt_data(struct skcipher_request *req, u8 *rc4key, size_t klen, u8 *data, size_t data_len); ieee80211_rx_result diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 58d0b258b684..a7870ec67a26 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -242,7 +242,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) /* Add room for ICV */ skb_put(skb, IEEE80211_TKIP_ICV_LEN); - return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, + return ieee80211_tkip_encrypt_data(tx->local->wep_tx_req, key, skb, pos, len); } @@ -293,7 +293,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_DECRYPTED) hwaccel = 1; - res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, + res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_req, key, skb->data + hdrlen, skb->len - hdrlen, rx->sta->sta.addr, hdr->addr1, hwaccel, rx->security_idx, From patchwork Fri Jun 7 14:49:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10982183 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9D54E15E6 for ; Fri, 7 Jun 2019 14:50:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8CDD82882F for ; Fri, 7 Jun 2019 14:50:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 810012886B; Fri, 7 Jun 2019 14:50:40 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 AB3262884A for ; Fri, 7 Jun 2019 14:50:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729438AbfFGOui (ORCPT ); Fri, 7 Jun 2019 10:50:38 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:37191 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729172AbfFGOuf (ORCPT ); Fri, 7 Jun 2019 10:50:35 -0400 Received: by mail-wm1-f67.google.com with SMTP id 22so2205624wmg.2 for ; Fri, 07 Jun 2019 07:50:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Z6Wy0LB17Cj8+QFhDjq+MOW1OHqvbDIBczgJ5kYrrbI=; b=xzaE+3nRMJcAfiRFheJgq7ol8JYf2GZx2t/sk5NVe5j9CnldAHgP4s/Xz+Px6ZEz7X xGWKPQEEn4kDOJ+pKVrFNbvTsgIS/umEIQxDx8MbIpVlm5yU/d5ch7Z9/ojPCtMfOTR2 RdCmaqud8/nO4QcdMTk5rD9ZYtzler0FRiC9sJ+KKr/Y4qg1HS14MC56w5tJzCmQfAeh q9Tra4gXU0dByQrHkPq7ksV6rxHvru13Tg2PmZcEzqaTWgK1bRPSXNELZuNWKVEPX4FO ArHQ2wGTRjh/rv/RmVmOrrPA1Sm0CDTt+Fp6hBIjoFOEAAjnc4DA0i/HU6jNZJh0T3kv hpNw== 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:mime-version:content-transfer-encoding; bh=Z6Wy0LB17Cj8+QFhDjq+MOW1OHqvbDIBczgJ5kYrrbI=; b=IZ9Q3sqlDy9DbqfzMhQ5IvpnUw2V4oKvLG1Lm9LYYjmSc/j4uPqpL/iRYQSNFWVdSU FEOQpVouaqnPxLaVgiHNYURS6zTOOVyhEb/3DlZeHaIzWGqh0yBPgeEYKb/XHzQcgRac OV032ohwhTWiLS/kKMfhflToWSf48OzhE72JOX/9j11+bb0qYoBOBTkkkdjUzZC3Y9jr HVUHkCvGZh+Hg+MNxyCd1CTDSbjPhlToHbQr4xRB7o/sgtm8LSp6kigWoJJLuOtJ28Yo CJVnkymQKR8GaG/q2yStPok4fdr9eGT5P+FbZuNXr31xNZh6UaZQzV2AGGrPNw0Qr7DX x9Nw== X-Gm-Message-State: APjAAAUxcGEUzZ/0qOBSlaRfLEL01zvCQ+s4uTnv1rglmDEZRWnAlL/R uYwF8Mq1RJLm7Q9QPoKJ2ZpkSw== X-Google-Smtp-Source: APXvYqxDd2bsboZayCVfX84i2mTQBsV5ovAMJqvB6quHwmu93T6O11m5STFQcm12ih+7klauM967IQ== X-Received: by 2002:a1c:1bc9:: with SMTP id b192mr3942201wmb.152.1559919033813; Fri, 07 Jun 2019 07:50:33 -0700 (PDT) Received: from localhost.localdomain (aaubervilliers-681-1-126-188.w90-88.abo.wanadoo.fr. [90.88.7.188]) by smtp.gmail.com with ESMTPSA id t13sm4129354wra.81.2019.06.07.07.50.32 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Fri, 07 Jun 2019 07:50:33 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: herbert@gondor.apana.org.au, ebiggers@kernel.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, davem@davemloft.net, Ard Biesheuvel Subject: [RFC PATCH 2/3] lib80211/tkip: switch to skcipher interface for arc4 Date: Fri, 7 Jun 2019 16:49:43 +0200 Message-Id: <20190607144944.13485-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190607144944.13485-1-ard.biesheuvel@linaro.org> References: <20190607144944.13485-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 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 The TKIP code uses the arc4 cipher interface, and invokes it byte by byte. This is rather inefficient, and since the cipher interface in general is not really suitable for use outside of the crypto subsystem, move this code to use the skcipher interface instead. Given that the only driver that provides a RC4 cipher also provides a skcipher implementation, this is guaranteed to work. (Note that ARC4_BLOCK_SIZE is #define'd as 1 so ecb(arc4) behaves as a stream cipher, as is required in this case) Signed-off-by: Ard Biesheuvel --- net/wireless/lib80211_crypt_tkip.c | 61 ++++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/net/wireless/lib80211_crypt_tkip.c b/net/wireless/lib80211_crypt_tkip.c index 11eaa5956f00..456c85b03b32 100644 --- a/net/wireless/lib80211_crypt_tkip.c +++ b/net/wireless/lib80211_crypt_tkip.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -64,9 +65,11 @@ struct lib80211_tkip_data { int key_idx; - struct crypto_cipher *rx_tfm_arc4; + struct crypto_skcipher *rx_tfm_arc4; + struct skcipher_request *rx_req_arc4; struct crypto_shash *rx_tfm_michael; - struct crypto_cipher *tx_tfm_arc4; + struct crypto_skcipher *tx_tfm_arc4; + struct skcipher_request *tx_req_arc4; struct crypto_shash *tx_tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ @@ -99,7 +102,8 @@ static void *lib80211_tkip_init(int key_idx) priv->key_idx = key_idx; - priv->tx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0); + priv->tx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->tx_tfm_arc4)) { priv->tx_tfm_arc4 = NULL; goto fail; @@ -111,7 +115,8 @@ static void *lib80211_tkip_init(int key_idx) goto fail; } - priv->rx_tfm_arc4 = crypto_alloc_cipher("arc4", 0, 0); + priv->rx_tfm_arc4 = crypto_alloc_skcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); if (IS_ERR(priv->rx_tfm_arc4)) { priv->rx_tfm_arc4 = NULL; goto fail; @@ -123,14 +128,26 @@ static void *lib80211_tkip_init(int key_idx) goto fail; } + priv->tx_req_arc4 = skcipher_request_alloc(priv->tx_tfm_arc4, + GFP_KERNEL); + if (!priv->tx_req_arc4) + goto fail; + + priv->rx_req_arc4 = skcipher_request_alloc(priv->rx_tfm_arc4, + GFP_KERNEL); + if (!priv->rx_req_arc4) + goto fail; + return priv; fail: if (priv) { + skcipher_request_free(priv->tx_req_arc4); + skcipher_request_free(priv->rx_req_arc4); crypto_free_shash(priv->tx_tfm_michael); - crypto_free_cipher(priv->tx_tfm_arc4); + crypto_free_skcipher(priv->tx_tfm_arc4); crypto_free_shash(priv->rx_tfm_michael); - crypto_free_cipher(priv->rx_tfm_arc4); + crypto_free_skcipher(priv->rx_tfm_arc4); kfree(priv); } @@ -141,10 +158,12 @@ static void lib80211_tkip_deinit(void *priv) { struct lib80211_tkip_data *_priv = priv; if (_priv) { + skcipher_request_free(_priv->tx_req_arc4); + skcipher_request_free(_priv->rx_req_arc4); crypto_free_shash(_priv->tx_tfm_michael); - crypto_free_cipher(_priv->tx_tfm_arc4); + crypto_free_skcipher(_priv->tx_tfm_arc4); crypto_free_shash(_priv->rx_tfm_michael); - crypto_free_cipher(_priv->rx_tfm_arc4); + crypto_free_skcipher(_priv->rx_tfm_arc4); } kfree(priv); } @@ -342,10 +361,10 @@ static int lib80211_tkip_hdr(struct sk_buff *skb, int hdr_len, static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_tkip_data *tkey = priv; + struct scatterlist sg; int len; u8 rc4key[16], *pos, *icv; u32 crc; - int i; if (tkey->flags & IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -370,10 +389,11 @@ static int lib80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - for (i = 0; i < len + 4; i++) - crypto_cipher_encrypt_one(tkey->tx_tfm_arc4, pos + i, pos + i); - return 0; + crypto_skcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + sg_init_one(&sg, pos, len + 4); + skcipher_request_set_crypt(tkey->tx_req_arc4, &sg, &sg, len + 4, NULL); + + return crypto_skcipher_encrypt(tkey->tx_req_arc4); } /* @@ -392,6 +412,7 @@ static inline int tkip_replay_check(u32 iv32_n, u16 iv16_n, static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_tkip_data *tkey = priv; + struct scatterlist sg; u8 rc4key[16]; u8 keyidx, *pos; u32 iv32; @@ -400,7 +421,6 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) u8 icv[4]; u32 crc; int plen; - int i; hdr = (struct ieee80211_hdr *)skb->data; @@ -453,9 +473,12 @@ static int lib80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; - crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - for (i = 0; i < plen + 4; i++) - crypto_cipher_decrypt_one(tkey->rx_tfm_arc4, pos + i, pos + i); + crypto_skcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + sg_init_one(&sg, pos, plen + 4); + skcipher_request_set_crypt(tkey->rx_req_arc4, &sg, &sg, plen + 4, NULL); + + if (crypto_skcipher_decrypt(tkey->rx_req_arc4)) + return -7; crc = ~crc32_le(~0, pos, plen); icv[0] = crc; @@ -640,9 +663,9 @@ static int lib80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) struct lib80211_tkip_data *tkey = priv; int keyidx; struct crypto_shash *tfm = tkey->tx_tfm_michael; - struct crypto_cipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_skcipher *tfm2 = tkey->tx_tfm_arc4; struct crypto_shash *tfm3 = tkey->rx_tfm_michael; - struct crypto_cipher *tfm4 = tkey->rx_tfm_arc4; + struct crypto_skcipher *tfm4 = tkey->rx_tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); From patchwork Fri Jun 7 14:49:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10982179 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 411F392A for ; Fri, 7 Jun 2019 14:50:39 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 30556285D6 for ; Fri, 7 Jun 2019 14:50:39 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 24406285D9; Fri, 7 Jun 2019 14:50:39 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,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 9FE892882F for ; Fri, 7 Jun 2019 14:50:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729440AbfFGOui (ORCPT ); Fri, 7 Jun 2019 10:50:38 -0400 Received: from mail-wr1-f65.google.com ([209.85.221.65]:42489 "EHLO mail-wr1-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728446AbfFGOug (ORCPT ); Fri, 7 Jun 2019 10:50:36 -0400 Received: by mail-wr1-f65.google.com with SMTP id x17so2449610wrl.9 for ; Fri, 07 Jun 2019 07:50:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=9n8YJM2aN2Tojwoz4xxKnfvlttLhNaxdXPyMxomRKLg=; b=PUiwLSAco3hmTp+31PViC1LfHPHcDGVR3bNcQjgSgRJjL5nJRypoQcMaOu6BfKV9d9 +aR/g1qclXtfM5JL40LECuhW9xZLo8lSFghvrCruHvVCtZurzrGCz89+ANOrEnSwL6T+ BeQ264VKH7RvNB0dITMAfuDM7Evf7M2uvMz4s9RbQ1j13G1pE6obWzlInoyeobaUq5yE zI3ngdTy1ShFwn2bUWYQTT9qHfAHz81dlbC7TnYE7qTyMvkRA0WtxoKmbdZZf0sIaCp0 ajAjfg4bB+IV00Qr0ODUYFnlqW81uXfG6zq5Bb/Jym8ZyZiowcHzpSWzplWN8B7YJbc7 KFag== 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:mime-version:content-transfer-encoding; bh=9n8YJM2aN2Tojwoz4xxKnfvlttLhNaxdXPyMxomRKLg=; b=DkOjW+Skgx9TBvYb0rGo4NLsZA3WCtSuzUQiUhajpSLW/2I1siJkWAkFMkylsaLGYE pdxEtncyb9W77OW3t99WwwBRbWbzsu8TxQXIuLEvr4nhfVk73LEmc1ttENNf/lhstTWu D6UwDOiWmF0V6aCKVaMXU/IJgt/j8bvvyN3z2VZ8bYjxMRTTZ+2rRum2CLO5vSmG7+ZB xIz1lYzaS8pGS+cYfk+yiGR5XKaSAL42YwC2++ZoOo1DYE0xONmzQhA6ppPpuN2tI10q p1mttiITncpWEWAymTMCAg3MDrqZIgXlHiFbtGoe4/V5ZoKoLmsvcHW5yD1Ot2Vb8KKl 78xg== X-Gm-Message-State: APjAAAV/vlqtCArGkZTnIWcpsOTWPetbZRep03DpSimKNvZebJx99yrv WduhQ+k9tYXep8lJO58v9wejIA9dDl9THA== X-Google-Smtp-Source: APXvYqxFVSY0azfTGLywjCh4fg09eiv7Zyyzv+CaMc66H7m3h97p81qndUThVkMzh6g2JCMQqkRIiw== X-Received: by 2002:adf:eb42:: with SMTP id u2mr32550695wrn.80.1559919034855; Fri, 07 Jun 2019 07:50:34 -0700 (PDT) Received: from localhost.localdomain (aaubervilliers-681-1-126-188.w90-88.abo.wanadoo.fr. [90.88.7.188]) by smtp.gmail.com with ESMTPSA id t13sm4129354wra.81.2019.06.07.07.50.33 (version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256); Fri, 07 Jun 2019 07:50:34 -0700 (PDT) From: Ard Biesheuvel To: linux-crypto@vger.kernel.org Cc: herbert@gondor.apana.org.au, ebiggers@kernel.org, johannes@sipsolutions.net, linux-wireless@vger.kernel.org, davem@davemloft.net, Ard Biesheuvel Subject: [RFC PATCH 3/3] lib80211/wep: switch to skcipher interface for arc4 Date: Fri, 7 Jun 2019 16:49:44 +0200 Message-Id: <20190607144944.13485-4-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190607144944.13485-1-ard.biesheuvel@linaro.org> References: <20190607144944.13485-1-ard.biesheuvel@linaro.org> MIME-Version: 1.0 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 The WEP code uses the arc4 cipher interface, and invokes it byte by byte. This is rather inefficient, and since the cipher interface in general is not really suitable for use outside of the crypto subsystem, move this code to use the skcipher interface instead. Given that the only driver that provides a RC4 cipher also provides a skcipher implementation, this is guaranteed to work. (Note that ARC4_BLOCK_SIZE is #define'd as 1 so ecb(arc4) behaves as a stream cipher, as is required in this case) Signed-off-by: Ard Biesheuvel --- net/wireless/lib80211_crypt_wep.c | 52 ++++++++++++++------ 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c index 20c1ad63ad44..461f94afe6e9 100644 --- a/net/wireless/lib80211_crypt_wep.c +++ b/net/wireless/lib80211_crypt_wep.c @@ -23,6 +23,7 @@ #include #include +#include #include MODULE_AUTHOR("Jouni Malinen"); @@ -35,8 +36,10 @@ struct lib80211_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_cipher *tx_tfm; - struct crypto_cipher *rx_tfm; + struct crypto_skcipher *tx_tfm; + struct crypto_skcipher *rx_tfm; + struct skcipher_request *tx_req; + struct skcipher_request *rx_req; }; static void *lib80211_wep_init(int keyidx) @@ -48,17 +51,26 @@ static void *lib80211_wep_init(int keyidx) goto fail; priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_cipher("arc4", 0, 0); + priv->tx_tfm = crypto_alloc_skcipher("ecb(arc4)", 0, 0); if (IS_ERR(priv->tx_tfm)) { priv->tx_tfm = NULL; goto fail; } - priv->rx_tfm = crypto_alloc_cipher("arc4", 0, 0); + priv->rx_tfm = crypto_alloc_skcipher("arc4", 0, 0); if (IS_ERR(priv->rx_tfm)) { priv->rx_tfm = NULL; goto fail; } + + priv->tx_req = skcipher_request_alloc(priv->tx_tfm, GFP_KERNEL); + if (!priv->tx_req) + goto fail; + + priv->rx_req = skcipher_request_alloc(priv->rx_tfm, GFP_KERNEL); + if (!priv->tx_req) + goto fail; + /* start WEP IV from a random value */ get_random_bytes(&priv->iv, 4); @@ -66,8 +78,10 @@ static void *lib80211_wep_init(int keyidx) fail: if (priv) { - crypto_free_cipher(priv->tx_tfm); - crypto_free_cipher(priv->rx_tfm); + skcipher_request_free(priv->tx_req); + skcipher_request_free(priv->rx_req); + crypto_free_skcipher(priv->tx_tfm); + crypto_free_skcipher(priv->rx_tfm); kfree(priv); } return NULL; @@ -77,8 +91,10 @@ static void lib80211_wep_deinit(void *priv) { struct lib80211_wep_data *_priv = priv; if (_priv) { - crypto_free_cipher(_priv->tx_tfm); - crypto_free_cipher(_priv->rx_tfm); + skcipher_request_free(_priv->tx_req); + skcipher_request_free(_priv->rx_req); + crypto_free_skcipher(_priv->tx_tfm); + crypto_free_skcipher(_priv->rx_tfm); } kfree(priv); } @@ -129,10 +145,10 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_wep_data *wep = priv; + struct scatterlist sg; u32 crc, klen, len; u8 *pos, *icv; u8 key[WEP_KEY_LEN + 3]; - int i; /* other checks are in lib80211_wep_build_iv */ if (skb_tailroom(skb) < 4) @@ -160,10 +176,11 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_cipher_setkey(wep->tx_tfm, key, klen); - - for (i = 0; i < len + 4; i++) - crypto_cipher_encrypt_one(wep->tx_tfm, pos + i, pos + i); + crypto_skcipher_setkey(wep->tx_tfm, key, klen); + sg_init_one(&sg, pos, len + 4); + skcipher_request_set_crypt(wep->tx_req, &sg, &sg, len + 4, NULL); + if (crypto_skcipher_encrypt(wep->tx_req) < 0) + return -1; return 0; } @@ -178,6 +195,7 @@ static int lib80211_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct lib80211_wep_data *wep = priv; + struct scatterlist sg; u32 crc, klen, plen; u8 key[WEP_KEY_LEN + 3]; u8 keyidx, *pos, icv[4]; @@ -202,9 +220,11 @@ static int lib80211_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) /* Apply RC4 to data and compute CRC32 over decrypted data */ plen = skb->len - hdr_len - 8; - crypto_cipher_setkey(wep->rx_tfm, key, klen); - for (i = 0; i < plen + 4; i++) - crypto_cipher_decrypt_one(wep->rx_tfm, pos + i, pos + i); + crypto_skcipher_setkey(wep->rx_tfm, key, klen); + sg_init_one(&sg, pos, plen + 4); + skcipher_request_set_crypt(wep->rx_req, &sg, &sg, plen + 4, NULL); + if (crypto_skcipher_decrypt(wep->rx_req) < 0) + return -1; crc = ~crc32_le(~0, pos, plen); icv[0] = crc;