root/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ieee80211_crypt_deinit_entries
  2. ieee80211_crypt_deinit_handler
  3. ieee80211_crypt_delayed_deinit
  4. ieee80211_register_crypto_ops
  5. ieee80211_unregister_crypto_ops
  6. ieee80211_get_crypto_ops
  7. ieee80211_crypt_null_init
  8. ieee80211_crypt_null_deinit
  9. ieee80211_crypto_init
  10. ieee80211_crypto_deinit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Host AP crypto routines
   4  *
   5  * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
   6  * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
   7  */
   8 
   9 #include <linux/module.h>
  10 #include <linux/init.h>
  11 #include <linux/slab.h>
  12 #include <linux/string.h>
  13 #include <linux/errno.h>
  14 
  15 #include "ieee80211.h"
  16 
  17 MODULE_AUTHOR("Jouni Malinen");
  18 MODULE_DESCRIPTION("HostAP crypto");
  19 MODULE_LICENSE("GPL");
  20 
  21 struct ieee80211_crypto_alg {
  22         struct list_head list;
  23         struct ieee80211_crypto_ops *ops;
  24 };
  25 
  26 
  27 struct ieee80211_crypto {
  28         struct list_head algs;
  29         spinlock_t lock;
  30 };
  31 
  32 static struct ieee80211_crypto *hcrypt;
  33 
  34 void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
  35                                            int force)
  36 {
  37         struct list_head *ptr, *n;
  38         struct ieee80211_crypt_data *entry;
  39 
  40         for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
  41              ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
  42                 entry = list_entry(ptr, struct ieee80211_crypt_data, list);
  43 
  44                 if (atomic_read(&entry->refcnt) != 0 && !force)
  45                         continue;
  46 
  47                 list_del(ptr);
  48 
  49                 if (entry->ops)
  50                         entry->ops->deinit(entry->priv);
  51                 kfree(entry);
  52         }
  53 }
  54 
  55 void ieee80211_crypt_deinit_handler(struct timer_list *t)
  56 {
  57         struct ieee80211_device *ieee = from_timer(ieee, t, crypt_deinit_timer);
  58         unsigned long flags;
  59 
  60         spin_lock_irqsave(&ieee->lock, flags);
  61         ieee80211_crypt_deinit_entries(ieee, 0);
  62         if (!list_empty(&ieee->crypt_deinit_list)) {
  63                 netdev_dbg(ieee->dev, "%s: entries remaining in delayed crypt deletion list\n",
  64                                 ieee->dev->name);
  65                 ieee->crypt_deinit_timer.expires = jiffies + HZ;
  66                 add_timer(&ieee->crypt_deinit_timer);
  67         }
  68         spin_unlock_irqrestore(&ieee->lock, flags);
  69 
  70 }
  71 
  72 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
  73                                     struct ieee80211_crypt_data **crypt)
  74 {
  75         struct ieee80211_crypt_data *tmp;
  76         unsigned long flags;
  77 
  78         if (!(*crypt))
  79                 return;
  80 
  81         tmp = *crypt;
  82         *crypt = NULL;
  83 
  84         /* must not run ops->deinit() while there may be pending encrypt or
  85          * decrypt operations. Use a list of delayed deinits to avoid needing
  86          * locking.
  87          */
  88 
  89         spin_lock_irqsave(&ieee->lock, flags);
  90         list_add(&tmp->list, &ieee->crypt_deinit_list);
  91         if (!timer_pending(&ieee->crypt_deinit_timer)) {
  92                 ieee->crypt_deinit_timer.expires = jiffies + HZ;
  93                 add_timer(&ieee->crypt_deinit_timer);
  94         }
  95         spin_unlock_irqrestore(&ieee->lock, flags);
  96 }
  97 
  98 int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
  99 {
 100         unsigned long flags;
 101         struct ieee80211_crypto_alg *alg;
 102 
 103         if (!hcrypt)
 104                 return -1;
 105 
 106         alg = kzalloc(sizeof(*alg), GFP_KERNEL);
 107         if (!alg)
 108                 return -ENOMEM;
 109 
 110         alg->ops = ops;
 111 
 112         spin_lock_irqsave(&hcrypt->lock, flags);
 113         list_add(&alg->list, &hcrypt->algs);
 114         spin_unlock_irqrestore(&hcrypt->lock, flags);
 115 
 116         pr_debug("ieee80211_crypt: registered algorithm '%s'\n",
 117                ops->name);
 118 
 119         return 0;
 120 }
 121 
 122 int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
 123 {
 124         unsigned long flags;
 125         struct list_head *ptr;
 126         struct ieee80211_crypto_alg *del_alg = NULL;
 127 
 128         if (!hcrypt)
 129                 return -1;
 130 
 131         spin_lock_irqsave(&hcrypt->lock, flags);
 132         for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
 133                 struct ieee80211_crypto_alg *alg =
 134                         (struct ieee80211_crypto_alg *)ptr;
 135                 if (alg->ops == ops) {
 136                         list_del(&alg->list);
 137                         del_alg = alg;
 138                         break;
 139                 }
 140         }
 141         spin_unlock_irqrestore(&hcrypt->lock, flags);
 142 
 143         if (del_alg) {
 144                 pr_debug("ieee80211_crypt: unregistered algorithm '%s'\n",
 145                                 ops->name);
 146                 kfree(del_alg);
 147         }
 148 
 149         return del_alg ? 0 : -1;
 150 }
 151 
 152 
 153 struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
 154 {
 155         unsigned long flags;
 156         struct list_head *ptr;
 157         struct ieee80211_crypto_alg *found_alg = NULL;
 158 
 159         if (!hcrypt)
 160                 return NULL;
 161 
 162         spin_lock_irqsave(&hcrypt->lock, flags);
 163         for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
 164                 struct ieee80211_crypto_alg *alg =
 165                         (struct ieee80211_crypto_alg *)ptr;
 166                 if (strcmp(alg->ops->name, name) == 0) {
 167                         found_alg = alg;
 168                         break;
 169                 }
 170         }
 171         spin_unlock_irqrestore(&hcrypt->lock, flags);
 172 
 173         if (found_alg)
 174                 return found_alg->ops;
 175         return NULL;
 176 }
 177 
 178 
 179 static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; }
 180 static void ieee80211_crypt_null_deinit(void *priv) {}
 181 
 182 static struct ieee80211_crypto_ops ieee80211_crypt_null = {
 183         .name                   = "NULL",
 184         .init                   = ieee80211_crypt_null_init,
 185         .deinit                 = ieee80211_crypt_null_deinit,
 186         .encrypt_mpdu           = NULL,
 187         .decrypt_mpdu           = NULL,
 188         .encrypt_msdu           = NULL,
 189         .decrypt_msdu           = NULL,
 190         .set_key                = NULL,
 191         .get_key                = NULL,
 192         .extra_prefix_len       = 0,
 193         .extra_postfix_len      = 0,
 194         .owner                  = THIS_MODULE,
 195 };
 196 
 197 int __init ieee80211_crypto_init(void)
 198 {
 199         int ret = -ENOMEM;
 200 
 201         hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
 202         if (!hcrypt)
 203                 goto out;
 204 
 205         INIT_LIST_HEAD(&hcrypt->algs);
 206         spin_lock_init(&hcrypt->lock);
 207 
 208         ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
 209         if (ret < 0) {
 210                 kfree(hcrypt);
 211                 hcrypt = NULL;
 212         }
 213 out:
 214         return ret;
 215 }
 216 
 217 void __exit ieee80211_crypto_deinit(void)
 218 {
 219         struct list_head *ptr, *n;
 220 
 221         if (!hcrypt)
 222                 return;
 223 
 224         for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
 225              ptr = n, n = ptr->next) {
 226                 struct ieee80211_crypto_alg *alg =
 227                         (struct ieee80211_crypto_alg *)ptr;
 228                 list_del(ptr);
 229                 pr_debug("ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
 230                                 alg->ops->name);
 231                 kfree(alg);
 232         }
 233 
 234         kfree(hcrypt);
 235 }

/* [<][>][^][v][top][bottom][index][help] */