1 // SPDX-License-Identifier: GPL-2.0
3 * Host AP crypto routines
5 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
6 * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
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>
15 #include "ieee80211.h"
17 MODULE_AUTHOR("Jouni Malinen");
18 MODULE_DESCRIPTION("HostAP crypto");
19 MODULE_LICENSE("GPL");
21 struct ieee80211_crypto_alg {
22 struct list_head list;
23 struct ieee80211_crypto_ops *ops;
27 struct ieee80211_crypto {
28 struct list_head algs;
32 static struct ieee80211_crypto *hcrypt;
34 void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
37 struct list_head *ptr, *n;
38 struct ieee80211_crypt_data *entry;
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);
44 if (atomic_read(&entry->refcnt) != 0 && !force)
50 entry->ops->deinit(entry->priv);
55 void ieee80211_crypt_deinit_handler(struct timer_list *t)
57 struct ieee80211_device *ieee = from_timer(ieee, t, crypt_deinit_timer);
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",
65 ieee->crypt_deinit_timer.expires = jiffies + HZ;
66 add_timer(&ieee->crypt_deinit_timer);
68 spin_unlock_irqrestore(&ieee->lock, flags);
72 void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
73 struct ieee80211_crypt_data **crypt)
75 struct ieee80211_crypt_data *tmp;
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
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);
95 spin_unlock_irqrestore(&ieee->lock, flags);
98 int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops)
101 struct ieee80211_crypto_alg *alg;
106 alg = kzalloc(sizeof(*alg), GFP_KERNEL);
112 spin_lock_irqsave(&hcrypt->lock, flags);
113 list_add(&alg->list, &hcrypt->algs);
114 spin_unlock_irqrestore(&hcrypt->lock, flags);
116 pr_debug("ieee80211_crypt: registered algorithm '%s'\n",
122 int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops)
125 struct list_head *ptr;
126 struct ieee80211_crypto_alg *del_alg = NULL;
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);
141 spin_unlock_irqrestore(&hcrypt->lock, flags);
144 pr_debug("ieee80211_crypt: unregistered algorithm '%s'\n",
149 return del_alg ? 0 : -1;
153 struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name)
156 struct list_head *ptr;
157 struct ieee80211_crypto_alg *found_alg = NULL;
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) {
171 spin_unlock_irqrestore(&hcrypt->lock, flags);
174 return found_alg->ops;
179 static void *ieee80211_crypt_null_init(int keyidx) { return (void *)1; }
180 static void ieee80211_crypt_null_deinit(void *priv) {}
182 static struct ieee80211_crypto_ops ieee80211_crypt_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,
192 .extra_prefix_len = 0,
193 .extra_postfix_len = 0,
194 .owner = THIS_MODULE,
197 int __init ieee80211_crypto_init(void)
201 hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL);
205 INIT_LIST_HEAD(&hcrypt->algs);
206 spin_lock_init(&hcrypt->lock);
208 ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null);
217 void __exit ieee80211_crypto_deinit(void)
219 struct list_head *ptr, *n;
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;
229 pr_debug("ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",