[BACK]Return to ieee80211_crypto.h CVS log [TXT][DIR] Up to [local] / src / sys / net80211

File: [local] / src / sys / net80211 / ieee80211_crypto.h (download)

Revision 1.27, Fri May 15 14:21:09 2020 UTC (4 years ago) by stsp
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, HEAD
Changes since 1.26: +5 -1 lines

Fix CCMP replay check with 11n Rx aggregation and CCMP hardware offloading.

So far, drivers using hardware CCMP decryption were expected to keep the
most recently seen CCMP packet number (PN) up-to-date, and to discard frames
with lower PNs as replays.

A-MPDU subframes may legitimately arrive out of order, and the drivers skipped
CCMP replay checking for such frames. Re-ordering happens in ieee80211_inputm(),
after the driver is done with a frame. Drivers cannot tell replayed frames
apart from legitimate out-of-order retransmissions.

To fix this, update the PN value in ieee80211_inputm() after subframes have
been reordered into their proper sequence. Drivers still perform replay checks
but they no longer have to worry about updating the last seen PN value.

The 802.11 spec confirms that replay checking is supposed to happen after
A-MPDU re-ordering.

Tested by jmc@, benno@, solene@, and myself with the following drivers:
  athn(4), iwn(4), iwm(4), wpi(4), urtwn(4)

ok solene@

/*	$OpenBSD: ieee80211_crypto.h,v 1.27 2020/05/15 14:21:09 stsp Exp $	*/

/*-
 * Copyright (c) 2007,2008 Damien Bergamini <damien.bergamini@free.fr>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _NET80211_IEEE80211_CRYPTO_H_
#define _NET80211_IEEE80211_CRYPTO_H_

/*
 * 802.11 protocol crypto-related definitions.
 */

/*
 * 802.11 ciphers.
 */
enum ieee80211_cipher {
	IEEE80211_CIPHER_NONE		= 0x00000000,
	IEEE80211_CIPHER_USEGROUP	= 0x00000001,
	IEEE80211_CIPHER_WEP40		= 0x00000002,
	IEEE80211_CIPHER_TKIP		= 0x00000004,
	IEEE80211_CIPHER_CCMP		= 0x00000008,
	IEEE80211_CIPHER_WEP104		= 0x00000010,
	IEEE80211_CIPHER_BIP		= 0x00000020	/* 11w */
};

/*
 * 802.11 Authentication and Key Management Protocols.
 */
enum ieee80211_akm {
	IEEE80211_AKM_NONE		= 0x00000000,
	IEEE80211_AKM_8021X		= 0x00000001,
	IEEE80211_AKM_PSK		= 0x00000002,
	IEEE80211_AKM_SHA256_8021X	= 0x00000004,	/* 11w */
	IEEE80211_AKM_SHA256_PSK	= 0x00000008	/* 11w */
};

#define IEEE80211_TKIP_HDRLEN	8
#define IEEE80211_TKIP_MICLEN	8
#define IEEE80211_TKIP_ICVLEN	4
#define IEEE80211_CCMP_HDRLEN	8
#define IEEE80211_CCMP_MICLEN	8

#define IEEE80211_PMK_LEN	32

#ifdef _KERNEL 

static __inline int
ieee80211_is_8021x_akm(enum ieee80211_akm akm)
{
	return akm == IEEE80211_AKM_8021X ||
	    akm == IEEE80211_AKM_SHA256_8021X;
}

static __inline int
ieee80211_is_sha256_akm(enum ieee80211_akm akm)
{
	return akm == IEEE80211_AKM_SHA256_8021X ||
	    akm == IEEE80211_AKM_SHA256_PSK;
}

struct ieee80211_key {
	u_int8_t		k_id;		/* identifier (0-5) */
	enum ieee80211_cipher	k_cipher;
	u_int			k_flags;
#define IEEE80211_KEY_GROUP	0x00000001	/* group data key */
#define IEEE80211_KEY_TX	0x00000002	/* Tx+Rx */
#define IEEE80211_KEY_IGTK	0x00000004	/* integrity group key */
#define IEEE80211_KEY_SWCRYPTO	0x00000080	/* loaded for software crypto */

	u_int			k_len;
	u_int64_t		k_rsc[IEEE80211_NUM_TID];
	u_int64_t		k_mgmt_rsc;
	u_int64_t		k_tsc;
	u_int8_t		k_key[32];
	void			*k_priv;
};

#define IEEE80211_KEYBUF_SIZE	16

