OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / net / ipsec / ipsec_alg.c
1 /*
2  * Modular extensions service and registration functions
3  *
4  * Author: JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
5  * 
6  * Version: 0.7.3
7  *
8  * $Id: ipsec_alg.c,v 1.3 2004-08-02 03:42:17 gerg Exp $
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2 of the License, or (at your
13  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
14  * 
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  * for more details.
19  *
20  */
21 #define __NO_VERSION__
22 #include <linux/module.h>
23 #include <linux/kernel.h> /* printk() */
24
25 #include <linux/netdevice.h>   /* struct device, and other headers */
26 #include <linux/etherdevice.h> /* eth_type_trans */
27 #include <linux/ip.h>          /* struct iphdr */
28 #include <linux/skbuff.h>
29 #include <linux/socket.h>
30 #include <linux/in.h>
31 #include <linux/types.h>
32 #include <linux/string.h>       /* memcmp() */
33 #include <linux/random.h>       /* get_random_bytes() */
34 #include <linux/errno.h>  /* error codes */
35 #ifdef SPINLOCK
36 # ifdef SPINLOCK_23
37 #  include <linux/spinlock.h> /* *lock* */
38 # else /* SPINLOCK_23 */
39 #  include <asm/spinlock.h> /* *lock* */
40 # endif /* SPINLOCK_23 */
41 #endif /* SPINLOCK */
42 #ifdef NET_21
43 # include <asm/uaccess.h>
44 # include <linux/in6.h>
45 # define proto_priv cb
46 #endif /* NET21 */
47 #include "ipsec_param.h"
48 #include <freeswan.h>
49 #include "radij.h"
50 #include "ipsec_encap.h"
51 #include "ipsec_radij.h"
52 #include "ipsec_netlink.h"
53 #include "ipsec_xform.h"
54 #include "ipsec_tunnel.h"
55 #include "ipsec_rcv.h"
56 #if defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH)
57 # include "ipsec_ah.h"
58 #endif /* defined(CONFIG_IPSEC_ESP) || defined(CONFIG_IPSEC_AH) */
59 #ifdef CONFIG_IPSEC_ESP
60 # include "ipsec_esp.h"
61 #endif /* !CONFIG_IPSEC_ESP */
62 #ifdef CONFIG_IPSEC_IPCOMP
63 # include "ipcomp.h"
64 #endif /* CONFIG_IPSEC_COMP */
65
66 #include <pfkeyv2.h>
67 #include <pfkey.h>
68
69 #include "ipsec_sa.h"
70 #include "ipsec_alg.h"
71
72 #if SADB_EALG_MAX < 255
73 #warning Compiling with limited ESP support ( SADB_EALG_MAX < 256 )
74 #endif
75
76 static rwlock_t ipsec_alg_lock = RW_LOCK_UNLOCKED;
77 #define IPSEC_ALG_HASHSZ        16      /* must be power of 2, even 2^0=1 */
78 static struct list_head ipsec_alg_hash_table[IPSEC_ALG_HASHSZ];
79
80 /*      Old gcc's will fail here        */
81 #define barf_out(fmt, args...)  do { printk(KERN_ERR "%s: (%s) " fmt, __FUNCTION__, ixt->ixt_name , ## args)\
82         ; goto out; } while(0)
83
84 /* 
85  *      Must be already protected by lock 
86  */
87 static void __ipsec_alg_usage_inc(struct ipsec_alg *ixt) {
88         if (ixt->ixt_module)
89                 __MOD_INC_USE_COUNT(ixt->ixt_module);
90         atomic_inc(&ixt->ixt_refcnt);
91 }
92 static void __ipsec_alg_usage_dec(struct ipsec_alg *ixt) {
93         atomic_dec(&ixt->ixt_refcnt);
94         if (ixt->ixt_module)
95                 __MOD_DEC_USE_COUNT(ixt->ixt_module);
96 }
97 /*
98  *      simple hash function, optimized for 0-hash (1 list) special
99  *      case
100  */
101 #if IPSEC_ALG_HASHSZ > 1
102 static inline unsigned ipsec_alg_hashfn(int alg_type, int alg_id) {
103         return ((alg_type^alg_id)&(IPSEC_ALG_HASHSZ-1));
104 }
105 #else
106 #define ipsec_alg_hashfn(x,y) (0)
107 #endif
108
109 /*****************************************************************
110  *
111  *      INTERNAL table handling: insert, delete, find
112  *
113  *****************************************************************/
114
115 /*      
116  *      hash table initialization, called from ipsec_alg_init()
117  */
118 static void ipsec_alg_hash_init(void) {
119         struct list_head *head = ipsec_alg_hash_table;
120         int i = IPSEC_ALG_HASHSZ;
121         do {
122                 INIT_LIST_HEAD(head);
123                 head++;
124                 i--;
125         } while (i);
126 }
127 /*
128  *      hash list lookup by {alg_type, alg_id} and table head,
129  *      must be already protected by lock
130  */
131 static struct ipsec_alg *__ipsec_alg_find(unsigned alg_type, unsigned alg_id, struct list_head * head) {
132         struct list_head *p;
133         struct ipsec_alg *ixt=NULL;
134         for (p=head->next; p!=head; p=p->next) {
135                 ixt = list_entry(p, struct ipsec_alg, ixt_list);
136                 if (ixt->ixt_alg_type == alg_type && ixt->ixt_alg_id==alg_id) {
137                         goto out;
138                 }
139         }
140         ixt=NULL;
141 out:
142         return ixt;
143 }
144 /*
145  *      inserts (in front) a new entry in hash table, 
146  *      called from ipsec_alg_register() when new algorithm is registered.
147  */
148 static int ipsec_alg_insert(struct ipsec_alg *ixt) {
149         int ret=-EINVAL;
150         unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id);
151         struct list_head *head= ipsec_alg_hash_table + hashval;
152         /*      new element must be virgin ... */
153         if (ixt->ixt_list.next != &ixt->ixt_list || 
154                 ixt->ixt_list.prev != &ixt->ixt_list) {
155                 printk(KERN_ERR "%s: ixt object \"%s\" "
156                                 "list head not initialized\n",
157                                 __FUNCTION__, ixt->ixt_name);
158                 return ret;
159         }
160         write_lock_bh(&ipsec_alg_lock);
161         if (__ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head))
162                 barf_out(KERN_WARNING "ipsec_alg for alg_type=%d, alg_id=%d already exist."
163                                 "Not loaded (ret=%d).\n",
164                                 ixt->ixt_alg_type,
165                                 ixt->ixt_alg_id, ret=-EEXIST);
166         list_add(&ixt->ixt_list, head);
167         ret=0;
168 out:
169         write_unlock_bh(&ipsec_alg_lock);
170         return ret;
171 }
172 /*
173  *      deletes an existing entry in hash table, 
174  *      called from ipsec_alg_unregister() when algorithm is unregistered.
175  */
176 static int ipsec_alg_delete(struct ipsec_alg *ixt) {
177         write_lock_bh(&ipsec_alg_lock);
178         list_del(&ixt->ixt_list);
179         write_unlock_bh(&ipsec_alg_lock);
180         return 0;
181 }
182 /*
183  *      here @user context (read-only when @kernel bh context) 
184  *      -> no bh disabling
185  *
186  *      called from ipsec_sa_init() -> ipsec_alg_sa_init()
187  */
188 static struct ipsec_alg *ipsec_alg_get(int alg_type, int alg_id) {
189         unsigned hashval=ipsec_alg_hashfn(alg_type, alg_id);
190         struct list_head *head= ipsec_alg_hash_table + hashval;
191         struct ipsec_alg *ixt;
192         read_lock(&ipsec_alg_lock);
193         ixt=__ipsec_alg_find(alg_type, alg_id, head);
194         if (ixt) __ipsec_alg_usage_inc(ixt);
195         read_unlock(&ipsec_alg_lock);
196         return ixt;
197 }
198
199 static void ipsec_alg_put(struct ipsec_alg *ixt) {
200         __ipsec_alg_usage_dec((struct ipsec_alg *)ixt);
201 }
202
203 /*****************************************************************
204  *
205  *      INTERFACE for ENC services: key creation, encrypt function
206  *
207  *****************************************************************/
208
209 /*
210  *      main encrypt service entry point
211  *      called from ipsec_rcv() with encrypt=IPSEC_ALG_DECRYPT and
212  *      ipsec_tunnel_start_xmit with encrypt=IPSEC_ALG_ENCRYPT
213  */
214 int ipsec_alg_esp_encrypt(struct ipsec_sa *sa_p, __u8 * idat, int ilen, const __u8 * iv, int encrypt) {
215         int ret;
216         struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
217         KLIPS_PRINT(debug_rcv||debug_tunnel,
218                     "klips_debug:ipsec_alg_esp_encrypt: "
219                     "entering with encalg=%d, ixt_e=%p\n",
220                     sa_p->ips_encalg, ixt_e);
221         if (!ixt_e) {
222                 KLIPS_PRINT(debug_rcv||debug_tunnel,
223                             "klips_debug:ipsec_alg_esp_encrypt: "
224                             "NULL ipsec_alg_enc object\n");
225                 return -1;
226         }
227         KLIPS_PRINT(debug_rcv||debug_tunnel,
228                     "klips_debug:ipsec_alg_esp_encrypt: "
229                     "calling cbc_encrypt encalg=%d "
230                     "ips_key_e=%p idat=%p ilen=%d iv=%p, encrypt=%d\n",
231                         sa_p->ips_encalg, 
232                         sa_p->ips_key_e, idat, ilen, iv, encrypt);
233         ret=ixt_e->ixt_e_cbc_encrypt(sa_p->ips_key_e, idat, idat, ilen, iv, encrypt);
234         KLIPS_PRINT(debug_rcv||debug_tunnel,
235                     "klips_debug:ipsec_alg_esp_encrypt: "
236                     "returned ret=%d\n",
237                     ret);
238         return ret;
239 }
240 /*
241  *      encryption key context creation function
242  *      called from pfkey_v2_parser.c:pfkey_ips_init() 
243  */
244 int ipsec_alg_enc_key_create(struct ipsec_sa *sa_p) {
245         int ret=-EINVAL;
246         int keyminbits, keymaxbits;
247         caddr_t ekp;
248         struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
249
250         KLIPS_PRINT(debug_pfkey,
251                     "klips_debug:ipsec_alg_enc_key_create: "
252                     "entering with encalg=%d ixt_e=%p\n",
253                     sa_p->ips_encalg, ixt_e);
254         if (!ixt_e) {
255                 KLIPS_PRINT(debug_pfkey,
256                             "klips_debug:ipsec_alg_enc_key_create: "
257                             "NULL ipsec_alg_enc object\n");
258                 return -EPROTO;
259         }
260         if (ixt_e->ixt_e_validate_key) {
261                 if ((ret=ixt_e->ixt_e_validate_key(sa_p)) < 0) {
262                         KLIPS_PRINT(debug_pfkey,
263                                 "klips_debug:pfkey_ipsec_sa_init: "
264                                 "error calling validate_key() "
265                                 "key_bits_e=%d\n",
266                                 sa_p->ips_key_bits_e);
267                         goto ixt_out;
268                 }
269         } else {
270                 keyminbits=ixt_e->ixt_keyminbits;
271                 keymaxbits=ixt_e->ixt_keymaxbits;
272                 if(sa_p->ips_key_bits_e<keyminbits || 
273                                 sa_p->ips_key_bits_e>keymaxbits) {
274                         KLIPS_PRINT(debug_pfkey,
275                                 "klips_debug:ipsec_alg_enc_key_create: "
276                                 "incorrect encryption key size: %d bits -- "
277                                 "must be between %d,%d bits\n" /*octets (bytes)\n"*/,
278                                 sa_p->ips_key_bits_e, keyminbits, keymaxbits);
279                         ret=-EINVAL;
280                         goto ixt_out;
281                 }
282         }
283         /* save encryption key pointer */
284         ekp = sa_p->ips_key_e;
285
286         if((sa_p->ips_key_e = (caddr_t)
287             kmalloc((sa_p->ips_key_e_size = ixt_e->ixt_e_ctx_size),
288                     GFP_ATOMIC)) == NULL) {
289                 ret=-ENOMEM;
290                 goto ixt_out;
291         }
292         /* zero-out key_e */
293         memset(sa_p->ips_key_e, 0, sa_p->ips_key_e_size);
294
295         /* I cast here to allow more decoupling in alg module */
296         KLIPS_PRINT(debug_pfkey,
297                     "klips_debug:ipsec_alg_enc_key_create: about to call:"
298                             "set_key(key_e=%p, ekp=%p, key_size=%d)\n",
299                             (caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
300         ret = ixt_e->ixt_e_set_key((caddr_t)sa_p->ips_key_e, ekp, sa_p->ips_key_bits_e/8);
301         /* paranoid */
302         memset(ekp, 0, sa_p->ips_key_bits_e/8);
303         kfree(ekp);
304 ixt_out:
305         return ret;
306 }
307
308 #ifdef USE_IXP4XX_CRYPTO
309 /*      cipher block size extraction function */
310 void ipsec_alg_enc_blksize_create(struct ipsec_sa *sa_p)  {
311         struct ipsec_alg_enc *ixt_e=sa_p->ips_alg_enc;
312
313         /* Set cipher block size */
314     sa_p->ips_enc_blksize = ixt_e->ixt_blocksize;
315 }
316 #endif /* USE_IXP4XX_CRYPTO */
317
318 /***************************************************************
319  *
320  *      INTERFACE for AUTH services: key creation, hash functions
321  *
322  ***************************************************************/
323
324 /*
325  *      auth key context creation function
326  *      called from pfkey_v2_parser.c:pfkey_ips_init() 
327  */
328 int ipsec_alg_auth_key_create(struct ipsec_sa *sa_p) {
329         int ret=-EINVAL;
330         struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth;
331         int keyminbits, keymaxbits;
332 #ifndef USE_IXP4XX_CRYPTO
333         unsigned char *akp;
334         unsigned int aks;
335 #endif /* USE_IXP4XX_CRYPTO */
336         KLIPS_PRINT(debug_pfkey,
337                     "klips_debug:ipsec_alg_auth_key_create: "
338                     "entering with authalg=%d ixt_a=%p\n",
339                     sa_p->ips_authalg, ixt_a);
340         if (!ixt_a) {
341                 KLIPS_PRINT(debug_pfkey,
342                             "klips_debug:ipsec_alg_auth_key_create: "
343                             "NULL ipsec_alg_auth object\n");
344                 return -EPROTO;
345         }
346         keyminbits=ixt_a->ixt_keyminbits;
347         keymaxbits=ixt_a->ixt_keymaxbits;
348         if(sa_p->ips_key_bits_a<keyminbits || sa_p->ips_key_bits_a>keymaxbits) {
349                 KLIPS_PRINT(debug_pfkey,
350                             "klips_debug:ipsec_alg_auth_key_create: incorrect auth"
351                             "key size: %d bits -- must be between %d,%d bits\n"/*octets (bytes)\n"*/,
352                             sa_p->ips_key_bits_a, keyminbits, keymaxbits);
353                 ret=-EINVAL;
354                 goto ixt_out;
355         }
356         /* save auth key pointer */
357         sa_p->ips_auth_bits = ixt_a->ixt_a_keylen * 8; /* XXX XXX */
358 #ifndef USE_IXP4XX_CRYPTO
359         akp = sa_p->ips_key_a;
360         aks = sa_p->ips_key_a_size;
361
362         /* will hold: 2 ctx and a blocksize buffer: kb */
363         sa_p->ips_key_a_size = ixt_a->ixt_a_ctx_size;
364         if((sa_p->ips_key_a = 
365                 (caddr_t) kmalloc(sa_p->ips_key_a_size, GFP_ATOMIC)) == NULL) {
366                 ret=-ENOMEM;
367                 goto ixt_out;
368         }
369         ixt_a->ixt_a_hmac_set_key(sa_p->ips_key_a, akp, sa_p->ips_key_bits_a/8); /* XXX XXX */
370         ret=0;
371         memset(akp, 0, aks);
372         kfree(akp);
373                         
374 #endif /* USE_IXP4XX_CRYPTO */
375 ixt_out:
376         return ret;
377 }
378 int ipsec_alg_sa_esp_hash(const struct ipsec_sa *sa_p, const __u8 *espp, int len, __u8 *hash, int hashlen) {
379         struct ipsec_alg_auth *ixt_a=sa_p->ips_alg_auth;
380         if (!ixt_a) {
381                 KLIPS_PRINT(debug_pfkey,
382                             "klips_debug:ipsec_sa_esp_hash: "
383                             "NULL ipsec_alg_auth object\n");
384                 return -EPROTO;
385         }
386         KLIPS_PRINT(debug_tunnel|debug_rcv,
387                         "klips_debug:ipsec_sa_esp_hash: "
388                         "hashing %p (%d bytes) to %p (%d bytes)\n",
389                         espp, len,
390                         hash, hashlen);
391         ixt_a->ixt_a_hmac_hash(sa_p->ips_key_a, 
392                         espp, len,
393                         hash, hashlen);
394         return 0;
395 }
396
397 /***************************************************************
398  *
399  *      INTERFACE for module loading,testing, and unloading
400  *
401  ***************************************************************/
402
403 /* validation for registering (enc) module */
404 static int check_enc(struct ipsec_alg_enc *ixt) {
405         int ret=-EINVAL;
406         if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_EALG_MAX)
407                 barf_out("invalid alg_id=%d >= %d\n", ixt->ixt_alg_id, SADB_EALG_MAX);
408         if (ixt->ixt_blocksize==0) /*  || ixt->ixt_blocksize%2) need for ESP_NULL */
409                 barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize);
410         if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_e_keylen==0)
411                 goto zero_key_ok;
412         if (ixt->ixt_keyminbits==0)
413                 barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits);
414         if (ixt->ixt_keymaxbits==0)
415                 barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits);
416         if (ixt->ixt_e_keylen==0)
417                 barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_e_keylen);
418 zero_key_ok:
419         if (ixt->ixt_e_ctx_size==0)
420                 barf_out(KERN_ERR "invalid key_e_size=%d\n", ixt->ixt_e_ctx_size);
421         if (ixt->ixt_e_cbc_encrypt==NULL)
422                 barf_out(KERN_ERR "e_cbc_encrypt() must be not NULL\n");
423         ret=0;
424 out:
425         return ret;
426 }
427
428 /* validation for registering (auth) module */
429 static int check_auth(struct ipsec_alg_auth *ixt) {
430         int ret=-EINVAL;
431         if (ixt->ixt_alg_id==0 || ixt->ixt_alg_id > SADB_AALG_MAX)
432                 barf_out("invalid alg_id=%d > %d (SADB_AALG_MAX)\n", ixt->ixt_alg_id, SADB_AALG_MAX);
433         if (ixt->ixt_blocksize==0 || ixt->ixt_blocksize%2)
434                 barf_out(KERN_ERR "invalid blocksize=%d\n", ixt->ixt_blocksize);
435         if (ixt->ixt_blocksize>AH_BLKLEN_MAX)
436                 barf_out(KERN_ERR "sorry blocksize=%d > %d. "
437                         "Please increase AH_BLKLEN_MAX and recompile\n", 
438                         ixt->ixt_blocksize,
439                         AH_BLKLEN_MAX);
440         if (ixt->ixt_keyminbits==0 && ixt->ixt_keymaxbits==0 && ixt->ixt_a_keylen==0)
441                 goto zero_key_ok;
442         if (ixt->ixt_keyminbits==0)
443                 barf_out(KERN_ERR "invalid keyminbits=%d\n", ixt->ixt_keyminbits);
444         if (ixt->ixt_keymaxbits==0)
445                 barf_out(KERN_ERR "invalid keymaxbits=%d\n", ixt->ixt_keymaxbits);
446         if (ixt->ixt_keymaxbits!=ixt->ixt_keyminbits)
447                 barf_out(KERN_ERR "keymaxbits must equal keyminbits (not sure).\n");
448         if (ixt->ixt_a_keylen==0)
449                 barf_out(KERN_ERR "invalid keysize=%d\n", ixt->ixt_a_keylen);
450 zero_key_ok:
451         if (ixt->ixt_a_ctx_size==0)
452                 barf_out(KERN_ERR "invalid a_ctx_size=%d\n", ixt->ixt_a_ctx_size);
453         if (ixt->ixt_a_hmac_set_key==NULL)
454                 barf_out(KERN_ERR "a_hmac_set_key() must be not NULL\n");
455         if (ixt->ixt_a_hmac_hash==NULL)
456                 barf_out(KERN_ERR "a_hmac_hash() must be not NULL\n");
457         ret=0;
458 out:
459         return ret;
460 }
461
462 /* 
463  * Generic (enc, auth) registration entry point 
464  */
465 int register_ipsec_alg(struct ipsec_alg *ixt) {
466         int ret=-EINVAL;
467         /*      Validation      */
468         if (ixt==NULL)
469                 barf_out("NULL ipsec_alg object passed\n");
470         if ((ixt->ixt_version&0xffffff00) != (IPSEC_ALG_VERSION&0xffffff00))
471                 barf_out("incorrect version: %d.%d.%d-%d, "
472                         "must be %d.%d.%d[-%d]\n",
473                                 IPSEC_ALG_VERSION_QUAD(ixt->ixt_version), 
474                                 IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION));
475         switch(ixt->ixt_alg_type) {
476                 case IPSEC_ALG_TYPE_AUTH:
477                         if ((ret=check_auth((struct ipsec_alg_auth *)ixt)<0))
478                                 goto out;
479                         break;
480                 case IPSEC_ALG_TYPE_ENCRYPT: 
481                         if ((ret=check_enc((struct ipsec_alg_enc *)ixt)<0))
482                                 goto out;
483                         if (ixt->ixt_ivlen == 0)
484                                 ixt->ixt_ivlen = ixt->ixt_blocksize*8;
485                         break;
486                 default:
487                         barf_out("alg_type=%d not supported", ixt->ixt_alg_type);
488         }
489         INIT_LIST_HEAD(&ixt->ixt_list);
490         ret = ipsec_alg_insert(ixt);
491         if (ret<0) 
492                 barf_out(KERN_WARNING "ipsec_alg for alg_id=%d failed."
493                                 "Not loaded (ret=%d).\n",
494                                 ixt->ixt_alg_id, ret);
495
496         ret = pfkey_list_insert_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP]));
497         if (ret==0) {
498                 ixt->ixt_state |= IPSEC_ALG_ST_SUPP;
499                 /*      send register event to userspace        */
500                 pfkey_register_reply(SADB_SATYPE_ESP, NULL);
501         } else
502                 printk(KERN_ERR "pfkey_list_insert_supported returned %d. "
503                                 "Loading anyway.\n", ret);
504         ret=0;
505 out:
506         return ret;
507 }
508
509 /* 
510  *      unregister ipsec_alg object from own tables, if 
511  *      success => calls pfkey_list_remove_supported()
512  */
513 int unregister_ipsec_alg(struct ipsec_alg *ixt) {
514         int ret= -EINVAL;
515         switch(ixt->ixt_alg_type) {
516                 case IPSEC_ALG_TYPE_AUTH:
517                 case IPSEC_ALG_TYPE_ENCRYPT: 
518                         break;
519                 default:
520                         /*      this is not a typo :) */
521                         barf_out("frog found in list (\"%s\"): ixt_p=NULL\n", 
522                                 ixt->ixt_name);
523         }
524
525         ret=ipsec_alg_delete(ixt);
526         if (ixt->ixt_state&IPSEC_ALG_ST_SUPP) {
527                 ixt->ixt_state &= ~IPSEC_ALG_ST_SUPP;
528                 pfkey_list_remove_supported((struct supported *)&ixt->ixt_support, &(pfkey_supported_list[SADB_SATYPE_ESP]));
529                 /*      send register event to userspace        */
530                 pfkey_register_reply(SADB_SATYPE_ESP, NULL);
531         }
532
533 out:
534         return ret;
535 }
536 /*
537  *      Must be called from user context
538  *      used at module load type for testing algo implementation
539  */
540 static int ipsec_alg_test_encrypt(int enc_alg, int test) {
541         int ret;
542         caddr_t buf;
543         int iv_size, keysize, key_e_size;
544         struct ipsec_alg_enc *ixt_e;
545         #define BUFSZ   1024
546         #define MARGIN  0
547         #define test_enc   (buf+MARGIN)
548         #define test_dec   (test_enc+BUFSZ+MARGIN)
549         #define test_tmp   (test_dec+BUFSZ+MARGIN)
550         #define test_key_e (test_tmp+BUFSZ+MARGIN)
551         #define test_iv    (test_key_e+key_e_size+MARGIN)
552         #define test_key   (test_iv+iv_size+MARGIN)
553         #define test_size  (BUFSZ*3+key_e_size+iv_size+keysize+MARGIN*7)
554         ixt_e=(struct ipsec_alg_enc *)ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, enc_alg);
555         if (ixt_e==NULL) {
556                 KLIPS_PRINT(1, 
557                             "klips_debug: %s: "
558                             "encalg=%d object not found\n",
559                             __FUNCTION__, enc_alg);
560                 ret=-EINVAL;
561                 goto out;
562         }
563         iv_size=ixt_e->ixt_blocksize;
564         key_e_size=ixt_e->ixt_e_ctx_size;
565         keysize=ixt_e->ixt_e_keylen;
566         KLIPS_PRINT(1, 
567                     "klips_debug: %s: "
568                     "enc_alg=%d blocksize=%d key_e_size=%d keysize=%d\n",
569                     __FUNCTION__, enc_alg, iv_size, key_e_size, keysize);
570         if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
571                 ret= -ENOMEM;
572                 goto out;
573         }
574         get_random_bytes(test_key, keysize);
575         get_random_bytes(test_iv, iv_size);
576         ixt_e->ixt_e_set_key(test_key_e, test_key, keysize);
577         get_random_bytes(test_enc, BUFSZ);
578         memcpy(test_tmp, test_enc, BUFSZ);
579         ret=ixt_e->ixt_e_cbc_encrypt(test_key_e, test_enc, test_enc, BUFSZ, test_iv, 1);
580         printk(KERN_INFO
581                     "klips_info: %s: "
582                     "cbc_encrypt=1 ret=%d\n", 
583                         __FUNCTION__, ret);
584         ret=memcmp(test_enc, test_tmp, BUFSZ);
585         printk(KERN_INFO
586                     "klips_info: %s: "
587                     "memcmp(enc, tmp) ret=%d: %s\n", ret,
588                         __FUNCTION__,
589                         ret!=0? "OK. (encr->DIFFers)" : "FAIL! (encr->SAME)" );
590         memcpy(test_dec, test_enc, BUFSZ);
591         ret=ixt_e->ixt_e_cbc_encrypt(test_key_e, test_dec, test_dec, BUFSZ, test_iv, 0);
592         printk(KERN_INFO
593                     "klips_info: %s : "
594                     "cbc_encrypt=0 ret=%d\n", __FUNCTION__, ret);
595         ret=memcmp(test_dec, test_tmp, BUFSZ);
596         printk(KERN_INFO
597                     "klips_info: %s : "
598                     "memcmp(dec,tmp) ret=%d: %s\n", __FUNCTION__, ret,
599                         ret==0? "OK. (encr->decr->SAME)" : "FAIL! (encr->decr->DIFFers)" );
600         {
601                 /*      Shamelessly taken from drivers/md sources  O:)  */
602                 unsigned long now;
603                 int i, count, max=0;
604                 int encrypt, speed;
605                 for (encrypt=0; encrypt <2;encrypt ++) {
606                         for (i = 0; i < 5; i++) {
607                                 now = jiffies;
608                                 count = 0;
609                                 while (jiffies == now) {
610                                         mb();
611                                         ixt_e->ixt_e_cbc_encrypt(test_key_e, test_tmp, test_tmp, BUFSZ, test_iv, encrypt);
612                                         mb();
613                                         count++;
614                                         mb();
615                                 }
616                                 if (count > max)
617                                         max = count;
618                         }
619                         speed = max * (HZ * BUFSZ / 1024);
620                         printk(KERN_INFO
621                                     "klips_info: %s: "
622                                     "%s %s speed=%d KB/s\n", 
623                                     __FUNCTION__, ixt_e->ixt_name,
624                                     encrypt? "encrypt": "decrypt", speed);
625                 }
626         }
627         kfree(buf);
628         ipsec_alg_put((struct ipsec_alg *)ixt_e);
629 out:
630         return ret;
631         #undef test_enc  
632         #undef test_dec  
633         #undef test_tmp  
634         #undef test_key_e
635         #undef test_iv   
636         #undef test_key  
637         #undef test_size 
638 }
639 /*
640  *      Must be called from user context
641  *      used at module load type for testing algo implementation
642  */
643 static int ipsec_alg_test_auth(int auth_alg, int test) {
644         int ret;
645         caddr_t buf;
646         int blocksize, keysize, key_a_size;
647         struct ipsec_alg_auth *ixt_a;
648         #define BUFSZ   1024
649         #define MARGIN  0
650         #define test_auth  (buf+MARGIN)
651         #define test_key_a (test_auth+BUFSZ+MARGIN)
652         #define test_key   (test_key_a+key_a_size+MARGIN)
653         #define test_hash  (test_key+keysize+MARGIN)
654         #define test_size  (BUFSZ+key_a_size+keysize+AHHMAC_HASHLEN+MARGIN*4)
655         ixt_a=(struct ipsec_alg_auth *)ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, auth_alg);
656         if (ixt_a==NULL) {
657                 KLIPS_PRINT(1, 
658                             "klips_debug: %s: "
659                             "encalg=%d object not found\n",
660                             __FUNCTION__, auth_alg);
661                 ret=-EINVAL;
662                 goto out;
663         }
664         blocksize=ixt_a->ixt_blocksize;
665         key_a_size=ixt_a->ixt_a_ctx_size;
666         keysize=ixt_a->ixt_a_keylen;
667         KLIPS_PRINT(1, 
668                     "klips_debug: %s : "
669                     "auth_alg=%d blocksize=%d key_a_size=%d keysize=%d\n",
670                     __FUNCTION__, auth_alg, blocksize, key_a_size, keysize);
671         if ((buf=kmalloc (test_size, GFP_KERNEL)) == NULL) {
672                 ret= -ENOMEM;
673                 goto out;
674         }
675         get_random_bytes(test_key, keysize);
676         ixt_a->ixt_a_hmac_set_key(test_key_a, test_key, keysize);
677         get_random_bytes(test_auth, BUFSZ);
678         ret=ixt_a->ixt_a_hmac_hash(test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
679         printk(KERN_INFO
680                     "klips_info: %s: "
681                     "ret=%d\n", __FUNCTION__, ret);
682         {
683                 /*      Shamelessly taken from drivers/md sources  O:)  */
684                 unsigned long now;
685                 int i, count, max=0;
686                 int speed;
687                 for (i = 0; i < 5; i++) {
688                         now = jiffies;
689                         count = 0;
690                         while (jiffies == now) {
691                                 mb();
692                                 ixt_a->ixt_a_hmac_hash(test_key_a, test_auth, BUFSZ, test_hash, AHHMAC_HASHLEN);
693                                 mb();
694                                 count++;
695                                 mb();
696                         }
697                         if (count > max)
698                                 max = count;
699                 }
700                 speed = max * (HZ * BUFSZ / 1024);
701                 printk(KERN_INFO
702                                 "klips_info: %s: "
703                                 "%s hash speed=%d KB/s\n", 
704                                 __FUNCTION__, ixt_a->ixt_name,
705                                 speed);
706         }
707         kfree(buf);
708         ipsec_alg_put((struct ipsec_alg *)ixt_a);
709 out:
710         return ret;
711         #undef test_auth 
712         #undef test_key_a
713         #undef test_key  
714         #undef test_hash 
715         #undef test_size 
716 }
717 int ipsec_alg_test(unsigned alg_type, unsigned alg_id, int test) {
718         switch(alg_type) {
719                 case IPSEC_ALG_TYPE_ENCRYPT:
720                         return ipsec_alg_test_encrypt(alg_id, test);
721                         break;
722                 case IPSEC_ALG_TYPE_AUTH:
723                         return ipsec_alg_test_auth(alg_id, test);
724                         break;
725         }
726         printk(KERN_ERR "klips_info: ipsec_alg_test() called incorrectly: "
727                         "alg_type=%d alg_id=%d\n",
728                         alg_type, alg_id);
729         return -EINVAL;
730 }
731 int ipsec_alg_init(void) {
732         KLIPS_PRINT(1, "klips_info:ipsec_alg_init: "
733                         "KLIPS alg v=%d.%d.%d-%d (EALG_MAX=%d, AALG_MAX=%d)\n",
734                         IPSEC_ALG_VERSION_QUAD(IPSEC_ALG_VERSION),
735                         SADB_EALG_MAX, SADB_AALG_MAX);
736         /*      Initialize tables */
737         write_lock_bh(&ipsec_alg_lock);
738         ipsec_alg_hash_init();
739         write_unlock_bh(&ipsec_alg_lock);
740         /*      Initialize static algos         */
741         KLIPS_PRINT(1, "klips_info:ipsec_alg_init: "
742                 "calling ipsec_alg_static_init()\n");
743         ipsec_alg_static_init();
744         return 0;
745 }
746
747 /**********************************************
748  *
749  *      INTERFACE for ipsec_sa init and wipe
750  *
751  **********************************************/
752
753 /*      
754  *      Called from pluto -> pfkey_v2_parser.c:pfkey_ipsec_sa_init()    
755  */
756 int ipsec_alg_sa_init(struct ipsec_sa *sa_p) {
757         struct ipsec_alg_enc *ixt_e;
758         struct ipsec_alg_auth *ixt_a;
759
760         /*      Only ESP for now ... */
761         if (sa_p->ips_said.proto != IPPROTO_ESP)
762                 return -EPROTONOSUPPORT;
763         KLIPS_PRINT(debug_pfkey, "klips_debug:  %s() :"
764                         "entering for encalg=%d, authalg=%d\n",
765                             __FUNCTION__, sa_p->ips_encalg, sa_p->ips_authalg);
766         if ((ixt_e=(struct ipsec_alg_enc *)
767                 ipsec_alg_get(IPSEC_ALG_TYPE_ENCRYPT, sa_p->ips_encalg))) {
768                 KLIPS_PRINT(debug_pfkey,
769                     "klips_debug:  %s() :"
770                     "found ipsec_alg (ixt_e=%p) for encalg=%d\n",
771                     __FUNCTION__, ixt_e, sa_p->ips_encalg);
772                 sa_p->ips_alg_enc=ixt_e;
773         }
774         if ((ixt_a=(struct ipsec_alg_auth *)
775                 ipsec_alg_get(IPSEC_ALG_TYPE_AUTH, sa_p->ips_authalg))) {
776                 KLIPS_PRINT(debug_pfkey,
777                     "klips_debug:  %s() :"
778                     "found ipsec_alg (ixt_a=%p) for auth=%d\n",
779                     __FUNCTION__, ixt_a, sa_p->ips_authalg);
780                 sa_p->ips_alg_auth=ixt_a;
781         }
782         return 0;
783 }
784
785 /*      
786  *      Called from pluto -> ipsec_sa.c:ipsec_sa_delchain()
787  */
788 int ipsec_alg_sa_wipe(struct ipsec_sa *sa_p) {
789         struct ipsec_alg *ixt;
790         if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_enc)) {
791                 KLIPS_PRINT(debug_pfkey, "klips_debug:  %s() :"
792                                 "unlinking for encalg=%d\n",
793                                 __FUNCTION__, ixt->ixt_alg_id);
794                 ipsec_alg_put(ixt);
795         }
796         if ((ixt=(struct ipsec_alg *)sa_p->ips_alg_auth)) {
797                 KLIPS_PRINT(debug_pfkey, "klips_debug: %s() :"
798                                 "unlinking for authalg=%d\n",
799                                 __FUNCTION__, ixt->ixt_alg_id);
800                 ipsec_alg_put(ixt);
801         }
802         return 0;
803 }
804 /*
805  *      As the author of this module, I ONLY ALLOW using it from
806  *      GPL (or same LICENSE TERMS as kernel source) modules.
807  *
808  *      In respect to hardware crypto engines this means:
809  *      * Closed-source device drivers ARE NOT ALLOWED to use 
810  *        this interface.
811  *      * Closed-source VHDL/Verilog firmware running on 
812  *        the crypto hardware device IS ALLOWED to use this interface
813  *        via a GPL (or same LICENSE TERMS as kernel source) device driver.
814  *      --Juan Jose Ciarlante 20/03/2002 (thanks RGB for the correct wording)
815  */
816
817 /*      
818  *      These symbols can only be used from GPL modules 
819  *      for now, I'm disabling this because it creates false
820  *      symbol problems for old modutils.
821  */
822
823 /* #ifndef EXPORT_SYMBOL_GPL */
824 #undef EXPORT_SYMBOL_GPL
825 #define EXPORT_SYMBOL_GPL EXPORT_SYMBOL
826 /* #endif */
827 EXPORT_SYMBOL_GPL(register_ipsec_alg);
828 EXPORT_SYMBOL_GPL(unregister_ipsec_alg);
829 EXPORT_SYMBOL_GPL(ipsec_alg_test);