[net80211] begin fleshing out new hardware crypto offload features.

* extend the keycache flag word to be 32 bits, not 16 bits
* add new key flags for transmit:
  + IEEE80211_KEY_NOIV: Don't insert IV in the payload when transmitting data frames;
  + IEEE80211_KEY_NOIVMGT:  Don't insert IV in the payload when transmitting MIC frames;
  + IEEE80211_KEY_NOMIC: Don't insert MIC in the payload when transmitting data frames;
  + IEEE80211_KEY_NOMICMGT: don't insert MIC in the payload when transmitting management
    frames.

* teach ieee80211_crypto_demic() about hardware decrypted frames:
  + if frames are hardware decrypted and the frame has failed MIC, treat it as a
     michael failure.
  + if frames are hardware decrypted and the frame has stripped MIC, we can't check the
    MIC in the payload - we don't have anything to compare it against.

This is only part of the work required to successfully transmit/receive
hardware crypto frames such as the qualcomm atheros 11ac offload chips.

There will be further work in the transmit and receive path before this
can be done by default.

Reviewed by:	avos
Differential Revision:	https://reviews.freebsd.org/D8364
This commit is contained in:
Adrian Chadd 2016-11-05 22:41:22 +00:00
parent 374d225e54
commit ee9d294b36
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=308354
2 changed files with 76 additions and 25 deletions

View File

@ -633,6 +633,61 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
#undef IEEE80211_WEP_HDRLEN
}
/*
* Check and remove any MIC.
*/
int
ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
struct mbuf *m, int force)
{
const struct ieee80211_cipher *cip;
const struct ieee80211_rx_stats *rxs;
struct ieee80211_frame *wh;
rxs = ieee80211_get_rx_params_ptr(m);
wh = mtod(m, struct ieee80211_frame *);
/*
* Handle demic / mic errors from hardware-decrypted offload devices.
*/
if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) {
if (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC) {
/*
* Hardware has said MIC failed. We don't care about
* whether it was stripped or not.
*
* Eventually - teach the demic methods in crypto
* modules to handle a NULL key and not to dereference
* it.
*/
ieee80211_notify_michael_failure(vap, wh, -1);
return (0);
}
if (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP) {
/*
* Hardware has decrypted and not indicated a
* MIC failure and has stripped the MIC.
* We may not have a key, so for now just
* return OK.
*/
return (1);
}
}
/*
* If we don't have a key at this point then we don't
* have to demic anything.
*/
if (k == NULL)
return (1);
cip = k->wk_cipher;
return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1);
}
static void
load_ucastkey(void *arg, struct ieee80211_node *ni)
{

View File

@ -73,19 +73,25 @@ typedef uint16_t ieee80211_keyix; /* h/w key index */
struct ieee80211_key {
uint8_t wk_keylen; /* key length in bytes */
uint8_t wk_pad;
uint16_t wk_flags;
#define IEEE80211_KEY_XMIT 0x0001 /* key used for xmit */
#define IEEE80211_KEY_RECV 0x0002 /* key used for recv */
#define IEEE80211_KEY_GROUP 0x0004 /* key used for WPA group operation */
#define IEEE80211_KEY_NOREPLAY 0x0008 /* ignore replay failures */
#define IEEE80211_KEY_SWENCRYPT 0x0010 /* host-based encrypt */
#define IEEE80211_KEY_SWDECRYPT 0x0020 /* host-based decrypt */
#define IEEE80211_KEY_SWENMIC 0x0040 /* host-based enmic */
#define IEEE80211_KEY_SWDEMIC 0x0080 /* host-based demic */
#define IEEE80211_KEY_DEVKEY 0x0100 /* device key request completed */
#define IEEE80211_KEY_CIPHER0 0x1000 /* cipher-specific action 0 */
#define IEEE80211_KEY_CIPHER1 0x2000 /* cipher-specific action 1 */
uint8_t wk_pad; /* .. some drivers use this. Fix that. */
uint8_t wk_pad1[2];
uint32_t wk_flags;
#define IEEE80211_KEY_XMIT 0x00000001 /* key used for xmit */
#define IEEE80211_KEY_RECV 0x00000002 /* key used for recv */
#define IEEE80211_KEY_GROUP 0x00000004 /* key used for WPA group operation */
#define IEEE80211_KEY_NOREPLAY 0x00000008 /* ignore replay failures */
#define IEEE80211_KEY_SWENCRYPT 0x00000010 /* host-based encrypt */
#define IEEE80211_KEY_SWDECRYPT 0x00000020 /* host-based decrypt */
#define IEEE80211_KEY_SWENMIC 0x00000040 /* host-based enmic */
#define IEEE80211_KEY_SWDEMIC 0x00000080 /* host-based demic */
#define IEEE80211_KEY_DEVKEY 0x00000100 /* device key request completed */
#define IEEE80211_KEY_CIPHER0 0x00001000 /* cipher-specific action 0 */
#define IEEE80211_KEY_CIPHER1 0x00002000 /* cipher-specific action 1 */
#define IEEE80211_KEY_NOIV 0x00004000 /* don't insert IV/MIC for !mgmt */
#define IEEE80211_KEY_NOIVMGT 0x00008000 /* don't insert IV/MIC for mgmt */
#define IEEE80211_KEY_NOMIC 0x00010000 /* don't insert MIC for !mgmt */
#define IEEE80211_KEY_NOMICMGT 0x00020000 /* don't insert MIC for mgmt */
ieee80211_keyix wk_keyix; /* h/w key index */
ieee80211_keyix wk_rxkeyix; /* optional h/w rx key index */
uint8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
@ -203,18 +209,8 @@ struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
struct mbuf *);
struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
struct mbuf *, int);
/*
* Check and remove any MIC.
*/
static __inline int
ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
struct mbuf *m, int force)
{
const struct ieee80211_cipher *cip = k->wk_cipher;
return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1);
}
int ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
struct mbuf *, int);
/*
* Add any MIC.
*/