Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a47e8f5a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ieee802154-next'



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: default avatarDavid S. Miller <davem@davemloft.net>
parents e54740e6 f0f77dc6
Loading
Loading
Loading
Loading
+31 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,22 @@ enum {


	IEEE802154_ATTR_FRAME_RETRIES,
	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,
	__IEEE802154_ATTR_MAX,
};
};


@@ -134,6 +150,21 @@ enum {


	IEEE802154_SET_MACPARAMS,
	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,
	__IEEE802154_CMD_MAX,
};
};


+9 −1
Original line number Original line Diff line number Diff line
@@ -58,5 +58,13 @@ struct sockaddr_ieee802154 {
#define SOL_IEEE802154	0
#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
#endif
+135 −0
Original line number Original line Diff line number Diff line
@@ -225,6 +225,9 @@ struct ieee802154_mac_cb {
	u8 type;
	u8 type;
	bool ackreq;
	bool ackreq;
	bool secen;
	bool secen;
	bool secen_override;
	u8 seclevel;
	bool seclevel_override;
	struct ieee802154_addr source;
	struct ieee802154_addr source;
	struct ieee802154_addr dest;
	struct ieee802154_addr dest;
};
};
@@ -242,6 +245,89 @@ static inline struct ieee802154_mac_cb *mac_cb_init(struct sk_buff *skb)
	return mac_cb(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_ED		0
#define IEEE802154_MAC_SCAN_ACTIVE	1
#define IEEE802154_MAC_SCAN_ACTIVE	1
#define IEEE802154_MAC_SCAN_PASSIVE	2
#define IEEE802154_MAC_SCAN_PASSIVE	2
@@ -260,6 +346,53 @@ struct ieee802154_mac_params {
};
};


struct wpan_phy;
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
 * This should be located at net_device->ml_priv
 *
 *
@@ -290,6 +423,8 @@ struct ieee802154_mlme_ops {
	void (*get_mac_params)(struct net_device *dev,
	void (*get_mac_params)(struct net_device *dev,
			       struct ieee802154_mac_params *params);
			       struct ieee802154_mac_params *params);


	struct ieee802154_llsec_ops *llsec;

	/* The fields below are required. */
	/* The fields below are required. */


	struct wpan_phy *(*get_phy)(const struct net_device *dev);
	struct wpan_phy *(*get_phy)(const struct net_device *dev);
+66 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@
 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 */
 */


#include <linux/capability.h>
#include <linux/net.h>
#include <linux/net.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/if_arp.h>
@@ -47,6 +48,10 @@ struct dgram_sock {
	unsigned int bound:1;
	unsigned int bound:1;
	unsigned int connected:1;
	unsigned int connected:1;
	unsigned int want_ack: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)
static inline struct dgram_sock *dgram_sk(const struct sock *sk)
@@ -264,6 +269,11 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk,
		dst_addr = ro->dst_addr;
		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,
	err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr,
			      ro->bound ? &ro->src_addr : NULL, size);
			      ro->bound ? &ro->src_addr : NULL, size);
	if (err < 0)
	if (err < 0)
@@ -427,6 +437,20 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname,
	case WPAN_WANTACK:
	case WPAN_WANTACK:
		val = ro->want_ack;
		val = ro->want_ack;
		break;
		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:
	default:
		return -ENOPROTOOPT;
		return -ENOPROTOOPT;
	}
	}
@@ -442,6 +466,7 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
		    char __user *optval, unsigned int optlen)
		    char __user *optval, unsigned int optlen)
{
{
	struct dgram_sock *ro = dgram_sk(sk);
	struct dgram_sock *ro = dgram_sk(sk);
	struct net *net = sock_net(sk);
	int val;
	int val;
	int err = 0;
	int err = 0;


@@ -457,6 +482,47 @@ static int dgram_setsockopt(struct sock *sk, int level, int optname,
	case WPAN_WANTACK:
	case WPAN_WANTACK:
		ro->want_ack = !!val;
		ro->want_ack = !!val;
		break;
		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:
	default:
		err = -ENOPROTOOPT;
		err = -ENOPROTOOPT;
		break;
		break;
+19 −0
Original line number Original line Diff line number Diff line
@@ -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_dump_iface(struct sk_buff *skb, struct netlink_callback *cb);
int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info);
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
#endif
Loading