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