^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2014 Fraunhofer ITWM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Written by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/ieee802154.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <crypto/aead.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <crypto/skcipher.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "ieee802154_i.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "llsec.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static void llsec_key_put(struct mac802154_llsec_key *key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static bool llsec_key_id_equal(const struct ieee802154_llsec_key_id *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) const struct ieee802154_llsec_key_id *b);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static void llsec_dev_free(struct mac802154_llsec_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) void mac802154_llsec_init(struct mac802154_llsec *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) memset(sec, 0, sizeof(*sec));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) memset(&sec->params.default_key_source, 0xFF, IEEE802154_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) INIT_LIST_HEAD(&sec->table.security_levels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) INIT_LIST_HEAD(&sec->table.devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) INIT_LIST_HEAD(&sec->table.keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) hash_init(sec->devices_short);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) hash_init(sec->devices_hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) rwlock_init(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) void mac802154_llsec_destroy(struct mac802154_llsec *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ieee802154_llsec_seclevel *sl, *sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct ieee802154_llsec_device *dev, *dn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct ieee802154_llsec_key_entry *key, *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) list_for_each_entry_safe(sl, sn, &sec->table.security_levels, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct mac802154_llsec_seclevel *msl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) msl = container_of(sl, struct mac802154_llsec_seclevel, level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) list_del(&sl->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) kfree_sensitive(msl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) list_for_each_entry_safe(dev, dn, &sec->table.devices, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct mac802154_llsec_device *mdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) mdev = container_of(dev, struct mac802154_llsec_device, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) list_del(&dev->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) llsec_dev_free(mdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) list_for_each_entry_safe(key, kn, &sec->table.keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct mac802154_llsec_key *mkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mkey = container_of(key->key, struct mac802154_llsec_key, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) list_del(&key->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) llsec_key_put(mkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) kfree_sensitive(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int mac802154_llsec_get_params(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct ieee802154_llsec_params *params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) read_lock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *params = sec->params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) read_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int mac802154_llsec_set_params(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) const struct ieee802154_llsec_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) write_lock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (changed & IEEE802154_LLSEC_PARAM_ENABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sec->params.enabled = params->enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (changed & IEEE802154_LLSEC_PARAM_FRAME_COUNTER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sec->params.frame_counter = params->frame_counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (changed & IEEE802154_LLSEC_PARAM_OUT_LEVEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) sec->params.out_level = params->out_level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (changed & IEEE802154_LLSEC_PARAM_OUT_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) sec->params.out_key = params->out_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (changed & IEEE802154_LLSEC_PARAM_KEY_SOURCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) sec->params.default_key_source = params->default_key_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (changed & IEEE802154_LLSEC_PARAM_PAN_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) sec->params.pan_id = params->pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (changed & IEEE802154_LLSEC_PARAM_HWADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) sec->params.hwaddr = params->hwaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (changed & IEEE802154_LLSEC_PARAM_COORD_HWADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) sec->params.coord_hwaddr = params->coord_hwaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (changed & IEEE802154_LLSEC_PARAM_COORD_SHORTADDR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sec->params.coord_shortaddr = params->coord_shortaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) write_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static struct mac802154_llsec_key*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) llsec_key_alloc(const struct ieee802154_llsec_key *template)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) const int authsizes[3] = { 4, 8, 16 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct mac802154_llsec_key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) key = kzalloc(sizeof(*key), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) kref_init(&key->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) key->key = *template;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) BUILD_BUG_ON(ARRAY_SIZE(authsizes) != ARRAY_SIZE(key->tfm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) for (i = 0; i < ARRAY_SIZE(key->tfm); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) key->tfm[i] = crypto_alloc_aead("ccm(aes)", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) CRYPTO_ALG_ASYNC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (IS_ERR(key->tfm[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) goto err_tfm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (crypto_aead_setkey(key->tfm[i], template->key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) IEEE802154_LLSEC_KEY_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto err_tfm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (crypto_aead_setauthsize(key->tfm[i], authsizes[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto err_tfm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) key->tfm0 = crypto_alloc_sync_skcipher("ctr(aes)", 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (IS_ERR(key->tfm0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto err_tfm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (crypto_sync_skcipher_setkey(key->tfm0, template->key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) IEEE802154_LLSEC_KEY_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) goto err_tfm0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) err_tfm0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) crypto_free_sync_skcipher(key->tfm0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) err_tfm:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) for (i = 0; i < ARRAY_SIZE(key->tfm); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!IS_ERR_OR_NULL(key->tfm[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) crypto_free_aead(key->tfm[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) kfree_sensitive(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static void llsec_key_release(struct kref *ref)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct mac802154_llsec_key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) key = container_of(ref, struct mac802154_llsec_key, ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = 0; i < ARRAY_SIZE(key->tfm); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) crypto_free_aead(key->tfm[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) crypto_free_sync_skcipher(key->tfm0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) kfree_sensitive(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static struct mac802154_llsec_key*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) llsec_key_get(struct mac802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) kref_get(&key->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) static void llsec_key_put(struct mac802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kref_put(&key->ref, llsec_key_release);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static bool llsec_key_id_equal(const struct ieee802154_llsec_key_id *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) const struct ieee802154_llsec_key_id *b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (a->mode != b->mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (a->mode == IEEE802154_SCF_KEY_IMPLICIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return ieee802154_addr_equal(&a->device_addr, &b->device_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (a->id != b->id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) switch (a->mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case IEEE802154_SCF_KEY_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case IEEE802154_SCF_KEY_SHORT_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return a->short_source == b->short_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) case IEEE802154_SCF_KEY_HW_INDEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return a->extended_source == b->extended_source;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int mac802154_llsec_key_add(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) const struct ieee802154_llsec_key_id *id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) const struct ieee802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct mac802154_llsec_key *mkey = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct ieee802154_llsec_key_entry *pos, *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (!(key->frame_types & (1 << IEEE802154_FC_TYPE_MAC_CMD)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) key->cmd_frame_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) list_for_each_entry(pos, &sec->table.keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (llsec_key_id_equal(&pos->id, id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (memcmp(pos->key->key, key->key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) IEEE802154_LLSEC_KEY_SIZE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) mkey = container_of(pos->key, struct mac802154_llsec_key, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Don't allow multiple instances of the same AES key to have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * different allowed frame types/command frame ids, as this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * not possible in the 802.15.4 PIB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (pos->key->frame_types != key->frame_types ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) pos->key->cmd_frame_ids != key->cmd_frame_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) new = kzalloc(sizeof(*new), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!mkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) mkey = llsec_key_alloc(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) mkey = llsec_key_get(mkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (!mkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) new->id = *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) new->key = &mkey->key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) list_add_rcu(&new->list, &sec->table.keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) kfree_sensitive(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int mac802154_llsec_key_del(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) const struct ieee802154_llsec_key_id *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct ieee802154_llsec_key_entry *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) list_for_each_entry(pos, &sec->table.keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct mac802154_llsec_key *mkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mkey = container_of(pos->key, struct mac802154_llsec_key, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (llsec_key_id_equal(&pos->id, key)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) list_del_rcu(&pos->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) llsec_key_put(mkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static bool llsec_dev_use_shortaddr(__le16 short_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return short_addr != cpu_to_le16(IEEE802154_ADDR_UNDEF) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) short_addr != cpu_to_le16(0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static u32 llsec_dev_hash_short(__le16 short_addr, __le16 pan_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return ((__force u16)short_addr) << 16 | (__force u16)pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) static u64 llsec_dev_hash_long(__le64 hwaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return (__force u64)hwaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) static struct mac802154_llsec_device*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) llsec_dev_find_short(struct mac802154_llsec *sec, __le16 short_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) __le16 pan_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct mac802154_llsec_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) u32 key = llsec_dev_hash_short(short_addr, pan_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) hash_for_each_possible_rcu(sec->devices_short, dev, bucket_s, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (dev->dev.short_addr == short_addr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev->dev.pan_id == pan_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static struct mac802154_llsec_device*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) llsec_dev_find_long(struct mac802154_llsec *sec, __le64 hwaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct mac802154_llsec_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) u64 key = llsec_dev_hash_long(hwaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) hash_for_each_possible_rcu(sec->devices_hw, dev, bucket_hw, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (dev->dev.hwaddr == hwaddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static void llsec_dev_free(struct mac802154_llsec_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct ieee802154_llsec_device_key *pos, *pn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct mac802154_llsec_device_key *devkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) list_for_each_entry_safe(pos, pn, &dev->dev.keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) devkey = container_of(pos, struct mac802154_llsec_device_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) devkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) list_del(&pos->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) kfree_sensitive(devkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) kfree_sensitive(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) int mac802154_llsec_dev_add(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) const struct ieee802154_llsec_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct mac802154_llsec_device *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) u32 skey = llsec_dev_hash_short(dev->short_addr, dev->pan_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) u64 hwkey = llsec_dev_hash_long(dev->hwaddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) BUILD_BUG_ON(sizeof(hwkey) != IEEE802154_ADDR_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if ((llsec_dev_use_shortaddr(dev->short_addr) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) llsec_dev_find_short(sec, dev->short_addr, dev->pan_id)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) llsec_dev_find_long(sec, dev->hwaddr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) entry = kmalloc(sizeof(*entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) entry->dev = *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) spin_lock_init(&entry->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) INIT_LIST_HEAD(&entry->dev.keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (llsec_dev_use_shortaddr(dev->short_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) hash_add_rcu(sec->devices_short, &entry->bucket_s, skey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) INIT_HLIST_NODE(&entry->bucket_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) hash_add_rcu(sec->devices_hw, &entry->bucket_hw, hwkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) list_add_tail_rcu(&entry->dev.list, &sec->table.devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static void llsec_dev_free_rcu(struct rcu_head *rcu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) llsec_dev_free(container_of(rcu, struct mac802154_llsec_device, rcu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int mac802154_llsec_dev_del(struct mac802154_llsec *sec, __le64 device_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct mac802154_llsec_device *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) pos = llsec_dev_find_long(sec, device_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (!pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) hash_del_rcu(&pos->bucket_s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) hash_del_rcu(&pos->bucket_hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) list_del_rcu(&pos->dev.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) call_rcu(&pos->rcu, llsec_dev_free_rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static struct mac802154_llsec_device_key*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) llsec_devkey_find(struct mac802154_llsec_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) const struct ieee802154_llsec_key_id *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct ieee802154_llsec_device_key *devkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) list_for_each_entry_rcu(devkey, &dev->dev.keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (!llsec_key_id_equal(key, &devkey->key_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) return container_of(devkey, struct mac802154_llsec_device_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) devkey);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) int mac802154_llsec_devkey_add(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) __le64 dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) const struct ieee802154_llsec_device_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct mac802154_llsec_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) struct mac802154_llsec_device_key *devkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) dev = llsec_dev_find_long(sec, dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (llsec_devkey_find(dev, &key->key_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) devkey = kmalloc(sizeof(*devkey), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (!devkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) devkey->devkey = *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) list_add_tail_rcu(&devkey->devkey.list, &dev->dev.keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) int mac802154_llsec_devkey_del(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) __le64 dev_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) const struct ieee802154_llsec_device_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) struct mac802154_llsec_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) struct mac802154_llsec_device_key *devkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) dev = llsec_dev_find_long(sec, dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) devkey = llsec_devkey_find(dev, &key->key_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!devkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) list_del_rcu(&devkey->devkey.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) kfree_rcu(devkey, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static struct mac802154_llsec_seclevel*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) llsec_find_seclevel(const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) const struct ieee802154_llsec_seclevel *sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct ieee802154_llsec_seclevel *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) list_for_each_entry(pos, &sec->table.security_levels, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (pos->frame_type != sl->frame_type ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) (pos->frame_type == IEEE802154_FC_TYPE_MAC_CMD &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) pos->cmd_frame_id != sl->cmd_frame_id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) pos->device_override != sl->device_override ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) pos->sec_levels != sl->sec_levels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return container_of(pos, struct mac802154_llsec_seclevel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int mac802154_llsec_seclevel_add(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) const struct ieee802154_llsec_seclevel *sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct mac802154_llsec_seclevel *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (llsec_find_seclevel(sec, sl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) return -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) entry = kmalloc(sizeof(*entry), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) entry->level = *sl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) list_add_tail_rcu(&entry->level.list, &sec->table.security_levels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int mac802154_llsec_seclevel_del(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) const struct ieee802154_llsec_seclevel *sl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct mac802154_llsec_seclevel *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) pos = llsec_find_seclevel(sec, sl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (!pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) list_del_rcu(&pos->level.list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) kfree_rcu(pos, rcu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int llsec_recover_addr(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct ieee802154_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) __le16 caddr = sec->params.coord_shortaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) addr->pan_id = sec->params.pan_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (caddr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) } else if (caddr == cpu_to_le16(IEEE802154_ADDR_UNDEF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) addr->extended_addr = sec->params.coord_hwaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) addr->mode = IEEE802154_ADDR_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) addr->short_addr = sec->params.coord_shortaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) addr->mode = IEEE802154_ADDR_SHORT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static struct mac802154_llsec_key*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) llsec_lookup_key(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) const struct ieee802154_addr *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) struct ieee802154_llsec_key_id *key_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct ieee802154_addr devaddr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) u8 key_id_mode = hdr->sec.key_id_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct ieee802154_llsec_key_entry *key_entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct mac802154_llsec_key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (key_id_mode == IEEE802154_SCF_KEY_IMPLICIT &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) devaddr.mode == IEEE802154_ADDR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (hdr->fc.type == IEEE802154_FC_TYPE_BEACON) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) devaddr.extended_addr = sec->params.coord_hwaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) devaddr.mode = IEEE802154_ADDR_LONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) } else if (llsec_recover_addr(sec, &devaddr) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) list_for_each_entry_rcu(key_entry, &sec->table.keys, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) const struct ieee802154_llsec_key_id *id = &key_entry->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (!(key_entry->key->frame_types & BIT(hdr->fc.type)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (id->mode != key_id_mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (key_id_mode == IEEE802154_SCF_KEY_IMPLICIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (ieee802154_addr_equal(&devaddr, &id->device_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) if (id->id != hdr->sec.key_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if ((key_id_mode == IEEE802154_SCF_KEY_INDEX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) (key_id_mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) id->short_source == hdr->sec.short_src) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) (key_id_mode == IEEE802154_SCF_KEY_HW_INDEX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) id->extended_source == hdr->sec.extended_src))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) goto found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) found:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) key = container_of(key_entry->key, struct mac802154_llsec_key, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (key_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) *key_id = key_entry->id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return llsec_key_get(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) static void llsec_geniv(u8 iv[16], __le64 addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) const struct ieee802154_sechdr *sec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) __be64 addr_bytes = (__force __be64) swab64((__force u64) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) __be32 frame_counter = (__force __be32) swab32((__force u32) sec->frame_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) iv[0] = 1; /* L' = L - 1 = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) memcpy(iv + 1, &addr_bytes, sizeof(addr_bytes));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) memcpy(iv + 9, &frame_counter, sizeof(frame_counter));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) iv[13] = sec->level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) iv[14] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) iv[15] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) llsec_do_encrypt_unauth(struct sk_buff *skb, const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) struct mac802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) u8 iv[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct scatterlist src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) SYNC_SKCIPHER_REQUEST_ON_STACK(req, key->tfm0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int err, datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) llsec_geniv(iv, sec->params.hwaddr, &hdr->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /* Compute data payload offset and data length */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) data = skb_mac_header(skb) + skb->mac_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) datalen = skb_tail_pointer(skb) - data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) sg_init_one(&src, data, datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) skcipher_request_set_sync_tfm(req, key->tfm0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) skcipher_request_set_callback(req, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) skcipher_request_set_crypt(req, &src, &src, datalen, iv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) err = crypto_skcipher_encrypt(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) skcipher_request_zero(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) static struct crypto_aead*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) llsec_tfm_by_len(struct mac802154_llsec_key *key, int authlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) for (i = 0; i < ARRAY_SIZE(key->tfm); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (crypto_aead_authsize(key->tfm[i]) == authlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return key->tfm[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) llsec_do_encrypt_auth(struct sk_buff *skb, const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) struct mac802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) u8 iv[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) int authlen, assoclen, datalen, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) struct scatterlist sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) struct aead_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) authlen = ieee802154_sechdr_authtag_len(&hdr->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) llsec_geniv(iv, sec->params.hwaddr, &hdr->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) req = aead_request_alloc(llsec_tfm_by_len(key, authlen), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) assoclen = skb->mac_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) data = skb_mac_header(skb) + skb->mac_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) datalen = skb_tail_pointer(skb) - data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) skb_put(skb, authlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) sg_init_one(&sg, skb_mac_header(skb), assoclen + datalen + authlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) if (!(hdr->sec.level & IEEE802154_SCF_SECLEVEL_ENC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) assoclen += datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) datalen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) aead_request_set_callback(req, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) aead_request_set_crypt(req, &sg, &sg, datalen, iv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) aead_request_set_ad(req, assoclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) rc = crypto_aead_encrypt(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) kfree_sensitive(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static int llsec_do_encrypt(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct mac802154_llsec_key *key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if (hdr->sec.level == IEEE802154_SCF_SECLEVEL_ENC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return llsec_do_encrypt_unauth(skb, sec, hdr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return llsec_do_encrypt_auth(skb, sec, hdr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int mac802154_llsec_encrypt(struct mac802154_llsec *sec, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct ieee802154_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int rc, authlen, hlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct mac802154_llsec_key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) u32 frame_ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) hlen = ieee802154_hdr_pull(skb, &hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (hlen < 0 || hdr.fc.type != IEEE802154_FC_TYPE_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (!hdr.fc.security_enabled ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) (hdr.sec.level == IEEE802154_SCF_SECLEVEL_NONE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) skb_push(skb, hlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) authlen = ieee802154_sechdr_authtag_len(&hdr.sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) if (skb->len + hlen + authlen + IEEE802154_MFR_SIZE > IEEE802154_MTU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) read_lock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (!sec->params.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) rc = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) goto fail_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) key = llsec_lookup_key(sec, &hdr, &hdr.dest, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) rc = -ENOKEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) goto fail_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) read_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) write_lock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) frame_ctr = be32_to_cpu(sec->params.frame_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) hdr.sec.frame_counter = cpu_to_le32(frame_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (frame_ctr == 0xFFFFFFFF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) write_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) llsec_key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) rc = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) sec->params.frame_counter = cpu_to_be32(frame_ctr + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) write_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) skb->mac_len = ieee802154_hdr_push(skb, &hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) skb_reset_mac_header(skb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) rc = llsec_do_encrypt(skb, sec, &hdr, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) llsec_key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) fail_read:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) read_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static struct mac802154_llsec_device*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) llsec_lookup_dev(struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) const struct ieee802154_addr *addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct ieee802154_addr devaddr = *addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct mac802154_llsec_device *dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (devaddr.mode == IEEE802154_ADDR_NONE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) llsec_recover_addr(sec, &devaddr) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (devaddr.mode == IEEE802154_ADDR_SHORT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) u32 key = llsec_dev_hash_short(devaddr.short_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) devaddr.pan_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) hash_for_each_possible_rcu(sec->devices_short, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) bucket_s, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (dev->dev.pan_id == devaddr.pan_id &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) dev->dev.short_addr == devaddr.short_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) u64 key = llsec_dev_hash_long(devaddr.extended_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) hash_for_each_possible_rcu(sec->devices_hw, dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) bucket_hw, key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (dev->dev.hwaddr == devaddr.extended_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) llsec_lookup_seclevel(const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) u8 frame_type, u8 cmd_frame_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) struct ieee802154_llsec_seclevel *rlevel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct ieee802154_llsec_seclevel *level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) list_for_each_entry_rcu(level, &sec->table.security_levels, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (level->frame_type == frame_type &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) (frame_type != IEEE802154_FC_TYPE_MAC_CMD ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) level->cmd_frame_id == cmd_frame_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) *rlevel = *level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) llsec_do_decrypt_unauth(struct sk_buff *skb, const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct mac802154_llsec_key *key, __le64 dev_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) u8 iv[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) int datalen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct scatterlist src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) SYNC_SKCIPHER_REQUEST_ON_STACK(req, key->tfm0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) llsec_geniv(iv, dev_addr, &hdr->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) data = skb_mac_header(skb) + skb->mac_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) datalen = skb_tail_pointer(skb) - data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sg_init_one(&src, data, datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) skcipher_request_set_sync_tfm(req, key->tfm0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) skcipher_request_set_callback(req, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) skcipher_request_set_crypt(req, &src, &src, datalen, iv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) err = crypto_skcipher_decrypt(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) skcipher_request_zero(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) llsec_do_decrypt_auth(struct sk_buff *skb, const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) struct mac802154_llsec_key *key, __le64 dev_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) u8 iv[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) unsigned char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) int authlen, datalen, assoclen, rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) struct scatterlist sg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) struct aead_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) authlen = ieee802154_sechdr_authtag_len(&hdr->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) llsec_geniv(iv, dev_addr, &hdr->sec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) req = aead_request_alloc(llsec_tfm_by_len(key, authlen), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) assoclen = skb->mac_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) data = skb_mac_header(skb) + skb->mac_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) datalen = skb_tail_pointer(skb) - data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) sg_init_one(&sg, skb_mac_header(skb), assoclen + datalen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (!(hdr->sec.level & IEEE802154_SCF_SECLEVEL_ENC)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) assoclen += datalen - authlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) datalen = authlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) aead_request_set_callback(req, 0, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) aead_request_set_crypt(req, &sg, &sg, datalen, iv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) aead_request_set_ad(req, assoclen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) rc = crypto_aead_decrypt(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) kfree_sensitive(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) skb_trim(skb, skb->len - authlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) llsec_do_decrypt(struct sk_buff *skb, const struct mac802154_llsec *sec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) const struct ieee802154_hdr *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) struct mac802154_llsec_key *key, __le64 dev_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) if (hdr->sec.level == IEEE802154_SCF_SECLEVEL_ENC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return llsec_do_decrypt_unauth(skb, sec, hdr, key, dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return llsec_do_decrypt_auth(skb, sec, hdr, key, dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) llsec_update_devkey_record(struct mac802154_llsec_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) const struct ieee802154_llsec_key_id *in_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) struct mac802154_llsec_device_key *devkey;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) devkey = llsec_devkey_find(dev, in_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) if (!devkey) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct mac802154_llsec_device_key *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) next = kzalloc(sizeof(*devkey), GFP_ATOMIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (!next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) next->devkey.key_id = *in_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) spin_lock_bh(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) devkey = llsec_devkey_find(dev, in_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) if (!devkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) list_add_rcu(&next->devkey.list, &dev->dev.keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) kfree_sensitive(next);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) spin_unlock_bh(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) llsec_update_devkey_info(struct mac802154_llsec_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) const struct ieee802154_llsec_key_id *in_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) u32 frame_counter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct mac802154_llsec_device_key *devkey = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (dev->dev.key_mode == IEEE802154_LLSEC_DEVKEY_RESTRICT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) devkey = llsec_devkey_find(dev, in_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (!devkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (dev->dev.key_mode == IEEE802154_LLSEC_DEVKEY_RECORD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) int rc = llsec_update_devkey_record(dev, in_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) if (rc < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) spin_lock_bh(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) if ((!devkey && frame_counter < dev->dev.frame_counter) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) (devkey && frame_counter < devkey->devkey.frame_counter)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) spin_unlock_bh(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (devkey)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) devkey->devkey.frame_counter = frame_counter + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) dev->dev.frame_counter = frame_counter + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) spin_unlock_bh(&dev->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) int mac802154_llsec_decrypt(struct mac802154_llsec *sec, struct sk_buff *skb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) struct ieee802154_hdr hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) struct mac802154_llsec_key *key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) struct ieee802154_llsec_key_id key_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) struct mac802154_llsec_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) struct ieee802154_llsec_seclevel seclevel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) __le64 dev_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) u32 frame_ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (ieee802154_hdr_peek(skb, &hdr) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (!hdr.fc.security_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (hdr.fc.version == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) read_lock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) if (!sec->params.enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) read_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) read_unlock_bh(&sec->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) key = llsec_lookup_key(sec, &hdr, &hdr.source, &key_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!key) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) err = -ENOKEY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) dev = llsec_lookup_dev(sec, &hdr.source);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (!dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) goto fail_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) if (llsec_lookup_seclevel(sec, hdr.fc.type, 0, &seclevel) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) goto fail_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (!(seclevel.sec_levels & BIT(hdr.sec.level)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) (hdr.sec.level == 0 && seclevel.device_override &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) !dev->dev.seclevel_exempt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) goto fail_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) frame_ctr = le32_to_cpu(hdr.sec.frame_counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (frame_ctr == 0xffffffff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) err = -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) goto fail_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) err = llsec_update_devkey_info(dev, &key_id, frame_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) goto fail_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) dev_addr = dev->dev.hwaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) err = llsec_do_decrypt(skb, sec, &hdr, key, dev_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) llsec_key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) fail_dev:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) llsec_key_put(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }