2
* Host AP crypto routines
4
* Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
5
* Portions Copyright (C) 2004, Intel Corporation <jketreno@linux.intel.com>
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
14
#include <linux/version.h>
15
#include <linux/module.h>
16
#include <linux/init.h>
17
#include <linux/slab.h>
18
#include <asm/string.h>
19
#include <asm/errno.h>
23
#ifndef BUILT_IN_RTLLIB
24
MODULE_AUTHOR("Jouni Malinen");
25
MODULE_DESCRIPTION("HostAP crypto");
26
MODULE_LICENSE("GPL");
29
struct rtllib_crypto_alg {
30
struct list_head list;
31
struct rtllib_crypto_ops *ops;
35
struct rtllib_crypto {
36
struct list_head algs;
40
static struct rtllib_crypto *hcrypt;
42
void rtllib_crypt_deinit_entries(struct rtllib_device *ieee,
45
struct list_head *ptr, *n;
46
struct rtllib_crypt_data *entry;
48
for (ptr = ieee->crypt_deinit_list.next, n = ptr->next;
49
ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) {
50
entry = list_entry(ptr, struct rtllib_crypt_data, list);
52
if (atomic_read(&entry->refcnt) != 0 && !force)
58
entry->ops->deinit(entry->priv);
59
#ifndef BUILT_IN_RTLLIB
60
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
61
module_put(entry->ops->owner);
63
__MOD_DEC_USE_COUNT(entry->ops->owner);
71
void rtllib_crypt_deinit_handler(unsigned long data)
73
struct rtllib_device *ieee = (struct rtllib_device *)data;
76
spin_lock_irqsave(&ieee->lock, flags);
77
rtllib_crypt_deinit_entries(ieee, 0);
78
if (!list_empty(&ieee->crypt_deinit_list)) {
79
printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
80
"deletion list\n", ieee->dev->name);
81
ieee->crypt_deinit_timer.expires = jiffies + HZ;
82
add_timer(&ieee->crypt_deinit_timer);
84
spin_unlock_irqrestore(&ieee->lock, flags);
88
void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee,
89
struct rtllib_crypt_data **crypt)
91
struct rtllib_crypt_data *tmp;
100
/* must not run ops->deinit() while there may be pending encrypt or
101
* decrypt operations. Use a list of delayed deinits to avoid needing
104
spin_lock_irqsave(&ieee->lock, flags);
105
list_add(&tmp->list, &ieee->crypt_deinit_list);
106
if (!timer_pending(&ieee->crypt_deinit_timer)) {
107
ieee->crypt_deinit_timer.expires = jiffies + HZ;
108
add_timer(&ieee->crypt_deinit_timer);
110
spin_unlock_irqrestore(&ieee->lock, flags);
113
int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops)
116
struct rtllib_crypto_alg *alg;
121
alg = kmalloc(sizeof(*alg), GFP_KERNEL);
125
memset(alg, 0, sizeof(*alg));
128
spin_lock_irqsave(&hcrypt->lock, flags);
129
list_add(&alg->list, &hcrypt->algs);
130
spin_unlock_irqrestore(&hcrypt->lock, flags);
132
printk(KERN_DEBUG "rtllib_crypt: registered algorithm '%s'\n",
138
int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops)
141
struct list_head *ptr;
142
struct rtllib_crypto_alg *del_alg = NULL;
147
spin_lock_irqsave(&hcrypt->lock, flags);
148
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
149
struct rtllib_crypto_alg *alg =
150
(struct rtllib_crypto_alg *) ptr;
151
if (alg->ops == ops) {
152
list_del(&alg->list);
157
spin_unlock_irqrestore(&hcrypt->lock, flags);
160
printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm "
161
"'%s'\n", ops->name);
165
return del_alg ? 0 : -1;
169
struct rtllib_crypto_ops * rtllib_get_crypto_ops(const char *name)
172
struct list_head *ptr;
173
struct rtllib_crypto_alg *found_alg = NULL;
178
spin_lock_irqsave(&hcrypt->lock, flags);
179
for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) {
180
struct rtllib_crypto_alg *alg =
181
(struct rtllib_crypto_alg *) ptr;
182
if (strcmp(alg->ops->name, name) == 0) {
187
spin_unlock_irqrestore(&hcrypt->lock, flags);
190
return found_alg->ops;
196
static void * rtllib_crypt_null_init(int keyidx) { return (void *) 1; }
197
static void rtllib_crypt_null_deinit(void *priv) {}
199
static struct rtllib_crypto_ops rtllib_crypt_null = {
201
.init = rtllib_crypt_null_init,
202
.deinit = rtllib_crypt_null_deinit,
203
.encrypt_mpdu = NULL,
204
.decrypt_mpdu = NULL,
205
.encrypt_msdu = NULL,
206
.decrypt_msdu = NULL,
209
.extra_prefix_len = 0,
210
.extra_postfix_len = 0,
211
.owner = THIS_MODULE,
215
int __init rtllib_crypto_init(void)
219
hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL);
223
memset(hcrypt, 0, sizeof(*hcrypt));
224
INIT_LIST_HEAD(&hcrypt->algs);
225
spin_lock_init(&hcrypt->lock);
227
ret = rtllib_register_crypto_ops(&rtllib_crypt_null);
237
void __exit rtllib_crypto_deinit(void)
239
struct list_head *ptr, *n;
244
for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
245
ptr = n, n = ptr->next) {
246
struct rtllib_crypto_alg *alg =
247
(struct rtllib_crypto_alg *) ptr;
249
printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm "
250
"'%s' (deinit)\n", alg->ops->name);
257
#ifndef BUILT_IN_RTLLIB
258
EXPORT_SYMBOL_RSL(rtllib_crypt_deinit_entries);
259
EXPORT_SYMBOL_RSL(rtllib_crypt_deinit_handler);
260
EXPORT_SYMBOL_RSL(rtllib_crypt_delayed_deinit);
262
EXPORT_SYMBOL_RSL(rtllib_register_crypto_ops);
263
EXPORT_SYMBOL_RSL(rtllib_unregister_crypto_ops);
264
EXPORT_SYMBOL_RSL(rtllib_get_crypto_ops);
266
module_init(rtllib_crypto_init);
267
module_exit(rtllib_crypto_deinit);