static int bsd_set_key(void *priv, const char *alg, unsigned char *addr, int key_idx, u8 *key, size_t key_len) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_key wk; u_int8_t cipher; if (strcmp(alg, "none") == 0) return bsd_del_key(priv, addr, key_idx); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: alg=%s addr=%s key_idx=%d\n", __func__, alg, ether_sprintf(addr), key_idx); if (strcmp(alg, "WEP") == 0) cipher = IEEE80211_CIPHER_WEP; else if (strcmp(alg, "TKIP") == 0) cipher = IEEE80211_CIPHER_TKIP; else if (strcmp(alg, "CCMP") == 0) cipher = IEEE80211_CIPHER_AES_CCM; else { printf("%s: unknown/unsupported algorithm %s\n", __func__, alg); return -1; } if (key_len > sizeof(wk.ik_keydata)) { printf("%s: key length %d too big\n", __func__, key_len); return -3; } memset(&wk, 0, sizeof(wk)); wk.ik_type = cipher; wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; if (addr == NULL) { memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; wk.ik_flags |= IEEE80211_KEY_DEFAULT; } else { memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); wk.ik_keyix = IEEE80211_KEYIX_NONE; } wk.ik_keylen = key_len; memcpy(wk.ik_keydata, key, key_len); return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }
static int bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct ieee80211req_key wk; wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, set_tx, seq_len, key_len); if (alg == WPA_ALG_NONE) { #ifndef HOSTAPD if (addr == NULL || is_broadcast_ether_addr(addr)) return bsd_del_key(priv, NULL, key_idx); else #endif /* HOSTAPD */ return bsd_del_key(priv, addr, key_idx); } os_memset(&wk, 0, sizeof(wk)); switch (alg) { case WPA_ALG_WEP: wk.ik_type = IEEE80211_CIPHER_WEP; break; case WPA_ALG_TKIP: wk.ik_type = IEEE80211_CIPHER_TKIP; break; case WPA_ALG_CCMP: wk.ik_type = IEEE80211_CIPHER_AES_CCM; break; default: wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); return -1; } wk.ik_flags = IEEE80211_KEY_RECV; if (set_tx) wk.ik_flags |= IEEE80211_KEY_XMIT; if (addr == NULL) { os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; } else { os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); /* * Deduce whether group/global or unicast key by checking * the address (yech). Note also that we can only mark global * keys default; doing this for a unicast key is an error. */ if (is_broadcast_ether_addr(addr)) { wk.ik_flags |= IEEE80211_KEY_GROUP; wk.ik_keyix = key_idx; } else { wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx; } } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; wk.ik_keylen = key_len; if (seq) { #ifdef WORDS_BIGENDIAN /* * wk.ik_keyrsc is in host byte order (big endian), need to * swap it to match with the byte order used in WPA. */ int i; u8 *keyrsc = (u8 *) &wk.ik_keyrsc; for (i = 0; i < seq_len; i++) keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i]; #else /* WORDS_BIGENDIAN */ os_memcpy(&wk.ik_keyrsc, seq, seq_len); #endif /* WORDS_BIGENDIAN */ } os_memcpy(wk.ik_keydata, key, key_len); return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }
static int bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct ieee80211req_key wk; wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, set_tx, seq_len, key_len); if (alg == WPA_ALG_NONE) { return bsd_del_key(priv, addr, key_idx); } os_memset(&wk, 0, sizeof(wk)); switch (alg) { case WPA_ALG_WEP: wk.ik_type = IEEE80211_CIPHER_WEP; break; case WPA_ALG_TKIP: wk.ik_type = IEEE80211_CIPHER_TKIP; break; case WPA_ALG_CCMP: wk.ik_type = IEEE80211_CIPHER_AES_CCM; break; default: wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); return -1; } wk.ik_flags = IEEE80211_KEY_RECV; if (set_tx) wk.ik_flags |= IEEE80211_KEY_XMIT; if (addr == NULL) { os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; } else { os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); /* * Deduce whether group/global or unicast key by checking * the address (yech). Note also that we can only mark global * keys default; doing this for a unicast key is an error. */ if (os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) { wk.ik_flags |= IEEE80211_KEY_GROUP; wk.ik_keyix = key_idx; } else { wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx; } } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; wk.ik_keylen = key_len; os_memcpy(&wk.ik_keyrsc, seq, seq_len); os_memcpy(wk.ik_keydata, key, key_len); return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }