Skip to content

Commit

Permalink
Merge branch 'ieee802154-next'
Browse files Browse the repository at this point in the history
Phoebe Buckheister says:

====================
802154: implement link-layer security

This patch series implements 802.15.4-2011 link layer security.

Patches 1 and 2 prepare for llsec by adding data structures to represent the
llsec PIB as specified in 802.15.4-2011. I've changed some structures from
their specification to be more sensible, since 802.15.4 specifies some
structures in not-exactly-useful ways. Nested lists are common, but not very
accessible for netlink methods, and not very fast to traverse when searching
for specific elements either.

Patch 3 implements backends for these structures in mac802154.

Patch 4 and 5 implement the encryption and decryption methods, split from patch
3 to ease review. The encryption and decryption methods are almost entirely
compliant with the specified outgoing/incoming frame procedures. Decryption
deviates from the specification slightly where the specification makes no
sense, i.e. encrypted frames with security level 0 may be sent, but must be
dropped an reception - but transforms for processing such frames are given a
few lines in the standard. I've opted to not drop these frames instead of not
implementing the transforms that wouldn't be used if they were dropped.

Patch 6 links the mac802154 llsec with the SoftMAC devices. This is mainly
init//fini code for llsec context, handling of security subheaders and calling
the encryption/decryption methods.

Patch 7 adds sockopts to 802.15.4 dgram sockets to modifiy outgoing security
parameters on a per-socket basis. Ideally, this would also be available for
sockets on 6lowpan devices, but I'm not sure how to do that nicely.

Patch 8 adds forwarders to the llsec configuration methods for netlink, patch
10 implements these netlink accessors. This is mainly mechanical.

Patch 11, implements a key tracking option for devices that previous patches
haven't, because I'm not entirely sure whether this is the best approach to the
problem. It performs reasonably well though, so I decided to include it as a
separate patch in this series instead of sending an RFC just for this one
option.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed May 16, 2014
2 parents e54740e + f0f77dc commit a47e8f5
Show file tree
Hide file tree
Showing 16 changed files with 2,670 additions and 33 deletions.
31 changes: 31 additions & 0 deletions include/linux/nl802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,22 @@ enum {

IEEE802154_ATTR_FRAME_RETRIES,

IEEE802154_ATTR_LLSEC_ENABLED,
IEEE802154_ATTR_LLSEC_SECLEVEL,
IEEE802154_ATTR_LLSEC_KEY_MODE,
IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT,
IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED,
IEEE802154_ATTR_LLSEC_KEY_ID,
IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
IEEE802154_ATTR_LLSEC_KEY_BYTES,
IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES,
IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS,
IEEE802154_ATTR_LLSEC_FRAME_TYPE,
IEEE802154_ATTR_LLSEC_CMD_FRAME_ID,
IEEE802154_ATTR_LLSEC_SECLEVELS,
IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
IEEE802154_ATTR_LLSEC_DEV_KEY_MODE,

__IEEE802154_ATTR_MAX,
};

Expand Down Expand Up @@ -134,6 +150,21 @@ enum {

IEEE802154_SET_MACPARAMS,

IEEE802154_LLSEC_GETPARAMS,
IEEE802154_LLSEC_SETPARAMS,
IEEE802154_LLSEC_LIST_KEY,
IEEE802154_LLSEC_ADD_KEY,
IEEE802154_LLSEC_DEL_KEY,
IEEE802154_LLSEC_LIST_DEV,
IEEE802154_LLSEC_ADD_DEV,
IEEE802154_LLSEC_DEL_DEV,
IEEE802154_LLSEC_LIST_DEVKEY,
IEEE802154_LLSEC_ADD_DEVKEY,
IEEE802154_LLSEC_DEL_DEVKEY,
IEEE802154_LLSEC_LIST_SECLEVEL,
IEEE802154_LLSEC_ADD_SECLEVEL,
IEEE802154_LLSEC_DEL_SECLEVEL,

__IEEE802154_CMD_MAX,
};

Expand Down
10 changes: 9 additions & 1 deletion include/net/af_ieee802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ struct sockaddr_ieee802154 {
/* get/setsockopt */
#define SOL_IEEE802154 0

#define WPAN_WANTACK 0
#define WPAN_WANTACK 0
#define WPAN_SECURITY 1
#define WPAN_SECURITY_LEVEL 2

#define WPAN_SECURITY_DEFAULT 0
#define WPAN_SECURITY_OFF 1
#define WPAN_SECURITY_ON 2

#define WPAN_SECURITY_LEVEL_DEFAULT (-1)

#endif
135 changes: 135 additions & 0 deletions include/net/ieee802154_netdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand All @@ -242,6 +245,89 @@ static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb)
return mac_cb(skb);
}

#define IEEE802154_LLSEC_KEY_SIZE 16

struct ieee802154_llsec_key_id {
u8 mode;
u8 id;
union {
struct ieee802154_addr device_addr;
__le32 short_source;
__le64 extended_source;
};
};

struct ieee802154_llsec_key {
u8 frame_types;
u32 cmd_frame_ids;
u8 key[IEEE802154_LLSEC_KEY_SIZE];
};

struct ieee802154_llsec_key_entry {
struct list_head list;

struct ieee802154_llsec_key_id id;
struct ieee802154_llsec_key *key;
};

struct ieee802154_llsec_device_key {
struct list_head list;

struct ieee802154_llsec_key_id key_id;
u32 frame_counter;
};

enum {
IEEE802154_LLSEC_DEVKEY_IGNORE,
IEEE802154_LLSEC_DEVKEY_RESTRICT,
IEEE802154_LLSEC_DEVKEY_RECORD,

__IEEE802154_LLSEC_DEVKEY_MAX,
};

struct ieee802154_llsec_device {
struct list_head list;

__le16 pan_id;
__le16 short_addr;
__le64 hwaddr;
u32 frame_counter;
bool seclevel_exempt;

u8 key_mode;
struct list_head keys;
};

struct ieee802154_llsec_seclevel {
struct list_head list;

u8 frame_type;
u8 cmd_frame_id;
bool device_override;
u32 sec_levels;
};

struct ieee802154_llsec_params {
bool enabled;

__be32 frame_counter;
u8 out_level;
struct ieee802154_llsec_key_id out_key;

__le64 default_key_source;

__le16 pan_id;
__le64 hwaddr;
__le64 coord_hwaddr;
__le16 coord_shortaddr;
};

struct ieee802154_llsec_table {
struct list_head keys;
struct list_head devices;
struct list_head security_levels;
};

#define IEEE802154_MAC_SCAN_ED 0
#define IEEE802154_MAC_SCAN_ACTIVE 1
#define IEEE802154_MAC_SCAN_PASSIVE 2
Expand All @@ -260,6 +346,53 @@ struct ieee802154_mac_params {
};

struct wpan_phy;

enum {
IEEE802154_LLSEC_PARAM_ENABLED = 1 << 0,
IEEE802154_LLSEC_PARAM_FRAME_COUNTER = 1 << 1,
IEEE802154_LLSEC_PARAM_OUT_LEVEL = 1 << 2,
IEEE802154_LLSEC_PARAM_OUT_KEY = 1 << 3,
IEEE802154_LLSEC_PARAM_KEY_SOURCE = 1 << 4,
IEEE802154_LLSEC_PARAM_PAN_ID = 1 << 5,
IEEE802154_LLSEC_PARAM_HWADDR = 1 << 6,
IEEE802154_LLSEC_PARAM_COORD_HWADDR = 1 << 7,
IEEE802154_LLSEC_PARAM_COORD_SHORTADDR = 1 << 8,
};

struct ieee802154_llsec_ops {
int (*get_params)(struct net_device *dev,
struct ieee802154_llsec_params *params);
int (*set_params)(struct net_device *dev,
const struct ieee802154_llsec_params *params,
int changed);

int (*add_key)(struct net_device *dev,
const struct ieee802154_llsec_key_id *id,
const struct ieee802154_llsec_key *key);
int (*del_key)(struct net_device *dev,
const struct ieee802154_llsec_key_id *id);

int (*add_dev)(struct net_device *dev,
const struct ieee802154_llsec_device *llsec_dev);
int (*del_dev)(struct net_device *dev, __le64 dev_addr);

int (*add_devkey)(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key);
int (*del_devkey)(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key);

int (*add_seclevel)(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl);
int (*del_seclevel)(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl);

void (*lock_table)(struct net_device *dev);
void (*get_table)(struct net_device *dev,
struct ieee802154_llsec_table **t);
void (*unlock_table)(struct net_device *dev);
};
/*
* This should be located at net_device->ml_priv
*
Expand Down Expand Up @@ -290,6 +423,8 @@ struct ieee802154_mlme_ops {
void (*get_mac_params)(struct net_device *dev,
struct ieee802154_mac_params *params);

struct ieee802154_llsec_ops *llsec;

/* The fields below are required. */

struct wpan_phy *(*get_phy)(const struct net_device *dev);
Expand Down
66 changes: 66 additions & 0 deletions net/ieee802154/dgram.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
*/

#include <linux/capability.h>
#include <linux/net.h>
#include <linux/module.h>
#include <linux/if_arp.h>
Expand All @@ -47,6 +48,10 @@ struct dgram_sock {
unsigned int bound:1;
unsigned int connected:1;
unsigned int want_ack:1;
unsigned int secen:1;
unsigned int secen_override:1;
unsigned int seclevel:3;
unsigned int seclevel_override:1;
};

static inline struct dgram_sock *dgram_sk(const struct sock *sk)
Expand Down Expand Up @@ -264,6 +269,11 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
dst_addr = ro->dst_addr;
}

cb->secen = ro->secen;
cb->secen_override = ro->secen_override;
cb->seclevel = ro->seclevel;
cb->seclevel_override = ro->seclevel_override;

