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

Commit a26c5fd7 authored by Alexander Aring's avatar Alexander Aring Committed by Marcel Holtmann
Browse files

nl802154: add support for security layer



This patch adds support for accessing mac802154 llsec implementation
over nl802154. I added for a new Kconfig entry to provide this
functionality CONFIG_IEEE802154_NL802154_EXPERIMENTAL. This interface is
still in development. It provides to change security parameters and
add/del/dump entries of security tables. Later we can add also a get to
get an entry by unique identifier.

Cc: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: default avatarAlexander Aring <alex.aring@gmail.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 1ee06ef1
Loading
Loading
Loading
Loading
+131 −0
Original line number Diff line number Diff line
@@ -27,6 +27,16 @@
struct wpan_phy;
struct wpan_phy_cca;

#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
struct ieee802154_llsec_device_key;
struct ieee802154_llsec_seclevel;
struct ieee802154_llsec_params;
struct ieee802154_llsec_device;
struct ieee802154_llsec_table;
struct ieee802154_llsec_key_id;
struct ieee802154_llsec_key;
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */

struct cfg802154_ops {
	struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
							   const char *name,
@@ -65,6 +75,51 @@ struct cfg802154_ops {
				struct wpan_dev *wpan_dev, bool mode);
	int	(*set_ackreq_default)(struct wpan_phy *wpan_phy,
				      struct wpan_dev *wpan_dev, bool ackreq);
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
	void	(*get_llsec_table)(struct wpan_phy *wpan_phy,
				   struct wpan_dev *wpan_dev,
				   struct ieee802154_llsec_table **table);
	void	(*lock_llsec_table)(struct wpan_phy *wpan_phy,
				    struct wpan_dev *wpan_dev);
	void	(*unlock_llsec_table)(struct wpan_phy *wpan_phy,
				      struct wpan_dev *wpan_dev);
	/* TODO remove locking/get table callbacks, this is part of the
	 * nl802154 interface and should be accessible from ieee802154 layer.
	 */
	int	(*get_llsec_params)(struct wpan_phy *wpan_phy,
				    struct wpan_dev *wpan_dev,
				    struct ieee802154_llsec_params *params);
	int	(*set_llsec_params)(struct wpan_phy *wpan_phy,
				    struct wpan_dev *wpan_dev,
				    const struct ieee802154_llsec_params *params,
				    int changed);
	int	(*add_llsec_key)(struct wpan_phy *wpan_phy,
				 struct wpan_dev *wpan_dev,
				 const struct ieee802154_llsec_key_id *id,
				 const struct ieee802154_llsec_key *key);
	int	(*del_llsec_key)(struct wpan_phy *wpan_phy,
				 struct wpan_dev *wpan_dev,
				 const struct ieee802154_llsec_key_id *id);
	int	(*add_seclevel)(struct wpan_phy *wpan_phy,
				 struct wpan_dev *wpan_dev,
				 const struct ieee802154_llsec_seclevel *sl);
	int	(*del_seclevel)(struct wpan_phy *wpan_phy,
				 struct wpan_dev *wpan_dev,
				 const struct ieee802154_llsec_seclevel *sl);
	int	(*add_device)(struct wpan_phy *wpan_phy,
			      struct wpan_dev *wpan_dev,
			      const struct ieee802154_llsec_device *dev);
	int	(*del_device)(struct wpan_phy *wpan_phy,
			      struct wpan_dev *wpan_dev, __le64 extended_addr);
	int	(*add_devkey)(struct wpan_phy *wpan_phy,
			      struct wpan_dev *wpan_dev,
			      __le64 extended_addr,
			      const struct ieee802154_llsec_device_key *key);
	int	(*del_devkey)(struct wpan_phy *wpan_phy,
			      struct wpan_dev *wpan_dev,
			      __le64 extended_addr,
			      const struct ieee802154_llsec_device_key *key);
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
};

static inline bool
@@ -176,6 +231,82 @@ struct ieee802154_addr {
	};
};

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

#define IEEE802154_LLSEC_KEY_SIZE 16

struct ieee802154_llsec_key {
	u8 frame_types;
	u32 cmd_frame_ids;
	/* TODO replace with NL802154_KEY_SIZE */
	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_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;
};

struct ieee802154_llsec_seclevel {
	struct list_head list;

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

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_device_key {
	struct list_head list;

	struct ieee802154_llsec_key_id key_id;
	u32 frame_counter;
};

struct wpan_dev_header_ops {
	/* TODO create callback currently assumes ieee802154_mac_cb inside
	 * skb->cb. This should be changed to give these information as
+0 −75
Original line number Diff line number Diff line
@@ -234,38 +234,6 @@ 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,
@@ -274,49 +242,6 @@ enum {
	__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
+191 −0
Original line number Diff line number Diff line
@@ -56,6 +56,22 @@ enum nl802154_commands {

	/* add new commands above here */

#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
	NL802154_CMD_SET_SEC_PARAMS,
	NL802154_CMD_GET_SEC_KEY,		/* can dump */
	NL802154_CMD_NEW_SEC_KEY,
	NL802154_CMD_DEL_SEC_KEY,
	NL802154_CMD_GET_SEC_DEV,		/* can dump */
	NL802154_CMD_NEW_SEC_DEV,
	NL802154_CMD_DEL_SEC_DEV,
	NL802154_CMD_GET_SEC_DEVKEY,		/* can dump */
	NL802154_CMD_NEW_SEC_DEVKEY,
	NL802154_CMD_DEL_SEC_DEVKEY,
	NL802154_CMD_GET_SEC_LEVEL,		/* can dump */
	NL802154_CMD_NEW_SEC_LEVEL,
	NL802154_CMD_DEL_SEC_LEVEL,
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */

	/* used to define NL802154_CMD_MAX below */
	__NL802154_CMD_AFTER_LAST,
	NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1
@@ -110,6 +126,18 @@ enum nl802154_attrs {

	/* add attributes here, update the policy in nl802154.c */

#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
	NL802154_ATTR_SEC_ENABLED,
	NL802154_ATTR_SEC_OUT_LEVEL,
	NL802154_ATTR_SEC_OUT_KEY_ID,
	NL802154_ATTR_SEC_FRAME_COUNTER,

	NL802154_ATTR_SEC_LEVEL,
	NL802154_ATTR_SEC_DEVICE,
	NL802154_ATTR_SEC_DEVKEY,
	NL802154_ATTR_SEC_KEY,
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */

	__NL802154_ATTR_AFTER_LAST,
	NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1
};
@@ -247,4 +275,167 @@ enum nl802154_supported_bool_states {
	NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1
};

#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL

enum nl802154_dev_addr_modes {
	NL802154_DEV_ADDR_NONE,
	__NL802154_DEV_ADDR_INVALID,
	NL802154_DEV_ADDR_SHORT,
	NL802154_DEV_ADDR_EXTENDED,

	/* keep last */
	__NL802154_DEV_ADDR_AFTER_LAST,
	NL802154_DEV_ADDR_MAX = __NL802154_DEV_ADDR_AFTER_LAST - 1
};

enum nl802154_dev_addr_attrs {
	NL802154_DEV_ADDR_ATTR_UNSPEC,

	NL802154_DEV_ADDR_ATTR_PAN_ID,
	NL802154_DEV_ADDR_ATTR_MODE,
	NL802154_DEV_ADDR_ATTR_SHORT,
	NL802154_DEV_ADDR_ATTR_EXTENDED,

	/* keep last */
	__NL802154_DEV_ADDR_ATTR_AFTER_LAST,
	NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1
};

enum nl802154_key_id_modes {
	NL802154_KEY_ID_MODE_IMPLICIT,
	NL802154_KEY_ID_MODE_INDEX,
	NL802154_KEY_ID_MODE_INDEX_SHORT,
	NL802154_KEY_ID_MODE_INDEX_EXTENDED,

	/* keep last */
	__NL802154_KEY_ID_MODE_AFTER_LAST,
	NL802154_KEY_ID_MODE_MAX = __NL802154_KEY_ID_MODE_AFTER_LAST - 1
};

enum nl802154_key_id_attrs {
	NL802154_KEY_ID_ATTR_UNSPEC,

	NL802154_KEY_ID_ATTR_MODE,
	NL802154_KEY_ID_ATTR_INDEX,
	NL802154_KEY_ID_ATTR_IMPLICIT,
	NL802154_KEY_ID_ATTR_SOURCE_SHORT,
	NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,

	/* keep last */
	__NL802154_KEY_ID_ATTR_AFTER_LAST,
	NL802154_KEY_ID_ATTR_MAX = __NL802154_KEY_ID_ATTR_AFTER_LAST - 1
};

enum nl802154_seclevels {
	NL802154_SECLEVEL_NONE,
	NL802154_SECLEVEL_MIC32,
	NL802154_SECLEVEL_MIC64,
	NL802154_SECLEVEL_MIC128,
	NL802154_SECLEVEL_ENC,
	NL802154_SECLEVEL_ENC_MIC32,
	NL802154_SECLEVEL_ENC_MIC64,
	NL802154_SECLEVEL_ENC_MIC128,

	/* keep last */
	__NL802154_SECLEVEL_AFTER_LAST,
	NL802154_SECLEVEL_MAX = __NL802154_SECLEVEL_AFTER_LAST - 1
};

enum nl802154_frames {
	NL802154_FRAME_BEACON,
	NL802154_FRAME_DATA,
	NL802154_FRAME_ACK,
	NL802154_FRAME_CMD,

	/* keep last */
	__NL802154_FRAME_AFTER_LAST,
	NL802154_FRAME_MAX = __NL802154_FRAME_AFTER_LAST - 1
};

enum nl802154_cmd_frames {
	__NL802154_CMD_FRAME_INVALID,
	NL802154_CMD_FRAME_ASSOC_REQUEST,
	NL802154_CMD_FRAME_ASSOC_RESPONSE,
	NL802154_CMD_FRAME_DISASSOC_NOTIFY,
	NL802154_CMD_FRAME_DATA_REQUEST,
	NL802154_CMD_FRAME_PAN_ID_CONFLICT_NOTIFY,
	NL802154_CMD_FRAME_ORPHAN_NOTIFY,
	NL802154_CMD_FRAME_BEACON_REQUEST,
	NL802154_CMD_FRAME_COORD_REALIGNMENT,
	NL802154_CMD_FRAME_GTS_REQUEST,

	/* keep last */
	__NL802154_CMD_FRAME_AFTER_LAST,
	NL802154_CMD_FRAME_MAX = __NL802154_CMD_FRAME_AFTER_LAST - 1
};

enum nl802154_seclevel_attrs {
	NL802154_SECLEVEL_ATTR_UNSPEC,

	NL802154_SECLEVEL_ATTR_LEVELS,
	NL802154_SECLEVEL_ATTR_FRAME,
	NL802154_SECLEVEL_ATTR_CMD_FRAME,
	NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,

	/* keep last */
	__NL802154_SECLEVEL_ATTR_AFTER_LAST,
	NL802154_SECLEVEL_ATTR_MAX = __NL802154_SECLEVEL_ATTR_AFTER_LAST - 1
};

/* TODO what is this? couldn't find in mib */
enum {
	NL802154_DEVKEY_IGNORE,
	NL802154_DEVKEY_RESTRICT,
	NL802154_DEVKEY_RECORD,

	/* keep last */
	__NL802154_DEVKEY_AFTER_LAST,
	NL802154_DEVKEY_MAX = __NL802154_DEVKEY_AFTER_LAST - 1
};

enum nl802154_dev {
	NL802154_DEV_ATTR_UNSPEC,

	NL802154_DEV_ATTR_FRAME_COUNTER,
	NL802154_DEV_ATTR_PAN_ID,
	NL802154_DEV_ATTR_SHORT_ADDR,
	NL802154_DEV_ATTR_EXTENDED_ADDR,
	NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
	NL802154_DEV_ATTR_KEY_MODE,

	/* keep last */
	__NL802154_DEV_ATTR_AFTER_LAST,
	NL802154_DEV_ATTR_MAX = __NL802154_DEV_ATTR_AFTER_LAST - 1
};

enum nl802154_devkey {
	NL802154_DEVKEY_ATTR_UNSPEC,

	NL802154_DEVKEY_ATTR_FRAME_COUNTER,
	NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
	NL802154_DEVKEY_ATTR_ID,

	/* keep last */
	__NL802154_DEVKEY_ATTR_AFTER_LAST,
	NL802154_DEVKEY_ATTR_MAX = __NL802154_DEVKEY_ATTR_AFTER_LAST - 1
};

enum nl802154_key {
	NL802154_KEY_ATTR_UNSPEC,

	NL802154_KEY_ATTR_ID,
	NL802154_KEY_ATTR_USAGE_FRAMES,
	NL802154_KEY_ATTR_USAGE_CMDS,
	NL802154_KEY_ATTR_BYTES,

	/* keep last */
	__NL802154_KEY_ATTR_AFTER_LAST,
	NL802154_KEY_ATTR_MAX = __NL802154_KEY_ATTR_AFTER_LAST - 1
};

#define NL802154_KEY_SIZE		16
#define NL802154_CMD_FRAME_NR_IDS	256

#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */

#endif /* __NL802154_H */
+5 −0
Original line number Diff line number Diff line
@@ -12,6 +12,11 @@ menuconfig IEEE802154

if IEEE802154

config IEEE802154_NL802154_EXPERIMENTAL
	bool "IEEE 802.15.4 experimental netlink support"
	---help---
	  Adds experimental netlink support for nl802154.

config IEEE802154_SOCKET
	tristate "IEEE 802.15.4 socket interface"
	default y
+12 −0
Original line number Diff line number Diff line
@@ -95,6 +95,18 @@ cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx)
	return result;
}

struct wpan_phy *wpan_phy_idx_to_wpan_phy(int wpan_phy_idx)
{
	struct cfg802154_registered_device *rdev;

	ASSERT_RTNL();

	rdev = cfg802154_rdev_by_wpan_phy_idx(wpan_phy_idx);
	if (!rdev)
		return NULL;
	return &rdev->wpan_phy;
}

struct wpan_phy *
wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
{
Loading