2 * Copyright (C) 2014 Fraunhofer ITWM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
17 #include <linux/err.h>
18 #include <linux/bug.h>
19 #include <linux/completion.h>
20 #include <net/ieee802154.h>
22 #include "mac802154.h"
25 static void llsec_key_put(struct mac802154_llsec_key
*key
);
26 static bool llsec_key_id_equal(const struct ieee802154_llsec_key_id
*a
,
27 const struct ieee802154_llsec_key_id
*b
);
29 static void llsec_dev_free(struct mac802154_llsec_device
*dev
);
31 void mac802154_llsec_init(struct mac802154_llsec
*sec
)
33 memset(sec
, 0, sizeof(*sec
));
35 memset(&sec
->params
.default_key_source
, 0xFF, IEEE802154_ADDR_LEN
);
37 INIT_LIST_HEAD(&sec
->table
.security_levels
);
38 INIT_LIST_HEAD(&sec
->table
.devices
);
39 INIT_LIST_HEAD(&sec
->table
.keys
);
40 hash_init(sec
->devices_short
);
41 hash_init(sec
->devices_hw
);
42 rwlock_init(&sec
->lock
);
45 void mac802154_llsec_destroy(struct mac802154_llsec
*sec
)
47 struct ieee802154_llsec_seclevel
*sl
, *sn
;
48 struct ieee802154_llsec_device
*dev
, *dn
;
49 struct ieee802154_llsec_key_entry
*key
, *kn
;
51 list_for_each_entry_safe(sl
, sn
, &sec
->table
.security_levels
, list
) {
52 struct mac802154_llsec_seclevel
*msl
;
54 msl
= container_of(sl
, struct mac802154_llsec_seclevel
, level
);
59 list_for_each_entry_safe(dev
, dn
, &sec
->table
.devices
, list
) {
60 struct mac802154_llsec_device
*mdev
;
62 mdev
= container_of(dev
, struct mac802154_llsec_device
, dev
);
67 list_for_each_entry_safe(key
, kn
, &sec
->table
.keys
, list
) {
68 struct mac802154_llsec_key
*mkey
;
70 mkey
= container_of(key
->key
, struct mac802154_llsec_key
, key
);
79 int mac802154_llsec_get_params(struct mac802154_llsec
*sec
,
80 struct ieee802154_llsec_params
*params
)
82 read_lock_bh(&sec
->lock
);
83 *params
= sec
->params
;
84 read_unlock_bh(&sec
->lock
);
89 int mac802154_llsec_set_params(struct mac802154_llsec
*sec
,
90 const struct ieee802154_llsec_params
*params
,
93 write_lock_bh(&sec
->lock
);
95 if (changed
& IEEE802154_LLSEC_PARAM_ENABLED
)
96 sec
->params
.enabled
= params
->enabled
;
97 if (changed
& IEEE802154_LLSEC_PARAM_FRAME_COUNTER
)
98 sec
->params
.frame_counter
= params
->frame_counter
;
99 if (changed
& IEEE802154_LLSEC_PARAM_OUT_LEVEL
)
100 sec
->params
.out_level
= params
->out_level
;
101 if (changed
& IEEE802154_LLSEC_PARAM_OUT_KEY
)
102 sec
->params
.out_key
= params
->out_key
;
103 if (changed
& IEEE802154_LLSEC_PARAM_KEY_SOURCE
)
104 sec
->params
.default_key_source
= params
->default_key_source
;
105 if (changed
& IEEE802154_LLSEC_PARAM_PAN_ID
)
106 sec
->params
.pan_id
= params
->pan_id
;
107 if (changed
& IEEE802154_LLSEC_PARAM_HWADDR
)
108 sec
->params
.hwaddr
= params
->hwaddr
;
109 if (changed
& IEEE802154_LLSEC_PARAM_COORD_HWADDR
)
110 sec
->params
.coord_hwaddr
= params
->coord_hwaddr
;
111 if (changed
& IEEE802154_LLSEC_PARAM_COORD_SHORTADDR
)
112 sec
->params
.coord_shortaddr
= params
->coord_shortaddr
;
114 write_unlock_bh(&sec
->lock
);
121 static struct mac802154_llsec_key
*
122 llsec_key_alloc(const struct ieee802154_llsec_key
*template)
124 const int authsizes
[3] = { 4, 8, 16 };
125 struct mac802154_llsec_key
*key
;
128 key
= kzalloc(sizeof(*key
), GFP_KERNEL
);
132 kref_init(&key
->ref
);
133 key
->key
= *template;
135 BUILD_BUG_ON(ARRAY_SIZE(authsizes
) != ARRAY_SIZE(key
->tfm
));
137 for (i
= 0; i
< ARRAY_SIZE(key
->tfm
); i
++) {
138 key
->tfm
[i
] = crypto_alloc_aead("ccm(aes)", 0,
142 if (crypto_aead_setkey(key
->tfm
[i
], template->key
,
143 IEEE802154_LLSEC_KEY_SIZE
))
145 if (crypto_aead_setauthsize(key
->tfm
[i
], authsizes
[i
]))
149 key
->tfm0
= crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC
);
153 if (crypto_blkcipher_setkey(key
->tfm0
, template->key
,
154 IEEE802154_LLSEC_KEY_SIZE
))
160 crypto_free_blkcipher(key
->tfm0
);
162 for (i
= 0; i
< ARRAY_SIZE(key
->tfm
); i
++)
164 crypto_free_aead(key
->tfm
[i
]);
170 static void llsec_key_release(struct kref
*ref
)
172 struct mac802154_llsec_key
*key
;
175 key
= container_of(ref
, struct mac802154_llsec_key
, ref
);
177 for (i
= 0; i
< ARRAY_SIZE(key
->tfm
); i
++)
178 crypto_free_aead(key
->tfm
[i
]);
180 crypto_free_blkcipher(key
->tfm0
);
184 static struct mac802154_llsec_key
*
185 llsec_key_get(struct mac802154_llsec_key
*key
)
191 static void llsec_key_put(struct mac802154_llsec_key
*key
)
193 kref_put(&key
->ref
, llsec_key_release
);
196 static bool llsec_key_id_equal(const struct ieee802154_llsec_key_id
*a
,
197 const struct ieee802154_llsec_key_id
*b
)
199 if (a
->mode
!= b
->mode
)
202 if (a
->mode
== IEEE802154_SCF_KEY_IMPLICIT
)
203 return ieee802154_addr_equal(&a
->device_addr
, &b
->device_addr
);
209 case IEEE802154_SCF_KEY_SHORT_INDEX
:
210 return a
->short_source
== b
->short_source
;
211 case IEEE802154_SCF_KEY_HW_INDEX
:
212 return a
->extended_source
== b
->extended_source
;
218 int mac802154_llsec_key_add(struct mac802154_llsec
*sec
,
219 const struct ieee802154_llsec_key_id
*id
,
220 const struct ieee802154_llsec_key
*key
)
222 struct mac802154_llsec_key
*mkey
= NULL
;
223 struct ieee802154_llsec_key_entry
*pos
, *new;
225 if (!(key
->frame_types
& (1 << IEEE802154_FC_TYPE_MAC_CMD
)) &&
229 list_for_each_entry(pos
, &sec
->table
.keys
, list
) {
230 if (llsec_key_id_equal(&pos
->id
, id
))
233 if (memcmp(pos
->key
->key
, key
->key
,
234 IEEE802154_LLSEC_KEY_SIZE
))
237 mkey
= container_of(pos
->key
, struct mac802154_llsec_key
, key
);
239 /* Don't allow multiple instances of the same AES key to have
240 * different allowed frame types/command frame ids, as this is
241 * not possible in the 802.15.4 PIB.
243 if (pos
->key
->frame_types
!= key
->frame_types
||
244 pos
->key
->cmd_frame_ids
!= key
->cmd_frame_ids
)
250 new = kzalloc(sizeof(*new), GFP_KERNEL
);
255 mkey
= llsec_key_alloc(key
);
257 mkey
= llsec_key_get(mkey
);
263 new->key
= &mkey
->key
;
265 list_add_rcu(&new->list
, &sec
->table
.keys
);
274 int mac802154_llsec_key_del(struct mac802154_llsec
*sec
,
275 const struct ieee802154_llsec_key_id
*key
)
277 struct ieee802154_llsec_key_entry
*pos
;
279 list_for_each_entry(pos
, &sec
->table
.keys
, list
) {
280 struct mac802154_llsec_key
*mkey
;
282 mkey
= container_of(pos
->key
, struct mac802154_llsec_key
, key
);
284 if (llsec_key_id_equal(&pos
->id
, key
)) {
295 static bool llsec_dev_use_shortaddr(__le16 short_addr
)
297 return short_addr
!= cpu_to_le16(IEEE802154_ADDR_UNDEF
) &&
298 short_addr
!= cpu_to_le16(0xffff);
301 static u32
llsec_dev_hash_short(__le16 short_addr
, __le16 pan_id
)
303 return ((__force u16
) short_addr
) << 16 | (__force u16
) pan_id
;
306 static u64
llsec_dev_hash_long(__le64 hwaddr
)
308 return (__force u64
) hwaddr
;
311 static struct mac802154_llsec_device
*
312 llsec_dev_find_short(struct mac802154_llsec
*sec
, __le16 short_addr
,
315 struct mac802154_llsec_device
*dev
;
316 u32 key
= llsec_dev_hash_short(short_addr
, pan_id
);
318 hash_for_each_possible_rcu(sec
->devices_short
, dev
, bucket_s
, key
) {
319 if (dev
->dev
.short_addr
== short_addr
&&
320 dev
->dev
.pan_id
== pan_id
)
327 static struct mac802154_llsec_device
*
328 llsec_dev_find_long(struct mac802154_llsec
*sec
, __le64 hwaddr
)
330 struct mac802154_llsec_device
*dev
;
331 u64 key
= llsec_dev_hash_long(hwaddr
);
333 hash_for_each_possible_rcu(sec
->devices_hw
, dev
, bucket_hw
, key
) {
334 if (dev
->dev
.hwaddr
== hwaddr
)
341 static void llsec_dev_free(struct mac802154_llsec_device
*dev
)
343 struct ieee802154_llsec_device_key
*pos
, *pn
;
344 struct mac802154_llsec_device_key
*devkey
;
346 list_for_each_entry_safe(pos
, pn
, &dev
->dev
.keys
, list
) {
347 devkey
= container_of(pos
, struct mac802154_llsec_device_key
,
350 list_del(&pos
->list
);
357 int mac802154_llsec_dev_add(struct mac802154_llsec
*sec
,
358 const struct ieee802154_llsec_device
*dev
)
360 struct mac802154_llsec_device
*entry
;
361 u32 skey
= llsec_dev_hash_short(dev
->short_addr
, dev
->pan_id
);
362 u64 hwkey
= llsec_dev_hash_long(dev
->hwaddr
);
364 BUILD_BUG_ON(sizeof(hwkey
) != IEEE802154_ADDR_LEN
);
366 if ((llsec_dev_use_shortaddr(dev
->short_addr
) &&
367 llsec_dev_find_short(sec
, dev
->short_addr
, dev
->pan_id
)) ||
368 llsec_dev_find_long(sec
, dev
->hwaddr
))
371 entry
= kmalloc(sizeof(*entry
), GFP_KERNEL
);
376 spin_lock_init(&entry
->lock
);
377 INIT_LIST_HEAD(&entry
->dev
.keys
);
379 if (llsec_dev_use_shortaddr(dev
->short_addr
))
380 hash_add_rcu(sec
->devices_short
, &entry
->bucket_s
, skey
);
382 INIT_HLIST_NODE(&entry
->bucket_s
);
384 hash_add_rcu(sec
->devices_hw
, &entry
->bucket_hw
, hwkey
);
385 list_add_tail_rcu(&entry
->dev
.list
, &sec
->table
.devices
);
390 static void llsec_dev_free_rcu(struct rcu_head
*rcu
)
392 llsec_dev_free(container_of(rcu
, struct mac802154_llsec_device
, rcu
));
395 int mac802154_llsec_dev_del(struct mac802154_llsec
*sec
, __le64 device_addr
)
397 struct mac802154_llsec_device
*pos
;
399 pos
= llsec_dev_find_long(sec
, device_addr
);
403 hash_del_rcu(&pos
->bucket_s
);
404 hash_del_rcu(&pos
->bucket_hw
);
405 call_rcu(&pos
->rcu
, llsec_dev_free_rcu
);
412 static struct mac802154_llsec_device_key
*
413 llsec_devkey_find(struct mac802154_llsec_device
*dev
,
414 const struct ieee802154_llsec_key_id
*key
)
416 struct ieee802154_llsec_device_key
*devkey
;
418 list_for_each_entry_rcu(devkey
, &dev
->dev
.keys
, list
) {
419 if (!llsec_key_id_equal(key
, &devkey
->key_id
))
422 return container_of(devkey
, struct mac802154_llsec_device_key
,
429 int mac802154_llsec_devkey_add(struct mac802154_llsec
*sec
,
431 const struct ieee802154_llsec_device_key
*key
)
433 struct mac802154_llsec_device
*dev
;
434 struct mac802154_llsec_device_key
*devkey
;
436 dev
= llsec_dev_find_long(sec
, dev_addr
);
441 if (llsec_devkey_find(dev
, &key
->key_id
))
444 devkey
= kmalloc(sizeof(*devkey
), GFP_KERNEL
);
448 devkey
->devkey
= *key
;
449 list_add_tail_rcu(&devkey
->devkey
.list
, &dev
->dev
.keys
);
453 int mac802154_llsec_devkey_del(struct mac802154_llsec
*sec
,
455 const struct ieee802154_llsec_device_key
*key
)
457 struct mac802154_llsec_device
*dev
;
458 struct mac802154_llsec_device_key
*devkey
;
460 dev
= llsec_dev_find_long(sec
, dev_addr
);
465 devkey
= llsec_devkey_find(dev
, &key
->key_id
);
469 list_del_rcu(&devkey
->devkey
.list
);
470 kfree_rcu(devkey
, rcu
);
476 static struct mac802154_llsec_seclevel
*
477 llsec_find_seclevel(const struct mac802154_llsec
*sec
,
478 const struct ieee802154_llsec_seclevel
*sl
)
480 struct ieee802154_llsec_seclevel
*pos
;
482 list_for_each_entry(pos
, &sec
->table
.security_levels
, list
) {
483 if (pos
->frame_type
!= sl
->frame_type
||
484 (pos
->frame_type
== IEEE802154_FC_TYPE_MAC_CMD
&&
485 pos
->cmd_frame_id
!= sl
->cmd_frame_id
) ||
486 pos
->device_override
!= sl
->device_override
||
487 pos
->sec_levels
!= sl
->sec_levels
)
490 return container_of(pos
, struct mac802154_llsec_seclevel
,
497 int mac802154_llsec_seclevel_add(struct mac802154_llsec
*sec
,
498 const struct ieee802154_llsec_seclevel
*sl
)
500 struct mac802154_llsec_seclevel
*entry
;
502 if (llsec_find_seclevel(sec
, sl
))
505 entry
= kmalloc(sizeof(*entry
), GFP_KERNEL
);
511 list_add_tail_rcu(&entry
->level
.list
, &sec
->table
.security_levels
);
516 int mac802154_llsec_seclevel_del(struct mac802154_llsec
*sec
,
517 const struct ieee802154_llsec_seclevel
*sl
)
519 struct mac802154_llsec_seclevel
*pos
;
521 pos
= llsec_find_seclevel(sec
, sl
);
525 list_del_rcu(&pos
->level
.list
);