err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr,
ro->bound ? &ro->src_addr : NULL, size);
if (err < 0)
Expand Down Expand Up @@ -427,6 +437,20 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname,
case WPAN_WANTACK:
val = ro->want_ack;
break;
case WPAN_SECURITY:
if (!ro->secen_override)
val = WPAN_SECURITY_DEFAULT;
else if (ro->secen)
val = WPAN_SECURITY_ON;
else
val = WPAN_SECURITY_OFF;
break;
case WPAN_SECURITY_LEVEL:
if (!ro->seclevel_override)
val = WPAN_SECURITY_LEVEL_DEFAULT;
else
val = ro->seclevel;
break;
default:
return -ENOPROTOOPT;
}
Expand All @@ -442,6 +466,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
char __user *optval, unsigned int optlen)
{
struct dgram_sock *ro = dgram_sk(sk);
struct net *net = sock_net(sk);
int val;
int err = 0;

Expand All @@ -457,6 +482,47 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
case WPAN_WANTACK:
ro->want_ack = !!val;
break;
case WPAN_SECURITY:
if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
!ns_capable(net->user_ns, CAP_NET_RAW)) {
err = -EPERM;
break;
}

switch (val) {
case WPAN_SECURITY_DEFAULT:
ro->secen_override = 0;
break;
case WPAN_SECURITY_ON:
ro->secen_override = 1;
ro->secen = 1;
break;
case WPAN_SECURITY_OFF:
ro->secen_override = 1;
ro->secen = 0;
break;
default:
err = -EINVAL;
break;
}
break;
case WPAN_SECURITY_LEVEL:
if (!ns_capable(net->user_ns, CAP_NET_ADMIN) &&
!ns_capable(net->user_ns, CAP_NET_RAW)) {
err = -EPERM;
break;
}

if (val < WPAN_SECURITY_LEVEL_DEFAULT ||
val > IEEE802154_SCF_SECLEVEL_ENC_MIC128) {
err = -EINVAL;
} else if (val == WPAN_SECURITY_LEVEL_DEFAULT) {
ro->seclevel_override = 0;
} else {
ro->seclevel_override = 1;
ro->seclevel = val;
}
break;
default:
err = -ENOPROTOOPT;
break;
Expand Down
19 changes: 19 additions & 0 deletions net/ieee802154/ieee802154.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,23 @@ int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info);
int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb);
int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info);

int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_setparams(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_add_key(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_del_key(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_dump_keys(struct sk_buff *skb,
struct netlink_callback *cb);
int ieee802154_llsec_add_dev(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_del_dev(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_dump_devs(struct sk_buff *skb,
struct netlink_callback *cb);
int ieee802154_llsec_add_devkey(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_del_devkey(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_dump_devkeys(struct sk_buff *skb,
struct netlink_callback *cb);
int ieee802154_llsec_add_seclevel(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_del_seclevel(struct sk_buff *skb, struct genl_info *info);
int ieee802154_llsec_dump_seclevels(struct sk_buff *skb,
struct netlink_callback *cb);

#endif
20 changes: 20 additions & 0 deletions net/ieee802154/netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,26 @@ static const struct genl_ops ieee8021154_ops[] = {
IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface,
ieee802154_dump_iface),
IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams),
IEEE802154_OP(IEEE802154_LLSEC_GETPARAMS, ieee802154_llsec_getparams),
IEEE802154_OP(IEEE802154_LLSEC_SETPARAMS, ieee802154_llsec_setparams),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_KEY, NULL,
ieee802154_llsec_dump_keys),
IEEE802154_OP(IEEE802154_LLSEC_ADD_KEY, ieee802154_llsec_add_key),
IEEE802154_OP(IEEE802154_LLSEC_DEL_KEY, ieee802154_llsec_del_key),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEV, NULL,
ieee802154_llsec_dump_devs),
IEEE802154_OP(IEEE802154_LLSEC_ADD_DEV, ieee802154_llsec_add_dev),
IEEE802154_OP(IEEE802154_LLSEC_DEL_DEV, ieee802154_llsec_del_dev),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_DEVKEY, NULL,
ieee802154_llsec_dump_devkeys),
IEEE802154_OP(IEEE802154_LLSEC_ADD_DEVKEY, ieee802154_llsec_add_devkey),
IEEE802154_OP(IEEE802154_LLSEC_DEL_DEVKEY, ieee802154_llsec_del_devkey),
IEEE802154_DUMP(IEEE802154_LLSEC_LIST_SECLEVEL, NULL,
ieee802154_llsec_dump_seclevels),
IEEE802154_OP(IEEE802154_LLSEC_ADD_SECLEVEL,
ieee802154_llsec_add_seclevel),
IEEE802154_OP(IEEE802154_LLSEC_DEL_SECLEVEL,
ieee802154_llsec_del_seclevel),
};

static const struct genl_multicast_group ieee802154_mcgrps[] = {
Expand Down
Loading

0 comments on commit a47e8f5

Please sign in to comment.