diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h index 57d05ad791c8..d7ac436f9bf5 100644 --- a/sys/net80211/ieee80211_crypto.h +++ b/sys/net80211/ieee80211_crypto.h @@ -78,6 +78,7 @@ struct ieee80211_key { #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 */ @@ -98,7 +99,8 @@ struct ieee80211_key { uint8_t wk_macaddr[IEEE80211_ADDR_LEN]; }; #define IEEE80211_KEY_COMMON /* common flags passed in by apps */\ - (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP) + (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV | IEEE80211_KEY_GROUP | \ + IEEE80211_KEY_NOREPLAY) #define IEEE80211_KEY_DEVICE /* flags owned by device driver */\ (IEEE80211_KEY_DEVKEY|IEEE80211_KEY_CIPHER0|IEEE80211_KEY_CIPHER1) diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c index 9ad240971bd2..cb9ed0af0149 100644 --- a/sys/net80211/ieee80211_crypto_ccmp.c +++ b/sys/net80211/ieee80211_crypto_ccmp.c @@ -226,14 +226,8 @@ ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) } tid = ieee80211_gettid(wh); pn = READ_6(ivp[0], ivp[1], ivp[4], ivp[5], ivp[6], ivp[7]); - /* - * NB: Multiple stations are using the same key in - * IBSS mode, there is currently no way to sync keyrsc - * counters without discarding too many frames. - */ - if (vap->iv_opmode != IEEE80211_M_IBSS && - vap->iv_opmode != IEEE80211_M_AHDEMO && - pn <= k->wk_keyrsc[tid]) { + if (pn <= k->wk_keyrsc[tid] && + (k->wk_flags & IEEE80211_KEY_NOREPLAY) == 0) { /* * Replay violation. */ diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c index 0f17c173e9e4..05d9c74bdf28 100644 --- a/sys/net80211/ieee80211_crypto_tkip.c +++ b/sys/net80211/ieee80211_crypto_tkip.c @@ -281,14 +281,8 @@ tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) tid = ieee80211_gettid(wh); ctx->rx_rsc = READ_6(ivp[2], ivp[0], ivp[4], ivp[5], ivp[6], ivp[7]); - /* - * NB: Multiple stations are using the same key in - * IBSS mode, there is currently no way to sync keyrsc - * counters without discarding too many frames. - */ - if (vap->iv_opmode != IEEE80211_M_IBSS && - vap->iv_opmode != IEEE80211_M_AHDEMO && - ctx->rx_rsc <= k->wk_keyrsc[tid]) { + if (ctx->rx_rsc <= k->wk_keyrsc[tid] && + (k->wk_flags & IEEE80211_KEY_NOREPLAY) == 0) { /* * Replay violation; notify upper layer. */ diff --git a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c index 65989c207eee..a9c86a6a16f3 100644 --- a/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c +++ b/usr.sbin/wpa/wpa_supplicant/driver_freebsd.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -47,8 +48,34 @@ struct wpa_driver_bsd_data { int lastssid_len; uint32_t drivercaps; /* general driver capabilities */ uint32_t cryptocaps; /* hardware crypto support */ + enum ieee80211_opmode opmode; /* operation mode */ }; +static enum ieee80211_opmode +get80211opmode(struct wpa_driver_bsd_data *drv) +{ + struct ifmediareq ifmr; + + (void) memset(&ifmr, 0, sizeof(ifmr)); + (void) strncpy(ifmr.ifm_name, drv->ifname, sizeof(ifmr.ifm_name)); + + if (ioctl(drv->sock, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) { + if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) { + if (ifmr.ifm_current & IFM_FLAG0) + return IEEE80211_M_AHDEMO; + else + return IEEE80211_M_IBSS; + } + if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP) + return IEEE80211_M_HOSTAP; + if (ifmr.ifm_current & IFM_IEEE80211_MONITOR) + return IEEE80211_M_MONITOR; + if (ifmr.ifm_current & IFM_IEEE80211_MBSS) + return IEEE80211_M_MBSS; + } + return IEEE80211_M_STA; +} + static int set80211var(struct wpa_driver_bsd_data *drv, int op, const void *arg, int arg_len) { @@ -332,6 +359,12 @@ wpa_driver_bsd_set_key(void *priv, wpa_alg alg, } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; + /* + * Ignore replay failures in IBSS and AHDEMO mode. + */ + if (drv->opmode == IEEE80211_M_IBSS || + drv->opmode == IEEE80211_M_AHDEMO) + wk.ik_flags |= IEEE80211_KEY_NOREPLAY; wk.ik_keylen = key_len; memcpy(&wk.ik_keyrsc, seq, seq_len); wk.ik_keyrsc = le64toh(wk.ik_keyrsc); @@ -861,6 +894,7 @@ wpa_driver_bsd_init(void *ctx, const char *ifname) __func__, strerror(errno)); goto fail; } + drv->opmode = get80211opmode(drv); return drv; fail: