wlan: set_key and del_key

This commit is contained in:
Matheus
2026-09-10 14:11:12 -03:00
parent d3ff861386
commit 2c73b64e3f
3 changed files with 162 additions and 4 deletions
+24
View File
@@ -4,6 +4,27 @@
#include <u80211_drv/kernel_interface.h>
#include <kernel/net.h>
#define WLAN_CIPHER_CCMP 0
#define WLAN_CIPHER_TKIP 1
#define WLAN_CIPHER_WEP40 2
#define WLAN_CIPHER_WEP104 3
#define WLAN_KEY_PAIRWISE 1
#define WLAN_KEY_GROUP 2
#define WLAN_KEY_RX 4
#define WLAN_KEY_TX 8
typedef struct {
uint8_t cipher;
uint8_t index;
uint8_t peer[6];
uint8_t *key;
size_t key_len;
uint8_t *rx_seq;
size_t rx_seq_len;
uint32_t flags;
} wlan_key_t;
int wlan_register(void *handle, const u80211_drv_device_metadata_t *metadata, const u80211_drv_device_ops_t *ops, u80211_drv_network_device_handle_t *network_device);
void wlan_process_packet(u80211_drv_network_device_handle_t handle, void *packet, size_t packet_size);
@@ -16,4 +37,7 @@ int wlan_associate(netdev_t *netdev, uint8_t bssid[6], void *ie, size_t ie_size)
int wlan_associate_wait(netdev_t *netdev);
int wlan_disassociate(netdev_t *netdev);
int wlan_set_key(netdev_t *netdev, wlan_key_t *key);
int wlan_del_key(netdev_t *netdev, uint8_t index, uint8_t peer[6], uint32_t flags);
#endif
+71 -4
View File
@@ -35,6 +35,14 @@ typedef struct {
size_t ie_size;
} wlan_association_request_t;
typedef struct {
uint8_t peer[6];
uint8_t index;
uint32_t flags;
} wlan_del_key_request_t;
#define MAX_KEY_SIZE 128
#define MAX_SEQ_SIZE 16
#define MAX_IE_SIZE 1024
#define NETDEV_IOCTL_GET_INFO 0x1337631
@@ -96,12 +104,71 @@ int handle_wlan_ioctl(netdev_t *netdev, unsigned long request, void *arg, int *r
return wlan_associate_wait(netdev);
case NETDEV_IOCTL_WLAN_DISASSOCIATE:
return wlan_disassociate(netdev);
case NETDEV_IOCTL_WLAN_SET_KEY:
case NETDEV_IOCTL_WLAN_SET_KEY: {
wlan_key_t req;
int error = USERCOPY_POSSIBLY_FROM_USER(&req, arg, sizeof(req));
if (error)
return error;
break;
case NETDEV_IOCTL_WLAN_DEL_KEY:
if (req.rx_seq_len > MAX_SEQ_SIZE)
return EINVAL;
break;
if (req.key_len > MAX_KEY_SIZE)
return EINVAL;
void *key = NULL;
void *seq = NULL;
if (req.key_len) {
if (IS_USER_ADDRESS(arg) && !IS_USER_ADDRESS(req.key))
return EFAULT;
key = alloc(req.key_len);
if (key == NULL)
return ENOMEM;
error = USERCOPY_POSSIBLY_FROM_USER(key, req.key, req.key_len);
if (error)
goto wlan_set_key_done;
}
if (req.rx_seq_len) {
if (IS_USER_ADDRESS(arg) && !IS_USER_ADDRESS(req.rx_seq)) {
error = EFAULT;
goto wlan_set_key_done;
}
seq = alloc(req.rx_seq_len);
if (seq == NULL) {
error = ENOMEM;
goto wlan_set_key_done;
}
error = USERCOPY_POSSIBLY_FROM_USER(seq, req.rx_seq, req.rx_seq_len);
if (error)
goto wlan_set_key_done;
}
req.key = key;
req.rx_seq = seq;
error = wlan_set_key(netdev, &req);
wlan_set_key_done:
if (key)
free(key);
if (seq)
free(seq);
return error;
}
case NETDEV_IOCTL_WLAN_DEL_KEY: {
wlan_del_key_request_t req;
int error = USERCOPY_POSSIBLY_FROM_USER(&req, arg, sizeof(req));
if (error)
return error;
return wlan_del_key(netdev, req.index, req.peer, req.flags);
}
default:
return ENOTTY;
}
+67
View File
@@ -363,3 +363,70 @@ int wlan_disassociate(netdev_t *netdev) {
return u80211_disassociate(wlan->u80211_device) == U80211_STATUS_SUCCESS ? 0 : EINVAL;
}
static bool wlan_cipher_to_u80211_cipher(uint8_t cipher, u80211_cipher_t *out) {
switch (cipher) {
case WLAN_CIPHER_CCMP:
*out = U80211_CIPHER_CCMP;
break;
case WLAN_CIPHER_TKIP:
*out = U80211_CIPHER_TKIP;
break;
case WLAN_CIPHER_WEP40:
*out = U80211_CIPHER_WEP40;
break;
case WLAN_CIPHER_WEP104:
*out = U80211_CIPHER_WEP104;
break;
default:
return false;
}
return true;
}
static uint32_t wlan_flags_to_u80211_flags(uint32_t flags) {
uint32_t out = 0;
if (flags & WLAN_KEY_PAIRWISE)
out |= U80211_KEY_PAIRWISE;
if (flags & WLAN_KEY_GROUP)
out |= U80211_KEY_GROUP;
if (flags & WLAN_KEY_RX)
out |= U80211_KEY_RX;
if (flags & WLAN_KEY_TX)
out |= U80211_KEY_TX;
return out;
}
int wlan_set_key(netdev_t *netdev, wlan_key_t *key) {
wlan_device_t *wlan = (wlan_device_t *)netdev;
u80211_key_t u80211_key = {
.index = key->index,
.key = key->key,
.key_len = key->key_len,
.rx_seq = key->rx_seq,
.rx_seq_len = key->rx_seq_len,
.flags = wlan_flags_to_u80211_flags(key->flags)
};
memcpy(&u80211_key.peer, key->peer, 6);
if (!wlan_cipher_to_u80211_cipher(key->cipher, &u80211_key.cipher))
return EINVAL;
return u80211_set_key(wlan->u80211_device, &u80211_key) == U80211_STATUS_SUCCESS ? 0 : EINVAL;
}
int wlan_del_key(netdev_t *netdev, uint8_t index, uint8_t peer[6], uint32_t flags) {
wlan_device_t *wlan = (wlan_device_t *)netdev;
u80211_mac_address_t mac;
memcpy(&mac, peer, 6);
return u80211_del_key(wlan->u80211_device, index, &mac, flags) == U80211_STATUS_SUCCESS ? 0 : EINVAL;
}