netdev: implement netdev_set_igtk

This commit is contained in:
Rahul Rahul 2016-10-28 14:49:54 -07:00 committed by Denis Kenzior
parent c3efd80dd0
commit 5e0b24dcb2
1 changed files with 77 additions and 4 deletions

View File

@ -67,6 +67,7 @@ struct netdev {
uint32_t pairwise_new_key_cmd_id;
uint32_t pairwise_set_key_cmd_id;
uint32_t group_new_key_cmd_id;
uint32_t group_management_new_key_cmd_id;
uint32_t connect_cmd_id;
uint32_t disconnect_cmd_id;
enum netdev_result result;
@ -303,6 +304,12 @@ static void netdev_connect_free(struct netdev *netdev)
netdev->group_new_key_cmd_id = 0;
}
if (netdev->group_management_new_key_cmd_id) {
l_genl_family_cancel(nl80211,
netdev->group_management_new_key_cmd_id);
netdev->group_management_new_key_cmd_id = 0;
}
if (netdev->connect_cmd_id) {
l_genl_family_cancel(nl80211, netdev->connect_cmd_id);
netdev->connect_cmd_id = 0;
@ -606,6 +613,10 @@ static void netdev_setting_keys_failed(struct netdev *netdev,
l_genl_family_cancel(nl80211, netdev->group_new_key_cmd_id);
netdev->group_new_key_cmd_id = 0;
l_genl_family_cancel(nl80211,
netdev->group_management_new_key_cmd_id);
netdev->group_management_new_key_cmd_id = 0;
netdev->result = NETDEV_RESULT_KEY_SETTING_FAILED;
msg = netdev_build_cmd_deauthenticate(netdev,
MPDU_REASON_CODE_UNSPECIFIED);
@ -673,18 +684,33 @@ error:
netdev_setting_keys_failed(netdev, MPDU_REASON_CODE_UNSPECIFIED);
}
static void netdev_new_group_management_key_cb(struct l_genl_msg *msg,
void *data)
{
struct netdev *netdev = data;
netdev->group_management_new_key_cmd_id = 0;
if (l_genl_msg_get_error(msg) < 0) {
l_error("New Key for Group Mgmt failed for ifindex: %d",
netdev->index);
netdev_setting_keys_failed(netdev,
MPDU_REASON_CODE_UNSPECIFIED);
}
}
static struct l_genl_msg *netdev_build_cmd_new_key_group(struct netdev *netdev,
uint32_t cipher, uint8_t key_id,
const uint8_t *gtk, size_t gtk_len,
const uint8_t *rsc, size_t rsc_len)
const uint8_t *key, size_t key_len,
const uint8_t *ctr, size_t ctr_len)
{
struct l_genl_msg *msg;
msg = l_genl_msg_new_sized(NL80211_CMD_NEW_KEY, 512);
l_genl_msg_append_attr(msg, NL80211_ATTR_KEY_DATA, gtk_len, gtk);
l_genl_msg_append_attr(msg, NL80211_ATTR_KEY_DATA, key_len, key);
l_genl_msg_append_attr(msg, NL80211_ATTR_KEY_CIPHER, 4, &cipher);
l_genl_msg_append_attr(msg, NL80211_ATTR_KEY_SEQ, rsc_len, rsc);
l_genl_msg_append_attr(msg, NL80211_ATTR_KEY_SEQ, ctr_len, ctr);
l_genl_msg_enter_nested(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
l_genl_msg_append_attr(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST,
@ -760,6 +786,52 @@ static void netdev_set_gtk(uint32_t ifindex, uint8_t key_index,
netdev_setting_keys_failed(netdev, MPDU_REASON_CODE_UNSPECIFIED);
}
static void netdev_set_igtk(uint32_t ifindex, uint8_t key_index,
const uint8_t *igtk, uint8_t igtk_len,
const uint8_t *ipn, uint8_t ipn_len,
uint32_t cipher, void *user_data)
{
uint8_t igtk_buf[16];
struct netdev *netdev;
struct l_genl_msg *msg;
netdev = netdev_find(ifindex);
l_debug("%d", netdev->index);
switch (cipher) {
case CRYPTO_CIPHER_BIP:
memcpy(igtk_buf, igtk, 16);
break;
default:
l_error("Unexpected cipher: %x", cipher);
netdev_setting_keys_failed(netdev,
MPDU_REASON_CODE_INVALID_GROUP_CIPHER);
return;
}
if (crypto_cipher_key_len(cipher) != igtk_len) {
l_error("Unexpected key length: %d", igtk_len);
netdev_setting_keys_failed(netdev,
MPDU_REASON_CODE_INVALID_GROUP_CIPHER);
return;
}
msg = netdev_build_cmd_new_key_group(netdev, cipher, key_index,
igtk_buf, igtk_len,
ipn, ipn_len);
netdev->group_management_new_key_cmd_id =
l_genl_family_send(nl80211, msg,
netdev_new_group_management_key_cb,
netdev, NULL);
if (netdev->group_management_new_key_cmd_id > 0)
return;
l_genl_msg_unref(msg);
netdev_setting_keys_failed(netdev, MPDU_REASON_CODE_UNSPECIFIED);
}
static void netdev_set_pairwise_key_cb(struct l_genl_msg *msg, void *data)
{
struct netdev *netdev = data;
@ -1782,6 +1854,7 @@ bool netdev_init(struct l_genl_family *in,
__eapol_set_install_tk_func(netdev_set_tk);
__eapol_set_install_gtk_func(netdev_set_gtk);
__eapol_set_install_igtk_func(netdev_set_igtk);
__eapol_set_deauthenticate_func(netdev_handshake_failed);
__eapol_set_rekey_offload_func(netdev_set_rekey_offload);