The Linux Kernel Mailing List
 help / color / mirror / Atom feed
From: Eric Biggers <ebiggers@kernel.org>
To: linux-crypto@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH 27/33] wifi: ipw2x00: Use AES-CCM library
Date: Mon,  6 Jul 2026 22:34:57 -0700	[thread overview]
Message-ID: <20260707053503.209874-28-ebiggers@kernel.org> (raw)
In-Reply-To: <20260707053503.209874-1-ebiggers@kernel.org>

Now that there's a library API for AES-CCM, use it instead of a
"ccm(aes)" crypto_aead.

This significantly simplifies the code:

- Dynamic memory allocations go away, including ones during Tx and Rx.

- The additional authenticated data is now just constructed on the
  stack, as it no longer needs to be representable in a scatterlist.

- The AES-CCM library supports variable-length nonces via the
  self-explanatory nonce_len parameter, so for the needed 13-byte nonce
  just use that instead of the odd workaround used by "ccm(aes)" where
  the nonce was prefixed with a byte containing '14 - nonce_len'.

Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
 drivers/net/wireless/intel/ipw2x00/Kconfig    |   2 +-
 .../intel/ipw2x00/libipw_crypto_ccmp.c        | 117 +++++-------------
 2 files changed, 29 insertions(+), 90 deletions(-)

diff --git a/drivers/net/wireless/intel/ipw2x00/Kconfig b/drivers/net/wireless/intel/ipw2x00/Kconfig
index b508f14542d5..a1073d34f634 100644
--- a/drivers/net/wireless/intel/ipw2x00/Kconfig
+++ b/drivers/net/wireless/intel/ipw2x00/Kconfig
@@ -153,8 +153,8 @@ config LIBIPW
 	tristate
 	depends on PCI && CFG80211
 	select WIRELESS_EXT
-	select CRYPTO
 	select CRYPTO_LIB_ARC4
+	select CRYPTO_LIB_AES_CCM
 	select CRC32
 	help
 	This option enables the hardware independent IEEE 802.11
diff --git a/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c
index 631a4dd86cab..aa6dce7acba1 100644
--- a/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c
+++ b/drivers/net/wireless/intel/ipw2x00/libipw_crypto_ccmp.c
@@ -19,15 +19,14 @@
 #include <asm/string.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
-#include <linux/crypto.h>
-#include <crypto/aead.h>
+#include <crypto/aes-ccm.h>
 #include "libipw.h"
 
-#define AES_BLOCK_LEN 16
 #define CCMP_HDR_LEN 8
 #define CCMP_MIC_LEN 8
 #define CCMP_TK_LEN 16
 #define CCMP_PN_LEN 6
+#define CCMP_NONCE_LEN 13
 
 struct libipw_ccmp_data {
 	u8 key[CCMP_TK_LEN];
@@ -42,11 +41,7 @@ struct libipw_ccmp_data {
 
 	int key_idx;
 
-	struct crypto_aead *tfm;
-
-	/* scratch buffers for virt_to_page() (crypto API) */
-	u8 tx_aad[2 * AES_BLOCK_LEN];
-	u8 rx_aad[2 * AES_BLOCK_LEN];
+	struct aes_ccm_key ccm_key;
 };
 
 static void *libipw_ccmp_init(int key_idx)
@@ -55,37 +50,20 @@ static void *libipw_ccmp_init(int key_idx)
 
 	priv = kzalloc_obj(*priv, GFP_ATOMIC);
 	if (priv == NULL)
-		goto fail;
+		return NULL;
 	priv->key_idx = key_idx;
 
-	priv->tfm = crypto_alloc_aead("ccm(aes)", 0, CRYPTO_ALG_ASYNC);
-	if (IS_ERR(priv->tfm)) {
-		priv->tfm = NULL;
-		goto fail;
-	}
-
 	return priv;
-
-      fail:
-	if (priv) {
-		if (priv->tfm)
-			crypto_free_aead(priv->tfm);
-		kfree(priv);
-	}
-
-	return NULL;
 }
 
 static void libipw_ccmp_deinit(void *priv)
 {
-	struct libipw_ccmp_data *_priv = priv;
-	if (_priv && _priv->tfm)
-		crypto_free_aead(_priv->tfm);
-	kfree(priv);
+	kfree_sensitive(priv);
 }
 
