Crypto api changes:
o don't use the key index to identify when the driver has been asked to allocate a key slot, use an explicit flag; allows drivers to force s/w fallback for entries in the global table o change callback api to allocate driver resources for a crypto key: - de-const the key parameter so drivers can muck with the flags - on callback failure don't automatically try to setup s/w crypto; instead the driver must now mark the key entry for s/w crypto and the caller will re-attach the cipher module NB: api change permits drivers more control over fallback to s/w crypto (e.g. based on a limited number of h/w key slots)
This commit is contained in:
parent
45f856e3ac
commit
e6e547d57b
@ -141,7 +141,7 @@ static void ath_bmiss_proc(void *, int);
|
||||
static int ath_keyset(struct ath_softc *, const struct ieee80211_key *,
|
||||
struct ieee80211_node *);
|
||||
static int ath_key_alloc(struct ieee80211vap *,
|
||||
const struct ieee80211_key *,
|
||||
struct ieee80211_key *,
|
||||
ieee80211_keyix *, ieee80211_keyix *);
|
||||
static int ath_key_delete(struct ieee80211vap *,
|
||||
const struct ieee80211_key *);
|
||||
@ -2387,7 +2387,7 @@ key_alloc_single(struct ath_softc *sc,
|
||||
* 64 entries.
|
||||
*/
|
||||
static int
|
||||
ath_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k,
|
||||
ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
|
||||
|
@ -59,7 +59,7 @@ static const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX];
|
||||
* Default "null" key management routines.
|
||||
*/
|
||||
static int
|
||||
null_key_alloc(struct ieee80211vap *vap, const struct ieee80211_key *k,
|
||||
null_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
if (!(&vap->iv_nw_keys[0] <= k &&
|
||||
@ -116,7 +116,7 @@ cipher_attach(struct ieee80211vap *vap, struct ieee80211_key *key)
|
||||
*/
|
||||
static __inline int
|
||||
dev_key_alloc(struct ieee80211vap *vap,
|
||||
const struct ieee80211_key *key,
|
||||
struct ieee80211_key *key,
|
||||
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
|
||||
{
|
||||
return vap->iv_key_alloc(vap, key, keyix, rxkeyix);
|
||||
@ -335,15 +335,11 @@ ieee80211_crypto_newkey(struct ieee80211vap *vap,
|
||||
* whether or not it needs to do the cipher work.
|
||||
*/
|
||||
if (key->wk_cipher != cip || key->wk_flags != flags) {
|
||||
again:
|
||||
/*
|
||||
* Fillin the flags so cipher modules can see s/w
|
||||
* crypto requirements and potentially allocate
|
||||
* different state and/or attach different method
|
||||
* pointers.
|
||||
*
|
||||
* XXX this is not right when s/w crypto fallback
|
||||
* fails and we try to restore previous state.
|
||||
*/
|
||||
key->wk_flags = flags;
|
||||
keyctx = cip->ic_attach(vap, key);
|
||||
@ -372,36 +368,45 @@ again:
|
||||
* cipher template. Note also that when using software
|
||||
* crypto we also call the driver to give us a key index.
|
||||
*/
|
||||
if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
|
||||
if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) {
|
||||
if (!dev_key_alloc(vap, key, &keyix, &rxkeyix)) {
|
||||
/*
|
||||
* Driver has no room; fallback to doing crypto
|
||||
* in the host. We change the flags and start the
|
||||
* procedure over. If we get back here then there's
|
||||
* no hope and we bail. Note that this can leave
|
||||
* the key in a inconsistent state if the caller
|
||||
* continues to use it.
|
||||
* Unable to setup driver state.
|
||||
*/
|
||||
if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
|
||||
vap->iv_stats.is_crypto_swfallback++;
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: no h/w resources for cipher %s, "
|
||||
"falling back to s/w\n", __func__,
|
||||
cip->ic_name);
|
||||
oflags = key->wk_flags;
|
||||
flags |= IEEE80211_KEY_SWCRYPT;
|
||||
if (cipher == IEEE80211_CIPHER_TKIP)
|
||||
flags |= IEEE80211_KEY_SWMIC;
|
||||
goto again;
|
||||
}
|
||||
vap->iv_stats.is_crypto_keyfail++;
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: unable to setup cipher %s\n",
|
||||
__func__, cip->ic_name);
|
||||
return 0;
|
||||
}
|
||||
if (key->wk_flags != flags) {
|
||||
/*
|
||||
* Driver overrode flags we setup; typically because
|
||||
* resources were unavailable to handle _this_ key.
|
||||
* Re-attach the cipher context to allow cipher
|
||||
* modules to handle differing requirements.
|
||||
*/
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: driver override for cipher %s, flags "
|
||||
"0x%x -> 0x%x\n", __func__, cip->ic_name,
|
||||
oflags, key->wk_flags);
|
||||
keyctx = cip->ic_attach(vap, key);
|
||||
if (keyctx == NULL) {
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: unable to attach cipher %s with "
|
||||
"flags 0x%x\n", __func__, cip->ic_name,
|
||||
key->wk_flags);
|
||||
key->wk_flags = oflags; /* restore old flags */
|
||||
vap->iv_stats.is_crypto_attachfail++;
|
||||
return 0;
|
||||
}
|
||||
cipher_detach(key);
|
||||
key->wk_cipher = cip; /* XXX refcnt? */
|
||||
key->wk_private = keyctx;
|
||||
}
|
||||
key->wk_keyix = keyix;
|
||||
key->wk_rxkeyix = rxkeyix;
|
||||
key->wk_flags |= IEEE80211_KEY_DEVKEY;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -412,8 +417,6 @@ again:
|
||||
static int
|
||||
_ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key)
|
||||
{
|
||||
ieee80211_keyix keyix;
|
||||
|
||||
KASSERT(key->wk_cipher != NULL, ("No cipher!"));
|
||||
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
@ -423,8 +426,7 @@ _ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key)
|
||||
key->wk_keyrsc[IEEE80211_NONQOS_TID], key->wk_keytsc,
|
||||
key->wk_keylen);
|
||||
|
||||
keyix = key->wk_keyix;
|
||||
if (keyix != IEEE80211_KEYIX_NONE) {
|
||||
if (key->wk_flags & IEEE80211_KEY_DEVKEY) {
|
||||
/*
|
||||
* Remove hardware entry.
|
||||
*/
|
||||
@ -432,7 +434,7 @@ _ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key)
|
||||
if (!dev_key_delete(vap, key)) {
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: driver did not delete key index %u\n",
|
||||
__func__, keyix);
|
||||
__func__, key->wk_keyix);
|
||||
vap->iv_stats.is_crypto_delkey++;
|
||||
/* XXX recovery? */
|
||||
}
|
||||
@ -492,6 +494,14 @@ ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key)
|
||||
key->wk_keyrsc[IEEE80211_NONQOS_TID], key->wk_keytsc,
|
||||
key->wk_keylen);
|
||||
|
||||
if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) {
|
||||
/* XXX nothing allocated, should not happen */
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: no device key setup done; should not happen!\n",
|
||||
__func__);
|
||||
vap->iv_stats.is_crypto_setkey_nokey++;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Give cipher a chance to validate key contents.
|
||||
* XXX should happen before modifying state.
|
||||
@ -504,13 +514,6 @@ ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key)
|
||||
vap->iv_stats.is_crypto_setkey_cipher++;
|
||||
return 0;
|
||||
}
|
||||
if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
|
||||
/* XXX nothing allocated, should not happen */
|
||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
|
||||
"%s: no key index; should not happen!\n", __func__);
|
||||
vap->iv_stats.is_crypto_setkey_nokey++;
|
||||
return 0;
|
||||
}
|
||||
return dev_key_set(vap, key);
|
||||
}
|
||||
|
||||
@ -619,7 +622,7 @@ load_ucastkey(void *arg, struct ieee80211_node *ni)
|
||||
if (vap->iv_state != IEEE80211_S_RUN)
|
||||
return;
|
||||
k = &ni->ni_ucastkey;
|
||||
if (k->wk_keyix != IEEE80211_KEYIX_NONE)
|
||||
if (k->wk_flags & IEEE80211_KEY_DEVKEY)
|
||||
dev_key_set(vap, k);
|
||||
}
|
||||
|
||||
@ -643,7 +646,7 @@ ieee80211_crypto_reload_keys(struct ieee80211com *ic)
|
||||
continue;
|
||||
for (i = 0; i < IEEE80211_WEP_NKID; i++) {
|
||||
const struct ieee80211_key *k = &vap->iv_nw_keys[i];
|
||||
if (k->wk_keyix != IEEE80211_KEYIX_NONE)
|
||||
if (k->wk_flags & IEEE80211_KEY_DEVKEY)
|
||||
dev_key_set(vap, k);
|
||||
}
|
||||
}
|
||||
|
@ -75,13 +75,16 @@ struct ieee80211_key {
|
||||
uint8_t wk_keylen; /* key length in bytes */
|
||||
uint8_t wk_pad;
|
||||
uint16_t wk_flags;
|
||||
#define IEEE80211_KEY_XMIT 0x01 /* key used for xmit */
|
||||
#define IEEE80211_KEY_RECV 0x02 /* key used for recv */
|
||||
#define IEEE80211_KEY_GROUP 0x04 /* key used for WPA group operation */
|
||||
#define IEEE80211_KEY_SWENCRYPT 0x10 /* host-based encrypt */
|
||||
#define IEEE80211_KEY_SWDECRYPT 0x20 /* host-based decrypt */
|
||||
#define IEEE80211_KEY_SWENMIC 0x40 /* host-based enmic */
|
||||
#define IEEE80211_KEY_SWDEMIC 0x80 /* host-based demic */
|
||||
#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_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 */
|
||||
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];
|
||||
|
@ -685,7 +685,7 @@ _db_show_key(const char *tag, int ix, const struct ieee80211_key *wk)
|
||||
const struct ieee80211_cipher *cip = wk->wk_cipher;
|
||||
int keylen = wk->wk_keylen;
|
||||
|
||||
if (wk->wk_keyix == IEEE80211_KEYIX_NONE)
|
||||
if ((wk->wk_flags & IEEE80211_KEY_DEVKEY) == 0)
|
||||
return;
|
||||
db_printf(tag, ix);
|
||||
switch (cip->ic_cipher) {
|
||||
|
@ -370,7 +370,7 @@ struct ieee80211vap {
|
||||
ieee80211_keyix iv_def_txkey; /* default/group tx key index */
|
||||
struct ieee80211_key iv_nw_keys[IEEE80211_WEP_NKID];
|
||||
int (*iv_key_alloc)(struct ieee80211vap *,
|
||||
const struct ieee80211_key *,
|
||||
struct ieee80211_key *,
|
||||
ieee80211_keyix *, ieee80211_keyix *);
|
||||
int (*iv_key_delete)(struct ieee80211vap *,
|
||||
const struct ieee80211_key *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user