mirror of
https://github.com/torvalds/linux.git
synced 2024-11-06 20:21:57 +00:00
mac802154: integrate llsec with wpan devices
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4c14a2fb5d
commit
f30be4d53c
@ -225,6 +225,9 @@ struct ieee802154_mac_cb {
|
||||
u8 type;
|
||||
bool ackreq;
|
||||
bool secen;
|
||||
bool secen_override;
|
||||
u8 seclevel;
|
||||
bool seclevel_override;
|
||||
struct ieee802154_addr source;
|
||||
struct ieee802154_addr dest;
|
||||
};
|
||||
|
@ -23,9 +23,12 @@
|
||||
#ifndef MAC802154_H
|
||||
#define MAC802154_H
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <net/mac802154.h>
|
||||
#include <net/ieee802154_netdev.h>
|
||||
|
||||
#include "llsec.h"
|
||||
|
||||
/* mac802154 device private data */
|
||||
struct mac802154_priv {
|
||||
struct ieee802154_dev hw;
|
||||
@ -91,6 +94,13 @@ struct mac802154_sub_if_data {
|
||||
u8 bsn;
|
||||
/* MAC DSN field */
|
||||
u8 dsn;
|
||||
|
||||
/* protects sec from concurrent access by netlink. access by
|
||||
* encrypt/decrypt/header_create safe without additional protection.
|
||||
*/
|
||||
struct mutex sec_mtx;
|
||||
|
||||
struct mac802154_llsec sec;
|
||||
};
|
||||
|
||||
#define mac802154_to_priv(_hw) container_of(_hw, struct mac802154_priv, hw)
|
||||
|
@ -183,6 +183,38 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int mac802154_set_header_security(struct mac802154_sub_if_data *priv,
|
||||
struct ieee802154_hdr *hdr,
|
||||
const struct ieee802154_mac_cb *cb)
|
||||
{
|
||||
struct ieee802154_llsec_params params;
|
||||
u8 level;
|
||||
|
||||
mac802154_llsec_get_params(&priv->sec, ¶ms);
|
||||
|
||||
if (!params.enabled && cb->secen_override && cb->secen)
|
||||
return -EINVAL;
|
||||
if (!params.enabled ||
|
||||
(cb->secen_override && !cb->secen) ||
|
||||
!params.out_level)
|
||||
return 0;
|
||||
if (cb->seclevel_override && !cb->seclevel)
|
||||
return -EINVAL;
|
||||
|
||||
level = cb->seclevel_override ? cb->seclevel : params.out_level;
|
||||
|
||||
hdr->fc.security_enabled = 1;
|
||||
hdr->sec.level = level;
|
||||
hdr->sec.key_id_mode = params.out_key.mode;
|
||||
if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
|
||||
hdr->sec.short_src = params.out_key.short_source;
|
||||
else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
|
||||
hdr->sec.extended_src = params.out_key.extended_source;
|
||||
hdr->sec.key_id = params.out_key.id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mac802154_header_create(struct sk_buff *skb,
|
||||
struct net_device *dev,
|
||||
unsigned short type,
|
||||
@ -204,6 +236,9 @@ static int mac802154_header_create(struct sk_buff *skb,
|
||||
hdr.fc.ack_request = cb->ackreq;
|
||||
hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
|
||||
|
||||
if (mac802154_set_header_security(priv, &hdr, cb) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!saddr) {
|
||||
spin_lock_bh(&priv->mib_lock);
|
||||
|
||||
@ -259,6 +294,7 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct mac802154_sub_if_data *priv;
|
||||
u8 chan, page;
|
||||
int rc;
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
|
||||
@ -274,6 +310,13 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
rc = mac802154_llsec_encrypt(&priv->sec, skb);
|
||||
if (rc) {
|
||||
pr_warn("encryption failed: %i\n", rc);
|
||||
kfree_skb(skb);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
skb->skb_iif = dev->ifindex;
|
||||
dev->stats.tx_packets++;
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
@ -294,6 +337,15 @@ static const struct net_device_ops mac802154_wpan_ops = {
|
||||
.ndo_set_mac_address = mac802154_wpan_mac_addr,
|
||||
};
|
||||
|
||||
static void mac802154_wpan_free(struct net_device *dev)
|
||||
{
|
||||
struct mac802154_sub_if_data *priv = netdev_priv(dev);
|
||||
|
||||
mac802154_llsec_destroy(&priv->sec);
|
||||
|
||||
free_netdev(dev);
|
||||
}
|
||||
|
||||
void mac802154_wpan_setup(struct net_device *dev)
|
||||
{
|
||||
struct mac802154_sub_if_data *priv;
|
||||
@ -303,14 +355,14 @@ void mac802154_wpan_setup(struct net_device *dev)
|
||||
|
||||
dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
|
||||
dev->header_ops = &mac802154_header_ops;
|
||||
dev->needed_tailroom = 2; /* FCS */
|
||||
dev->needed_tailroom = 2 + 16; /* FCS + MIC */
|
||||
dev->mtu = IEEE802154_MTU;
|
||||
dev->tx_queue_len = 300;
|
||||
dev->type = ARPHRD_IEEE802154;
|
||||
dev->flags = IFF_NOARP | IFF_BROADCAST;
|
||||
dev->watchdog_timeo = 0;
|
||||
|
||||
dev->destructor = free_netdev;
|
||||
dev->destructor = mac802154_wpan_free;
|
||||
dev->netdev_ops = &mac802154_wpan_ops;
|
||||
dev->ml_priv = &mac802154_mlme_wpan;
|
||||
|
||||
@ -321,6 +373,7 @@ void mac802154_wpan_setup(struct net_device *dev)
|
||||
priv->page = 0;
|
||||
|
||||
spin_lock_init(&priv->mib_lock);
|
||||
mutex_init(&priv->sec_mtx);
|
||||
|
||||
get_random_bytes(&priv->bsn, 1);
|
||||
get_random_bytes(&priv->dsn, 1);
|
||||
@ -333,6 +386,8 @@ void mac802154_wpan_setup(struct net_device *dev)
|
||||
|
||||
priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
|
||||
priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
|
||||
|
||||
mac802154_llsec_init(&priv->sec);
|
||||
}
|
||||
|
||||
static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
|
||||
@ -341,9 +396,11 @@ static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
static int
|
||||
mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
|
||||
mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
|
||||
const struct ieee802154_hdr *hdr)
|
||||
{
|
||||
__le16 span, sshort;
|
||||
int rc;
|
||||
|
||||
pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
|
||||
|
||||
@ -390,6 +447,12 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb)
|
||||
|
||||
skb->dev = sdata->dev;
|
||||
|
||||
rc = mac802154_llsec_decrypt(&sdata->sec, skb);
|
||||
if (rc) {
|
||||
pr_debug("decryption failed: %i\n", rc);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
sdata->dev->stats.rx_packets++;
|
||||
sdata->dev->stats.rx_bytes += skb->len;
|
||||
|
||||
@ -421,60 +484,58 @@ static void mac802154_print_addr(const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
static int mac802154_parse_frame_start(struct sk_buff *skb)
|
||||
static int mac802154_parse_frame_start(struct sk_buff *skb,
|
||||
struct ieee802154_hdr *hdr)
|
||||
{
|
||||
int hlen;
|
||||
struct ieee802154_hdr hdr;
|
||||
struct ieee802154_mac_cb *cb = mac_cb_init(skb);
|
||||
|
||||
hlen = ieee802154_hdr_pull(skb, &hdr);
|
||||
hlen = ieee802154_hdr_pull(skb, hdr);
|
||||
if (hlen < 0)
|
||||
return -EINVAL;
|
||||
|
||||
skb->mac_len = hlen;
|
||||
|
||||
pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr.fc),
|
||||
hdr.seq);
|
||||
pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
|
||||
hdr->seq);
|
||||
|
||||
cb->type = hdr.fc.type;
|
||||
cb->ackreq = hdr.fc.ack_request;
|
||||
cb->secen = hdr.fc.security_enabled;
|
||||
cb->type = hdr->fc.type;
|
||||
cb->ackreq = hdr->fc.ack_request;
|
||||
cb->secen = hdr->fc.security_enabled;
|
||||
|
||||
mac802154_print_addr("destination", &hdr.dest);
|
||||
mac802154_print_addr("source", &hdr.source);
|
||||
mac802154_print_addr("destination", &hdr->dest);
|
||||
mac802154_print_addr("source", &hdr->source);
|
||||
|
||||
cb->source = hdr.source;
|
||||
cb->dest = hdr.dest;
|
||||
cb->source = hdr->source;
|
||||
cb->dest = hdr->dest;
|
||||
|
||||
if (hdr.fc.security_enabled) {
|
||||
if (hdr->fc.security_enabled) {
|
||||
u64 key;
|
||||
|
||||
pr_debug("seclevel %i\n", hdr.sec.level);
|
||||
pr_debug("seclevel %i\n", hdr->sec.level);
|
||||
|
||||
switch (hdr.sec.key_id_mode) {
|
||||
switch (hdr->sec.key_id_mode) {
|
||||
case IEEE802154_SCF_KEY_IMPLICIT:
|
||||
pr_debug("implicit key\n");
|
||||
break;
|
||||
|
||||
case IEEE802154_SCF_KEY_INDEX:
|
||||
pr_debug("key %02x\n", hdr.sec.key_id);
|
||||
pr_debug("key %02x\n", hdr->sec.key_id);
|
||||
break;
|
||||
|
||||
case IEEE802154_SCF_KEY_SHORT_INDEX:
|
||||
pr_debug("key %04x:%04x %02x\n",
|
||||
le32_to_cpu(hdr.sec.short_src) >> 16,
|
||||
le32_to_cpu(hdr.sec.short_src) & 0xffff,
|
||||
hdr.sec.key_id);
|
||||
le32_to_cpu(hdr->sec.short_src) >> 16,
|
||||
le32_to_cpu(hdr->sec.short_src) & 0xffff,
|
||||
hdr->sec.key_id);
|
||||
break;
|
||||
|
||||
case IEEE802154_SCF_KEY_HW_INDEX:
|
||||
key = swab64((__force u64) hdr.sec.extended_src);
|
||||
key = swab64((__force u64) hdr->sec.extended_src);
|
||||
pr_debug("key source %8phC %02x\n", &key,
|
||||
hdr.sec.key_id);
|
||||
hdr->sec.key_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -485,8 +546,9 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
|
||||
int ret;
|
||||
struct sk_buff *sskb;
|
||||
struct mac802154_sub_if_data *sdata;
|
||||
struct ieee802154_hdr hdr;
|
||||
|
||||
ret = mac802154_parse_frame_start(skb);
|
||||
ret = mac802154_parse_frame_start(skb, &hdr);
|
||||
if (ret) {
|
||||
pr_debug("got invalid frame\n");
|
||||
return;
|
||||
@ -499,7 +561,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
|
||||
|
||||
sskb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (sskb)
|
||||
mac802154_subif_frame(sdata, sskb);
|
||||
mac802154_subif_frame(sdata, sskb, &hdr);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user