1 // SPDX-License-Identifier: GPL-2.0-only
3 * libipw -- common bits for IPW drivers
5 * Copyright(c) 2008 John W. Linville <linville@tuxdriver.com>
7 * Portions copied from old ieee80211 component, w/ original copyright
10 * Host AP crypto routines
12 * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
13 * Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
17 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19 #include <linux/module.h>
20 #include <linux/ctype.h>
21 #include <linux/ieee80211.h>
22 #include <linux/errno.h>
23 #include <linux/init.h>
24 #include <linux/slab.h>
25 #include <linux/string.h>
28 struct libipw_crypto_alg
{
29 struct list_head list
;
30 const struct libipw_crypto_ops
*ops
;
33 static LIST_HEAD(libipw_crypto_algs
);
34 static DEFINE_SPINLOCK(libipw_crypto_lock
);
36 static void libipw_crypt_deinit_entries(struct libipw_crypt_info
*info
,
38 static void libipw_crypt_quiescing(struct libipw_crypt_info
*info
);
39 static void libipw_crypt_deinit_handler(struct timer_list
*t
);
41 int libipw_crypt_info_init(struct libipw_crypt_info
*info
, char *name
,
44 memset(info
, 0, sizeof(*info
));
49 INIT_LIST_HEAD(&info
->crypt_deinit_list
);
50 timer_setup(&info
->crypt_deinit_timer
, libipw_crypt_deinit_handler
,
55 EXPORT_SYMBOL(libipw_crypt_info_init
);
57 void libipw_crypt_info_free(struct libipw_crypt_info
*info
)
61 libipw_crypt_quiescing(info
);
62 del_timer_sync(&info
->crypt_deinit_timer
);
63 libipw_crypt_deinit_entries(info
, 1);
65 for (i
= 0; i
< NUM_WEP_KEYS
; i
++) {
66 struct libipw_crypt_data
*crypt
= info
->crypt
[i
];
69 crypt
->ops
->deinit(crypt
->priv
);
70 module_put(crypt
->ops
->owner
);
73 info
->crypt
[i
] = NULL
;
77 EXPORT_SYMBOL(libipw_crypt_info_free
);
79 static void libipw_crypt_deinit_entries(struct libipw_crypt_info
*info
,
82 struct libipw_crypt_data
*entry
, *next
;
85 spin_lock_irqsave(info
->lock
, flags
);
86 list_for_each_entry_safe(entry
, next
, &info
->crypt_deinit_list
, list
) {
87 if (atomic_read(&entry
->refcnt
) != 0 && !force
)
90 list_del(&entry
->list
);
93 entry
->ops
->deinit(entry
->priv
);
94 module_put(entry
->ops
->owner
);
98 spin_unlock_irqrestore(info
->lock
, flags
);
101 /* After this, crypt_deinit_list won't accept new members */
102 static void libipw_crypt_quiescing(struct libipw_crypt_info
*info
)
106 spin_lock_irqsave(info
->lock
, flags
);
107 info
->crypt_quiesced
= 1;
108 spin_unlock_irqrestore(info
->lock
, flags
);
111 static void libipw_crypt_deinit_handler(struct timer_list
*t
)
113 struct libipw_crypt_info
*info
= from_timer(info
, t
,
117 libipw_crypt_deinit_entries(info
, 0);
119 spin_lock_irqsave(info
->lock
, flags
);
120 if (!list_empty(&info
->crypt_deinit_list
) && !info
->crypt_quiesced
) {
121 printk(KERN_DEBUG
"%s: entries remaining in delayed crypt "
122 "deletion list\n", info
->name
);
123 info
->crypt_deinit_timer
.expires
= jiffies
+ HZ
;
124 add_timer(&info
->crypt_deinit_timer
);
126 spin_unlock_irqrestore(info
->lock
, flags
);
129 void libipw_crypt_delayed_deinit(struct libipw_crypt_info
*info
,
130 struct libipw_crypt_data
**crypt
)
132 struct libipw_crypt_data
*tmp
;
141 /* must not run ops->deinit() while there may be pending encrypt or
142 * decrypt operations. Use a list of delayed deinits to avoid needing
145 spin_lock_irqsave(info
->lock
, flags
);
146 if (!info
->crypt_quiesced
) {
147 list_add(&tmp
->list
, &info
->crypt_deinit_list
);
148 if (!timer_pending(&info
->crypt_deinit_timer
)) {
149 info
->crypt_deinit_timer
.expires
= jiffies
+ HZ
;
150 add_timer(&info
->crypt_deinit_timer
);
153 spin_unlock_irqrestore(info
->lock
, flags
);
155 EXPORT_SYMBOL(libipw_crypt_delayed_deinit
);
157 int libipw_register_crypto_ops(const struct libipw_crypto_ops
*ops
)
160 struct libipw_crypto_alg
*alg
;
162 alg
= kzalloc(sizeof(*alg
), GFP_KERNEL
);
168 spin_lock_irqsave(&libipw_crypto_lock
, flags
);
169 list_add(&alg
->list
, &libipw_crypto_algs
);
170 spin_unlock_irqrestore(&libipw_crypto_lock
, flags
);
172 printk(KERN_DEBUG
"libipw_crypt: registered algorithm '%s'\n",
177 EXPORT_SYMBOL(libipw_register_crypto_ops
);
179 int libipw_unregister_crypto_ops(const struct libipw_crypto_ops
*ops
)
181 struct libipw_crypto_alg
*alg
;
184 spin_lock_irqsave(&libipw_crypto_lock
, flags
);
185 list_for_each_entry(alg
, &libipw_crypto_algs
, list
) {
189 spin_unlock_irqrestore(&libipw_crypto_lock
, flags
);
193 printk(KERN_DEBUG
"libipw_crypt: unregistered algorithm '%s'\n",
195 list_del(&alg
->list
);
196 spin_unlock_irqrestore(&libipw_crypto_lock
, flags
);
200 EXPORT_SYMBOL(libipw_unregister_crypto_ops
);
202 const struct libipw_crypto_ops
*libipw_get_crypto_ops(const char *name
)
204 struct libipw_crypto_alg
*alg
;
207 spin_lock_irqsave(&libipw_crypto_lock
, flags
);
208 list_for_each_entry(alg
, &libipw_crypto_algs
, list
) {
209 if (strcmp(alg
->ops
->name
, name
) == 0)
212 spin_unlock_irqrestore(&libipw_crypto_lock
, flags
);
216 spin_unlock_irqrestore(&libipw_crypto_lock
, flags
);
219 EXPORT_SYMBOL(libipw_get_crypto_ops
);
221 static void *libipw_crypt_null_init(int keyidx
)
226 static void libipw_crypt_null_deinit(void *priv
)
230 static const struct libipw_crypto_ops libipw_crypt_null
= {
232 .init
= libipw_crypt_null_init
,
233 .deinit
= libipw_crypt_null_deinit
,
234 .owner
= THIS_MODULE
,
237 int __init
libipw_crypto_init(void)
239 return libipw_register_crypto_ops(&libipw_crypt_null
);
242 void libipw_crypto_exit(void)
244 libipw_unregister_crypto_ops(&libipw_crypt_null
);
245 BUG_ON(!list_empty(&libipw_crypto_algs
));