-static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr,
-				const u8 *pn, u8 *iv, u8 *aad)
+static int ccmp_init_nonce_and_aad(const struct ieee80211_hdr *hdr,
+				   const u8 *pn, u8 nonce[CCMP_NONCE_LEN],
+				   u8 *aad)
 {
 	u8 *pos, qc = 0;
 	size_t aad_len;
@@ -105,19 +83,11 @@ static int ccmp_init_iv_and_aad(const struct ieee80211_hdr *hdr,
 		aad_len += 2;
 	}
 
-	/* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
-	 * mode authentication are not allowed to collide, yet both are derived
-	 * from the same vector. We only set L := 1 here to indicate that the
-	 * data size can be represented in (L+1) bytes. The CCM layer will take
-	 * care of storing the data length in the top (L+1) bytes and setting
-	 * and clearing the other bits as is required to derive the two IVs.
-	 */
-	iv[0] = 0x1;
-
 	/* Nonce: QC | A2 | PN */
-	iv[1] = qc;
-	memcpy(iv + 2, hdr->addr2, ETH_ALEN);
-	memcpy(iv + 8, pn, CCMP_PN_LEN);
+	nonce[0] = qc;
+	memcpy(nonce + 1, hdr->addr2, ETH_ALEN);
+	memcpy(nonce + 7, pn, CCMP_PN_LEN);
+	static_assert(7 + CCMP_PN_LEN == CCMP_NONCE_LEN);
 
 	/* AAD:
 	 * FC with bits 4..6 and 11..13 masked to zero; 14 is always one
@@ -184,12 +154,9 @@ static int libipw_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 {
 	struct libipw_ccmp_data *key = priv;
 	struct ieee80211_hdr *hdr;
-	struct aead_request *req;
-	struct scatterlist sg[2];
-	u8 *aad = key->tx_aad;
-	u8 iv[AES_BLOCK_LEN];
+	u8 aad[2 * AES_BLOCK_SIZE];
+	u8 nonce[CCMP_NONCE_LEN];
 	int len, data_len, aad_len;
-	int ret;
 
 	if (skb_tailroom(skb) < CCMP_MIC_LEN || skb->len < hdr_len)
 		return -1;
@@ -199,28 +166,16 @@ static int libipw_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	if (len < 0)
 		return -1;
 
-	req = aead_request_alloc(key->tfm, GFP_ATOMIC);
-	if (!req)
-		return -ENOMEM;
-
 	hdr = (struct ieee80211_hdr *)skb->data;
-	aad_len = ccmp_init_iv_and_aad(hdr, key->tx_pn, iv, aad);
+	aad_len = ccmp_init_nonce_and_aad(hdr, key->tx_pn, nonce, aad);
 
 	skb_put(skb, CCMP_MIC_LEN);
 
-	sg_init_table(sg, 2);
-	sg_set_buf(&sg[0], aad, aad_len);
-	sg_set_buf(&sg[1], skb->data + hdr_len + CCMP_HDR_LEN,
-		   data_len + CCMP_MIC_LEN);
-
-	aead_request_set_callback(req, 0, NULL, NULL);
-	aead_request_set_ad(req, aad_len);
-	aead_request_set_crypt(req, sg, sg, data_len, iv);
-
-	ret = crypto_aead_encrypt(req);
-	aead_request_free(req);
-
-	return ret;
+	return aes_ccm_encrypt(skb->data + hdr_len + CCMP_HDR_LEN,
+			       skb->data + hdr_len + CCMP_HDR_LEN + data_len,
+			       skb->data + hdr_len + CCMP_HDR_LEN, data_len,
+			       aad, aad_len, nonce, CCMP_NONCE_LEN,
+			       &key->ccm_key);
 }
 
 /*
@@ -249,10 +204,8 @@ static int libipw_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	struct libipw_ccmp_data *key = priv;
 	u8 keyidx, *pos;
 	struct ieee80211_hdr *hdr;
-	struct aead_request *req;
-	struct scatterlist sg[2];
-	u8 *aad = key->rx_aad;
-	u8 iv[AES_BLOCK_LEN];
+	u8 aad[2 * AES_BLOCK_SIZE];
+	u8 nonce[CCMP_NONCE_LEN];
 	u8 pn[6];
 	int aad_len, ret;
 	size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN;
@@ -303,23 +256,11 @@ static int libipw_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 		return -4;
 	}
 
-	req = aead_request_alloc(key->tfm, GFP_ATOMIC);
-	if (!req)
-		return -ENOMEM;
-
-	aad_len = ccmp_init_iv_and_aad(hdr, pn, iv, aad);
-
-	sg_init_table(sg, 2);
-	sg_set_buf(&sg[0], aad, aad_len);
-	sg_set_buf(&sg[1], pos, data_len);
-
-	aead_request_set_callback(req, 0, NULL, NULL);
-	aead_request_set_ad(req, aad_len);
-	aead_request_set_crypt(req, sg, sg, data_len, iv);
-
-	ret = crypto_aead_decrypt(req);
-	aead_request_free(req);
+	aad_len = ccmp_init_nonce_and_aad(hdr, pn, nonce, aad);
 
+	ret = aes_ccm_decrypt(pos, pos, pos + data_len - CCMP_MIC_LEN,
+			      data_len - CCMP_MIC_LEN, aad, aad_len, nonce,
+			      CCMP_NONCE_LEN, &key->ccm_key);
 	if (ret) {
 		net_dbg_ratelimited("CCMP: decrypt failed: STA=%pM (%d)\n",
 				    hdr->addr2, ret);
@@ -341,12 +282,10 @@ static int libipw_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
 {
 	struct libipw_ccmp_data *data = priv;
 	int keyidx;
-	struct crypto_aead *tfm = data->tfm;
 
 	keyidx = data->key_idx;
 	memset(data, 0, sizeof(*data));
 	data->key_idx = keyidx;
-	data->tfm = tfm;
 	if (len == CCMP_TK_LEN) {
 		memcpy(data->key, key, CCMP_TK_LEN);
 		data->key_set = 1;
@@ -358,8 +297,8 @@ static int libipw_ccmp_set_key(void *key, int len, u8 * seq, void *priv)
 			data->rx_pn[4] = seq[1];
 			data->rx_pn[5] = seq[0];
 		}
-		if (crypto_aead_setauthsize(data->tfm, CCMP_MIC_LEN) ||
-		    crypto_aead_setkey(data->tfm, data->key, CCMP_TK_LEN))
+		if (aes_ccm_preparekey(&data->ccm_key, data->key, CCMP_TK_LEN,
+				       CCMP_MIC_LEN))
 			return -1;
 	} else if (len == 0)
 		data->key_set = 0;
-- 
2.54.0


  parent reply	other threads:[~2026-07-07  5:37 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  5:34 [PATCH 00/33] Library APIs for AES encryption modes Eric Biggers
2026-07-07  5:34 ` [PATCH 01/33] crypto: xts - Split out __xts_verify_key() helper Eric Biggers
2026-07-07 13:20   ` Thomas Huth
2026-07-07  5:34 ` [PATCH 02/33] lib/crypto: aes: Add ECB support Eric Biggers
2026-07-07 13:59   ` Thomas Huth
2026-07-07 19:22     ` Eric Biggers
2026-07-08  5:29       ` Thomas Huth
2026-07-07  5:34 ` [PATCH 03/33] lib/crypto: aes: Add CBC and CBC-CTS support Eric Biggers
2026-07-07  5:34 ` [PATCH 04/33] lib/crypto: aes: Add CTR and XCTR support Eric Biggers
2026-07-07  5:34 ` [PATCH 05/33] lib/crypto: aes: Add XTS support Eric Biggers
2026-07-07  5:34 ` [PATCH 06/33] lib/crypto: aes: Add GCM support Eric Biggers
2026-07-07  5:34 ` [PATCH 07/33] lib/crypto: aes: Add CCM support Eric Biggers
2026-07-07  5:34 ` [PATCH 08/33] crypto: aes - Add ECB support using library Eric Biggers
2026-07-07  5:34 ` [PATCH 09/33] crypto: aes - Add CBC and CBC-CTS " Eric Biggers
2026-07-07  5:34 ` [PATCH 10/33] crypto: aes - Add CTR and XCTR " Eric Biggers
2026-07-07  5:34 ` [PATCH 11/33] crypto: aes - Add XTS " Eric Biggers
2026-07-07  5:34 ` [PATCH 12/33] crypto: aes - Add GCM " Eric Biggers
2026-07-07  5:34 ` [PATCH 13/33] crypto: aes - Add CCM " Eric Biggers
2026-07-07  5:34 ` [PATCH 14/33] x86/sev: Use new AES-GCM library Eric Biggers
2026-07-07  5:34 ` [PATCH 15/33] lib/crypto: aesgcm: Remove old " Eric Biggers
2026-07-07  5:34 ` [PATCH 16/33] crypto: aes - Remove AES-CBC-MAC support Eric Biggers
2026-07-07  5:34 ` [PATCH 17/33] lib/crypto: aes: Remove aes_cbcmac_* functions Eric Biggers
2026-07-07  5:34 ` [PATCH 18/33] fscrypt: Use aes_ecb_encrypt() for v1 key derivation Eric Biggers
2026-07-07  5:34 ` [PATCH 19/33] KEYS: encrypted: Use AES-CBC library instead of crypto_skcipher Eric Biggers
2026-07-07  5:34 ` [PATCH 20/33] KEYS: trusted: dcp: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07  5:34 ` [PATCH 21/33] libceph: Use AES-CBC library in ceph_aes_crypt() Eric Biggers
2026-07-07  5:34 ` [PATCH 22/33] libceph: Reimplement messenger v2 encryption using AES-GCM library Eric Biggers
2026-07-07  5:34 ` [PATCH 23/33] wifi: mac80211: Use AES-CTR library in fils_aead.c Eric Biggers
2026-07-07  5:34 ` [PATCH 24/33] wifi: mac80211: Use AES-GCM library for GMAC suite Eric Biggers
2026-07-07  5:34 ` [PATCH 25/33] wifi: mac80211: Use crypto libraries for GCMP and CCMP suites Eric Biggers
2026-07-07  5:34 ` [PATCH 26/33] macsec: Use AES-GCM library instead of crypto_aead Eric Biggers
2026-07-07  5:34 ` Eric Biggers [this message]
2026-07-07  5:34 ` [PATCH 28/33] mac802154: Use AES-CCM and AES-CTR libraries Eric Biggers
2026-07-07  5:34 ` [PATCH 29/33] bpf: crypto: Use AES-CBC and AES-ECB libraries Eric Biggers
2026-07-07 15:01   ` Vadim Fedorenko
2026-07-07 18:20     ` Eric Biggers
2026-07-07 22:50       ` Vadim Fedorenko
2026-07-07 23:16         ` Eric Biggers
2026-07-08 11:47           ` Vadim Fedorenko
2026-07-07  5:35 ` [PATCH 30/33] bpf: crypto: Add AES-GCM support Eric Biggers
2026-07-07 15:02   ` Vadim Fedorenko
2026-07-07  5:35 ` [PATCH 31/33] smb: client: Use AES-GCM and AES-CCM libraries Eric Biggers
2026-07-07  5:35 ` [PATCH 32/33] ksmbd: " Eric Biggers
2026-07-07 10:51   ` Namjae Jeon
2026-07-07  5:35 ` [PATCH 33/33] net: tipc: Use AES-GCM library instead of crypto_aead Eric Biggers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260707053503.209874-28-ebiggers@kernel.org \
    --to=ebiggers@kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox