ieee802154, mac802154: implement devkey record option
authorPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Fri, 16 May 2014 15:46:45 +0000 (17:46 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 16 May 2014 21:23:42 +0000 (17:23 -0400)
The 802.15.4-2011 standard states that for each key, a list of devices
that use this key shall be kept. Previous patches have only considered
two options:

 * a device "uses" (or may use) all keys, rendering the list useless
 * a device is restricted to a certain set of keys

Another option would be that a device *may* use all keys, but need not
do so, and we are interested in the actual set of keys the device uses.
Recording keys used by any given device may have a noticable performance
impact and might not be needed as often. The common case, in which a
device will not switch keys too often, should still perform well.

Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ieee802154_netdev.h
net/mac802154/llsec.c

index eb9f850..3b53c8e 100644 (file)
@@ -280,6 +280,7 @@ struct ieee802154_llsec_device_key {
 enum {
        IEEE802154_LLSEC_DEVKEY_IGNORE,
        IEEE802154_LLSEC_DEVKEY_RESTRICT,
+       IEEE802154_LLSEC_DEVKEY_RECORD,
 
        __IEEE802154_LLSEC_DEVKEY_MAX,
 };
index 392653b..a83674e 100644 (file)
@@ -920,6 +920,37 @@ llsec_do_decrypt(struct sk_buff *skb, const struct mac802154_llsec *sec,
                return llsec_do_decrypt_auth(skb, sec, hdr, key, dev_addr);
 }
 
+static int
+llsec_update_devkey_record(struct mac802154_llsec_device *dev,
+                          const struct ieee802154_llsec_key_id *in_key)
+{
+       struct mac802154_llsec_device_key *devkey;
+
+       devkey = llsec_devkey_find(dev, in_key);
+
+       if (!devkey) {
+               struct mac802154_llsec_device_key *next;
+
+               next = kzalloc(sizeof(*devkey), GFP_ATOMIC);
+               if (!next)
+                       return -ENOMEM;
+
+               next->devkey.key_id = *in_key;
+
+               spin_lock_bh(&dev->lock);
+
+               devkey = llsec_devkey_find(dev, in_key);
+               if (!devkey)
+                       list_add_rcu(&next->devkey.list, &dev->dev.keys);
+               else
+                       kfree(next);
+
+               spin_unlock_bh(&dev->lock);
+       }
+
+       return 0;
+}
+
 static int
 llsec_update_devkey_info(struct mac802154_llsec_device *dev,
                         const struct ieee802154_llsec_key_id *in_key,
@@ -933,6 +964,13 @@ llsec_update_devkey_info(struct mac802154_llsec_device *dev,
                        return -ENOENT;
        }
 
+       if (dev->dev.key_mode == IEEE802154_LLSEC_DEVKEY_RECORD) {
+               int rc = llsec_update_devkey_record(dev, in_key);
+
+               if (rc < 0)
+                       return rc;
+       }
+
        spin_lock_bh(&dev->lock);
 
        if ((!devkey && frame_counter < dev->dev.frame_counter) ||