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 <linux/string.h>
19 #include <linux/errno.h>
23 struct rtllib_crypto_alg
{
24 struct list_head list
;
25 struct rtllib_crypto_ops
*ops
;
29 struct rtllib_crypto
{
30 struct list_head algs
;
34 static struct rtllib_crypto
*hcrypt
;
36 void rtllib_crypt_deinit_entries(struct rtllib_device
*ieee
,
39 struct list_head
*ptr
, *n
;
40 struct rtllib_crypt_data
*entry
;
42 for (ptr
= ieee
->crypt_deinit_list
.next
, n
= ptr
->next
;
43 ptr
!= &ieee
->crypt_deinit_list
; ptr
= n
, n
= ptr
->next
) {
44 entry
= list_entry(ptr
, struct rtllib_crypt_data
, list
);
46 if (atomic_read(&entry
->refcnt
) != 0 && !force
)
52 entry
->ops
->deinit(entry
->priv
);
57 void rtllib_crypt_deinit_handler(unsigned long data
)
59 struct rtllib_device
*ieee
= (struct rtllib_device
*)data
;
62 spin_lock_irqsave(&ieee
->lock
, flags
);
63 rtllib_crypt_deinit_entries(ieee
, 0);
64 if (!list_empty(&ieee
->crypt_deinit_list
)) {
65 printk(KERN_DEBUG
"%s: entries remaining in delayed crypt "
66 "deletion list\n", ieee
->dev
->name
);
67 ieee
->crypt_deinit_timer
.expires
= jiffies
+ HZ
;
68 add_timer(&ieee
->crypt_deinit_timer
);
70 spin_unlock_irqrestore(&ieee
->lock
, flags
);
74 void rtllib_crypt_delayed_deinit(struct rtllib_device
*ieee
,
75 struct rtllib_crypt_data
**crypt
)
77 struct rtllib_crypt_data
*tmp
;
86 /* must not run ops->deinit() while there may be pending encrypt or
87 * decrypt operations. Use a list of delayed deinits to avoid needing
90 spin_lock_irqsave(&ieee
->lock
, flags
);
91 list_add(&tmp
->list
, &ieee
->crypt_deinit_list
);
92 if (!timer_pending(&ieee
->crypt_deinit_timer
)) {
93 ieee
->crypt_deinit_timer
.expires
= jiffies
+ HZ
;
94 add_timer(&ieee
->crypt_deinit_timer
);
96 spin_unlock_irqrestore(&ieee
->lock
, flags
);
99 int rtllib_register_crypto_ops(struct rtllib_crypto_ops
*ops
)
102 struct rtllib_crypto_alg
*alg
;
107 alg
= kmalloc(sizeof(*alg
), GFP_KERNEL
);
111 memset(alg
, 0, sizeof(*alg
));
114 spin_lock_irqsave(&hcrypt
->lock
, flags
);
115 list_add(&alg
->list
, &hcrypt
->algs
);
116 spin_unlock_irqrestore(&hcrypt
->lock
, flags
);
118 printk(KERN_DEBUG
"rtllib_crypt: registered algorithm '%s'\n",
124 int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops
*ops
)
127 struct list_head
*ptr
;
128 struct rtllib_crypto_alg
*del_alg
= NULL
;
133 spin_lock_irqsave(&hcrypt
->lock
, flags
);
134 for (ptr
= hcrypt
->algs
.next
; ptr
!= &hcrypt
->algs
; ptr
= ptr
->next
) {
135 struct rtllib_crypto_alg
*alg
=
136 (struct rtllib_crypto_alg
*) ptr
;
137 if (alg
->ops
== ops
) {
138 list_del(&alg
->list
);
143 spin_unlock_irqrestore(&hcrypt
->lock
, flags
);
146 printk(KERN_DEBUG
"rtllib_crypt: unregistered algorithm "
147 "'%s'\n", ops
->name
);
151 return del_alg
? 0 : -1;
155 struct rtllib_crypto_ops
*rtllib_get_crypto_ops(const char *name
)
158 struct list_head
*ptr
;
159 struct rtllib_crypto_alg
*found_alg
= NULL
;
164 spin_lock_irqsave(&hcrypt
->lock
, flags
);
165 for (ptr
= hcrypt
->algs
.next
; ptr
!= &hcrypt
->algs
; ptr
= ptr
->next
) {
166 struct rtllib_crypto_alg
*alg
=
167 (struct rtllib_crypto_alg
*) ptr
;
168 if (strcmp(alg
->ops
->name
, name
) == 0) {
173 spin_unlock_irqrestore(&hcrypt
->lock
, flags
);
176 return found_alg
->ops
;
182 static void * rtllib_crypt_null_init(int keyidx
) { return (void *) 1; }
183 static void rtllib_crypt_null_deinit(void *priv
) {}
185 static struct rtllib_crypto_ops rtllib_crypt_null
= {
187 .init
= rtllib_crypt_null_init
,
188 .deinit
= rtllib_crypt_null_deinit
,
189 .encrypt_mpdu
= NULL
,
190 .decrypt_mpdu
= NULL
,
191 .encrypt_msdu
= NULL
,
192 .decrypt_msdu
= NULL
,
195 .extra_prefix_len
= 0,
196 .extra_postfix_len
= 0,
197 .owner
= THIS_MODULE
,
201 int __init
rtllib_crypto_init(void)
205 hcrypt
= kmalloc(sizeof(*hcrypt
), GFP_KERNEL
);
209 memset(hcrypt
, 0, sizeof(*hcrypt
));
210 INIT_LIST_HEAD(&hcrypt
->algs
);
211 spin_lock_init(&hcrypt
->lock
);
213 ret
= rtllib_register_crypto_ops(&rtllib_crypt_null
);
223 void __exit
rtllib_crypto_deinit(void)
225 struct list_head
*ptr
, *n
;
230 for (ptr
= hcrypt
->algs
.next
, n
= ptr
->next
; ptr
!= &hcrypt
->algs
;
231 ptr
= n
, n
= ptr
->next
) {
232 struct rtllib_crypto_alg
*alg
=
233 (struct rtllib_crypto_alg
*) ptr
;
235 printk(KERN_DEBUG
"rtllib_crypt: unregistered algorithm "
236 "'%s' (deinit)\n", alg
->ops
->name
);