Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56c52da2 authored by Jouni Malinen's avatar Jouni Malinen Committed by Johannes Berg
Browse files

mac80111: Add BIP-CMAC-256 cipher



This allows mac80211 to configure BIP-CMAC-256 to the driver and also
use software-implementation within mac80211 when the driver does not
support this with hardware accelaration.

Signed-off-by: default avatarJouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2b2ba0db
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1017,6 +1017,15 @@ struct ieee80211_mmie {
	u8 mic[8];
} __packed;

/* Management MIC information element (IEEE 802.11w) for GMAC and CMAC-256 */
struct ieee80211_mmie_16 {
	u8 element_id;
	u8 length;
	__le16 key_id;
	u8 sequence_number[6];
	u8 mic[16];
} __packed;

struct ieee80211_vendor_ie {
	u8 element_id;
	u8 len;
+26 −8
Original line number Diff line number Diff line
@@ -18,8 +18,8 @@
#include "key.h"
#include "aes_cmac.h"

#define AES_CMAC_KEY_LEN 16
#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
#define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
#define AAD_LEN 20


@@ -35,9 +35,9 @@ static void gf_mulx(u8 *pad)
		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
}


static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
				const u8 *addr[], const size_t *len, u8 *mac)
static void aes_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
			    const u8 *addr[], const size_t *len, u8 *mac,
			    size_t mac_len)
{
	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
	const u8 *pos, *end;
@@ -88,7 +88,7 @@ static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem,
	for (i = 0; i < AES_BLOCK_SIZE; i++)
		pad[i] ^= cbc[i];
	crypto_cipher_encrypt_one(tfm, pad, pad);
	memcpy(mac, pad, CMAC_TLEN);
	memcpy(mac, pad, mac_len);
}


@@ -107,17 +107,35 @@ void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
	addr[2] = zero;
	len[2] = CMAC_TLEN;

	aes_128_cmac_vector(tfm, 3, addr, len, mic);
	aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN);
}

void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
			    const u8 *data, size_t data_len, u8 *mic)
{
	const u8 *addr[3];
	size_t len[3];
	u8 zero[CMAC_TLEN_256];

	memset(zero, 0, CMAC_TLEN_256);
	addr[0] = aad;
	len[0] = AAD_LEN;
	addr[1] = data;
	len[1] = data_len - CMAC_TLEN_256;
	addr[2] = zero;
	len[2] = CMAC_TLEN_256;

	aes_cmac_vector(tfm, 3, addr, len, mic, CMAC_TLEN_256);
}

struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[])
struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
						   size_t key_len)
{
	struct crypto_cipher *tfm;

	tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
	if (!IS_ERR(tfm))
		crypto_cipher_setkey(tfm, key, AES_CMAC_KEY_LEN);
		crypto_cipher_setkey(tfm, key, key_len);

	return tfm;
}
+4 −1
Original line number Diff line number Diff line
@@ -11,9 +11,12 @@

#include <linux/crypto.h>

struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[]);
struct crypto_cipher *ieee80211_aes_cmac_key_setup(const u8 key[],
						   size_t key_len);
void ieee80211_aes_cmac(struct crypto_cipher *tfm, const u8 *aad,
			const u8 *data, size_t data_len, u8 *mic);
void ieee80211_aes_cmac_256(struct crypto_cipher *tfm, const u8 *aad,
			    const u8 *data, size_t data_len, u8 *mic);
void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm);

#endif /* AES_CMAC_H */
+2 −0
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
	case WLAN_CIPHER_SUITE_CCMP:
	case WLAN_CIPHER_SUITE_CCMP_256:
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
	case WLAN_CIPHER_SUITE_GCMP:
	case WLAN_CIPHER_SUITE_GCMP_256:
		break;
@@ -362,6 +363,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
		params.seq_len = 6;
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
		seq[0] = pn64;
		seq[1] = pn64 >> 8;
+4 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
				(u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		pn = atomic64_read(&key->u.aes_cmac.tx_pn);
		len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
				(u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
@@ -153,6 +154,7 @@ static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
		len = p - buf;
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		rpn = key->u.aes_cmac.rx_pn;
		p += scnprintf(p, sizeof(buf)+buf-p,
			       "%02x%02x%02x%02x%02x%02x\n",
@@ -191,6 +193,7 @@ static ssize_t key_replays_read(struct file *file, char __user *userbuf,
		len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
		break;
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		len = scnprintf(buf, sizeof(buf), "%u\n",
				key->u.aes_cmac.replays);
		break;
@@ -214,6 +217,7 @@ static ssize_t key_icverrors_read(struct file *file, char __user *userbuf,

	switch (key->conf.cipher) {
	case WLAN_CIPHER_SUITE_AES_CMAC:
	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
		len = scnprintf(buf, sizeof(buf), "%u\n",
				key->u.aes_cmac.icverrors);
		break;
Loading