/*
 * Entry in the PMKSA cache.
 */
struct ieee80211_pmk {
	enum ieee80211_akm	pmk_akm;
	u_int32_t		pmk_lifetime;
#define IEEE80211_PMK_INFINITE	0

	u_int8_t		pmk_pmkid[IEEE80211_PMKID_LEN];
	u_int8_t		pmk_macaddr[IEEE80211_ADDR_LEN];
	u_int8_t		pmk_key[IEEE80211_PMK_LEN];

	TAILQ_ENTRY(ieee80211_pmk) pmk_next;
};

/* forward references */
struct	ieee80211com;
struct	ieee80211_node;

void	ieee80211_crypto_attach(struct ifnet *);
void	ieee80211_crypto_detach(struct ifnet *);

void	ieee80211_crypto_clear_groupkeys(struct ieee80211com *);
struct	ieee80211_key *ieee80211_get_txkey(struct ieee80211com *,
	    const struct ieee80211_frame *, struct ieee80211_node *);
struct	ieee80211_key *ieee80211_get_rxkey(struct ieee80211com *,
	    struct mbuf *, struct ieee80211_node *);
struct	mbuf *ieee80211_encrypt(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_decrypt(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_node *);

int	ieee80211_set_key(struct ieee80211com *, struct ieee80211_node *,
	    struct ieee80211_key *);
void	ieee80211_delete_key(struct ieee80211com *, struct ieee80211_node *,
	    struct ieee80211_key *);

void	ieee80211_eapol_key_mic(struct ieee80211_eapol_key *,
	    const u_int8_t *);
int	ieee80211_eapol_key_check_mic(struct ieee80211_eapol_key *,
	    const u_int8_t *);
#ifndef IEEE80211_STA_ONLY
void	ieee80211_eapol_key_encrypt(struct ieee80211com *,
	    struct ieee80211_eapol_key *, const u_int8_t *);
#endif
int	ieee80211_eapol_key_decrypt(struct ieee80211_eapol_key *,
	    const u_int8_t *);

struct	ieee80211_pmk *ieee80211_pmksa_add(struct ieee80211com *,
	    enum ieee80211_akm, const u_int8_t *, const u_int8_t *, u_int32_t);
struct	ieee80211_pmk *ieee80211_pmksa_find(struct ieee80211com *,
	    struct ieee80211_node *, const u_int8_t *);
void	ieee80211_derive_ptk(enum ieee80211_akm, const u_int8_t *,
	    const u_int8_t *, const u_int8_t *, const u_int8_t *,
	    const u_int8_t *, struct ieee80211_ptk *);
int	ieee80211_cipher_keylen(enum ieee80211_cipher);

int	ieee80211_wep_set_key(struct ieee80211com *, struct ieee80211_key *);
void	ieee80211_wep_delete_key(struct ieee80211com *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_wep_encrypt(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_wep_decrypt(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);

int	ieee80211_tkip_set_key(struct ieee80211com *, struct ieee80211_key *);
void	ieee80211_tkip_delete_key(struct ieee80211com *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_tkip_encrypt(struct ieee80211com *,
	    struct mbuf *, struct ieee80211_key *);
int	ieee80211_tkip_get_tsc(uint64_t *, uint64_t **, struct mbuf *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_tkip_decrypt(struct ieee80211com *,
	    struct mbuf *, struct ieee80211_key *);
void	ieee80211_tkip_mic(struct mbuf *, int, const u_int8_t *,
	    u_int8_t[IEEE80211_TKIP_MICLEN]);
void	ieee80211_michael_mic_failure(struct ieee80211com *, u_int64_t);
#ifndef IEEE80211_STA_ONLY
void	ieee80211_michael_mic_failure_timeout(void *);
#endif

int	ieee80211_ccmp_set_key(struct ieee80211com *, struct ieee80211_key *);
void	ieee80211_ccmp_delete_key(struct ieee80211com *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_ccmp_encrypt(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);
int	ieee80211_ccmp_get_pn(uint64_t *, uint64_t **, struct mbuf *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_ccmp_decrypt(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);

int	ieee80211_bip_set_key(struct ieee80211com *, struct ieee80211_key *);
void	ieee80211_bip_delete_key(struct ieee80211com *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_bip_encap(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);
struct	mbuf *ieee80211_bip_decap(struct ieee80211com *, struct mbuf *,
	    struct ieee80211_key *);

#endif /* _KERNEL */
#endif /* _NET80211_IEEE80211_CRYPTO_H_ */