OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / klips / net / ipsec_xscale / ipsec_glue.c
1 /*
2  * IPSEC_GLUE interface code.
3  * Copyright 2002 Intel Corporation All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  */
15
16
17 /* To do: Note to myself try to compile these file first see to see if it's work */
18
19 char ipsec_sa_glue_c_version[] = "RCSID $Id: ipsec_glue.c,v 1.1 2004/05/11 00:38:42 danield Exp $";
20
21 #include <linux/config.h>
22 #include <linux/version.h>
23 #include <linux/module.h>
24 #include <linux/kernel.h> /* printk() */
25 #include <linux/spinlock.h>
26
27 #include "ipsec_param.h"
28
29 #ifdef MALLOC_SLAB
30 # include <linux/slab.h> /* kmalloc() */
31 #else /* MALLOC_SLAB */
32 # include <linux/malloc.h> /* kmalloc() */
33 #endif /* MALLOC_SLAB */
34 #include <linux/errno.h>  /* error codes */
35 #include <linux/types.h>  /* size_t */
36 #include <linux/interrupt.h> /* mark_bh */
37
38 #include <linux/netdevice.h>   /* struct device, and other headers */
39 #include <linux/etherdevice.h> /* eth_type_trans */
40 #include <linux/ip.h>          /* struct iphdr */
41 #include <linux/in.h>          /* struct sockaddr_in */
42 #include <linux/skbuff.h>
43
44 #ifdef NET_21
45 # include <asm/uaccess.h>
46 # include <linux/in6.h>
47 #endif /* NET_21 */
48
49 #include <asm/checksum.h>
50 #include <net/ip.h>
51
52 #include "ipsec_glue_mbuf.h"    /* The interface to glue mbuf                           */
53 #include "ipsec_glue.h"         /* The interface to glue sa                             */
54 #include "ipsec_glue_desc.h"    /* The interface to glue desc                           */
55
56 #include <freeswan.h>
57 #include "ipsec_netlink.h"
58 #include "ipsec_xform.h"        /* The interface to ipsec transform                     */
59 #include "ipsec_ah.h"
60 #include "ipsec_esp.h"
61 #include "ipsec_sa.h"
62 #include <pfkeyv2.h>
63 #include <pfkey.h>
64
65 #define AES_KEY_E_OFFSET_IN_TDB     8
66
67 extern spinlock_t tdb_lock;
68
69 extern int debug_xform;
70         
71 /* Perform the encrytion for hardware accelaration funtion */
72 extern void ipsec_tunnel_start_xmit_cb( UINT32, IX_MBUF *, IX_MBUF *, IxCryptoAccStatus);
73
74 /* Perform the dencrytion for hardware accelaration funtion */
75 extern void ipsec_rcv_cb( UINT32, IX_MBUF *, IX_MBUF *, IxCryptoAccStatus);
76
77 /* Callback funtion for crypto context registration */
78 static IxCryptoAccPerformCompleteCallback PerformCallbk = NULL; 
79
80 /* Forward declaration of the show funtion */
81 #ifdef SA_GLUE_DEBUG
82   void print_show_algo(void);
83 #endif /* SA_GLUE_DEBUG */
84
85 /* Crypto context       */
86 IxCryptoAccCtx cryptoAccCtx;
87
88 /* To do need to allocate this mbuf */
89 IX_MBUF *callbackmbuf = NULL;
90 IX_MBUF *pMbufPrimaryChainVar = NULL;
91 IX_MBUF *pMbufSecondaryChainVar = NULL;
92
93
94 void ipsec_glue_crypto_ctx_init(void)
95 {
96     cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_TYPE_OF_OPERATION;
97     cryptoAccCtx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_NULL;
98     cryptoAccCtx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_NULL ;
99     cryptoAccCtx.cipherCtx.cipherKeyLen = 0;
100     cryptoAccCtx.cipherCtx.cipherBlockLen = 0;
101     cryptoAccCtx.cipherCtx.cipherInitialVectorLen = 0;
102     cryptoAccCtx.authCtx.authAlgo =IX_CRYPTO_ACC_AUTH_NULL;
103     cryptoAccCtx.authCtx.authDigestLen = 0;
104     cryptoAccCtx.authCtx.authKeyLen = 0;
105     cryptoAccCtx.authCtx.key.authKey[0] =  0;
106     cryptoAccCtx.useDifferentSrcAndDestMbufs = FALSE;
107 }
108
109 void ipsec_glue_update_state(struct ipsec_sa *ips,
110                              IxCryptoAccStatus state)
111 {
112     if (state == IX_SUCCESS)
113     {
114         KLIPS_PRINT(debug_xform,
115                     "klips_glue:update_state: "
116                     "Changing State to Mature.!");
117         /* update tdb to MATURE state */
118         ips->ips_state = SADB_SASTATE_MATURE;
119     }
120     else if (state ==IX_CRYPTO_ACC_STATUS_WAIT)
121     {
122             KLIPS_PRINT(debug_xform,
123                     "klips_glue:update_state: "
124                     "Registration not complete yet; wait for next completion indication.!");
125             /* update tdb to LARVA state */
126         ips->ips_state = SADB_SASTATE_LARVAL;
127     }
128     else if (state == IX_FAIL)
129     {
130         KLIPS_PRINT(debug_xform,
131             "klips_glue:update_state: "
132             "Changing State to Dead.!");
133         /* update tdb to DEAD state */
134         ips->ips_state = SADB_SASTATE_DEAD;
135     }
136     else
137     {
138             KLIPS_PRINT(debug_xform,
139                     "klips_glue:update_state: "
140                     "Error in status message.!");
141         /* update tdb to DEAD state */
142         ips->ips_state = SADB_SASTATE_DEAD;
143     }
144 }
145
146 UINT32 ipsec_glue_create_cipher(struct ipsec_sa *ips)
147 {
148     UINT32 status = IPSEC_GLUE_STATUS_SUCCESS;
149
150     switch(ips->ips_encalg)
151     {
152 #ifdef CONFIG_IPSEC_ENC_DES
153         case ESP_DES:
154             /* The cipher algorith, DES */
155             cryptoAccCtx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_DES;
156
157             /* The cipher key length                    */
158             /* check the cipher length, 3DES = 24 bytes */
159             if (EMT_ESPDES_KEY_SZ == (DIVUP(ips->ips_key_bits_e, IPSEC_GLUE_BITS)))
160             {
161             cryptoAccCtx.cipherCtx.cipherKeyLen = IX_CRYPTO_ACC_DES_KEY_64;
162             }
163             else
164             {
165             status = IPSEC_GLUE_STATUS_FAIL;
166             KLIPS_PRINT(debug_xform,
167                     "klips_error:ipsec_glue_create_cipher: "
168                     "Invalid DES length!\n");
169             break;
170             }
171
172             /* The cipher key  */
173             memcpy (cryptoAccCtx.cipherCtx.key.cipherKey, (UINT8 *)(ips->ips_key_e),
174                     cryptoAccCtx.cipherCtx.cipherKeyLen);
175
176             /* The cipher block length */
177             cryptoAccCtx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
178
179         /* The cipher IV length */
180         if (EMT_ESPDES_IV_SZ == (DIVUP(ips->ips_iv_bits, IPSEC_GLUE_BITS)))
181         {
182             cryptoAccCtx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_DES_IV_64;
183         }
184         else
185         {
186             status = IPSEC_GLUE_STATUS_FAIL;
187             KLIPS_PRINT(debug_xform,
188                 "klips_error:ipsec_glue_create_cipher: "
189                 "Invalid IV length!\n");
190         }
191
192             break;
193 #endif /* CONFIG_IPSEC_ENC_DES */
194     
195 #ifdef CONFIG_IPSEC_ENC_3DES
196         case ESP_3DES:
197             /* The cipher algorith, 3DES */
198             cryptoAccCtx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_3DES;
199
200             /* The cipher key length                    */
201             /* check the cipher length, 3DES = 24 bytes */
202             if (EMT_ESP3DES_KEY_SZ == (DIVUP(ips->ips_key_bits_e, IPSEC_GLUE_BITS)))
203             {
204             cryptoAccCtx.cipherCtx.cipherKeyLen = IX_CRYPTO_ACC_3DES_KEY_192;
205             }
206             else
207             {
208             status = IPSEC_GLUE_STATUS_FAIL;
209             KLIPS_PRINT(debug_xform,
210                     "klips_error:ipsec_glue_create_cipher: "
211                     "Invalid 3DES length!\n");
212             break;
213             }
214
215             /* The cipher key  */
216             memcpy (cryptoAccCtx.cipherCtx.key.cipherKey, (UINT8 *)(ips->ips_key_e),
217                     cryptoAccCtx.cipherCtx.cipherKeyLen);
218
219             /* The cipher block length */
220             cryptoAccCtx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_DES_BLOCK_64;
221
222         /* The cipher IV length */
223         if (EMT_ESPDES_IV_SZ == (DIVUP(ips->ips_iv_bits, IPSEC_GLUE_BITS)))
224         {
225             cryptoAccCtx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_DES_IV_64;
226         }
227         else
228         {
229             status = IPSEC_GLUE_STATUS_FAIL;
230             KLIPS_PRINT(debug_xform,
231                 "klips_error:ipsec_glue_create_cipher: "
232                 "Invalid IV length!\n");
233         }
234
235             break;
236 #endif /* CONFIG_IPSEC_ENC_3DES */
237
238
239 #ifdef CONFIG_IPSEC_ALG
240         case ESP_AES:
241             /* The cipher algorith, AES */
242             cryptoAccCtx.cipherCtx.cipherAlgo = IX_CRYPTO_ACC_CIPHER_AES;
243
244             /* The cipher key length                    */
245             switch (DIVUP(ips->ips_key_bits_e, IPSEC_GLUE_BITS))
246             {
247                 case EMT_ESPAES128_KEY_SZ :
248                     cryptoAccCtx.cipherCtx.cipherKeyLen = IX_CRYPTO_ACC_AES_KEY_128;
249                     break;
250
251                 case EMT_ESPAES192_KEY_SZ :
252                     cryptoAccCtx.cipherCtx.cipherKeyLen = IX_CRYPTO_ACC_AES_KEY_192;
253                     break;
254
255                 case EMT_ESPAES256_KEY_SZ :
256                     cryptoAccCtx.cipherCtx.cipherKeyLen = IX_CRYPTO_ACC_AES_KEY_256;
257                     break;
258
259                 default :
260                     status = IPSEC_GLUE_STATUS_FAIL;
261                     KLIPS_PRINT(debug_xform,
262                         "klips_error:ipsec_glue_create_cipher: "
263                         "Invalid AES key length!\n");
264                     break;
265             }
266             /* The cipher key  */
267             memcpy (cryptoAccCtx.cipherCtx.key.cipherKey,
268                 (UINT8 *)((ips->ips_key_e) + AES_KEY_E_OFFSET_IN_TDB),
269                 cryptoAccCtx.cipherCtx.cipherKeyLen);
270
271             /* The cipher block length */
272             cryptoAccCtx.cipherCtx.cipherBlockLen = IX_CRYPTO_ACC_AES_BLOCK_128;
273
274             /* The cipher IV length */
275             if (EMT_ESPAES_CBC_IV_SZ == (DIVUP(ips->ips_iv_bits, IPSEC_GLUE_BITS)))
276             {
277                 cryptoAccCtx.cipherCtx.cipherInitialVectorLen = IX_CRYPTO_ACC_AES_CBC_IV_128;
278             }
279             else
280             {
281                 status = IPSEC_GLUE_STATUS_FAIL;
282                 KLIPS_PRINT(debug_xform,
283                     "klips_error:ipsec_glue_create_cipher: "
284                     "Invalid IV length!\n");
285                 break;
286             }
287
288             break;
289 #endif /* CONFIG_IPSEC_ALG */
290
291         default:
292             /* Encryption not supported */
293             status = IPSEC_GLUE_STATUS_FAIL;
294             KLIPS_PRINT(debug_xform,
295                         "klips_error:ipsec_glue_create_cipher: "
296                         "Encap. Algorithm not supported!\n");
297             return status;
298     }
299
300
301     /* The cipher mode, supported cipher mode: CBC      */
302     cryptoAccCtx.cipherCtx.cipherMode = IX_CRYPTO_ACC_MODE_CBC;
303
304   
305     
306
307     return status;
308 }
309
310
311 UINT32 ipsec_glue_create_auth(struct ipsec_sa *ips)
312 {
313     UINT32 status = IPSEC_GLUE_STATUS_SUCCESS;
314
315     switch(ips->ips_authalg) {
316 #ifdef CONFIG_IPSEC_AUTH_HMAC_MD5
317         case AH_MD5:
318             /* Tne the authentication algorithm - MD5*/
319             cryptoAccCtx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_MD5;
320
321             /* The digest length, in bytes */
322             cryptoAccCtx.authCtx.authDigestLen = AHHMAC_HASHLEN;
323
324             /* The authentication key length */
325             if (AHMD596_KLEN == (DIVUP(ips->ips_key_bits_a, IPSEC_GLUE_BITS)))
326             {
327                     cryptoAccCtx.authCtx.authKeyLen = IX_CRYPTO_ACC_MD5_KEY_128;
328             }
329             else
330             {
331             status = IPSEC_GLUE_STATUS_FAIL;
332             KLIPS_PRINT(debug_xform,
333                             "klips_error:glue_create_auth: "
334                             "Invalid MD5 length!\n");
335                     break;
336             }
337
338             /* The authentication key */
339             memcpy(cryptoAccCtx.authCtx.key.authKey, (UINT8 *)(ips->ips_key_a),
340                     cryptoAccCtx.authCtx.authKeyLen);
341             break;
342 #endif /* CONFIG_IPSEC_AUTH_HMAC_MD5 */
343
344 #ifdef CONFIG_IPSEC_AUTH_HMAC_SHA1
345         case AH_SHA:
346             cryptoAccCtx.authCtx.authAlgo = IX_CRYPTO_ACC_AUTH_SHA1;
347
348             /* The digest length, in bytes */
349             cryptoAccCtx.authCtx.authDigestLen = AHHMAC_HASHLEN;
350
351             /* The authentication key length */
352             if (AHSHA196_KLEN == (DIVUP(ips->ips_key_bits_a, IPSEC_GLUE_BITS)))
353             {
354                 cryptoAccCtx.authCtx.authKeyLen = IX_CRYPTO_ACC_SHA1_KEY_160;
355             }
356             else
357             {
358                 status = IPSEC_GLUE_STATUS_FAIL;
359                     KLIPS_PRINT(debug_xform,
360                             "klips_error:glue_create_auth: "
361                             "Invalid SHA1 length!\n");
362                     break;
363             }
364
365             /* The authentication key, SHA1 */
366             memcpy(cryptoAccCtx.authCtx.key.authKey, (UINT8 *)(ips->ips_key_a),
367                     cryptoAccCtx.authCtx.authKeyLen);
368
369             break;
370 #endif /* CONFIG_IPSEC_AUTH_HMAC_SHA1 */
371
372         case AH_NONE:
373             break;
374
375         default:
376             /* Authentication algo. not supported */
377             status = IPSEC_GLUE_STATUS_FAIL;
378             KLIPS_PRINT(debug_xform,
379                         "klips_error:ipsec_glue_create_auth: "
380                         "Authen. Algorithm not supported!\n");
381     }
382     return status;
383 }
384
385
386 UINT32 ipsec_compose_context(struct ipsec_sa *ips)
387 {
388     UINT32 status = IPSEC_GLUE_STATUS_SUCCESS;
389
390     /*
391        Temporary structure to store the crypto context. Hardware
392        accelarator will copy the data into its own structure
393     */
394     ipsec_glue_crypto_ctx_init();
395
396     switch(ips->ips_said.proto)
397     {
398             case IPPROTO_AH:
399             /* fill only in cryto authentication context */
400             if (IPSEC_GLUE_STATUS_FAIL == ipsec_glue_create_auth(ips))
401             {
402                 status = IPSEC_GLUE_STATUS_FAIL;
403                 KLIPS_PRINT(debug_xform,
404                     "klips_error:glue_compose_context: "
405                     "Encapsulation Algo error!\n");
406                         return (IPSEC_GLUE_STATUS_FAIL);
407                 }
408             /* Determine the direction of the transformation */
409             if (ips->ips_flags & EMT_INBOUND)
410             {   /* Incoming direction */
411                         cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_AUTH_CHECK;
412                         PerformCallbk = &ipsec_rcv_cb;
413                 }
414                 else
415                 {       /* Outgoing direction */
416                cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_AUTH_CALC;
417                 PerformCallbk = &ipsec_tunnel_start_xmit_cb;
418             }
419                 break;
420
421             case IPPROTO_ESP:
422                 if (IPSEC_GLUE_STATUS_FAIL == ipsec_glue_create_cipher(ips))
423                 {
424                 status = IPSEC_GLUE_STATUS_FAIL;
425                         KLIPS_PRINT(debug_xform,
426                     "klips_error:glue_compose_context: "
427                     "Encapsulation Algo error!\n");
428                         return (IPSEC_GLUE_STATUS_FAIL);
429                 }
430
431             /* fill only in cryto authentication context */
432             if (IPSEC_GLUE_STATUS_FAIL == ipsec_glue_create_auth(ips))
433             {
434                 status = IPSEC_GLUE_STATUS_FAIL;
435                         KLIPS_PRINT(debug_xform,
436                             "klips_error:glue_compose_context: "
437                                 "Encapsulation Algo error!\n");
438                         return (IPSEC_GLUE_STATUS_FAIL);
439                 }
440
441                 /* Determine the direction of the transformation */
442                 if (ips->ips_flags & EMT_INBOUND)
443                 {       /* Incoming direction */
444                 if (AH_NONE == ips->ips_authalg)
445                 {
446                     cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_DECRYPT;
447                 }
448                 else
449                 {
450                     cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_AUTH_DECRYPT;
451                 }
452                 PerformCallbk = &ipsec_rcv_cb;
453                 }
454                 else
455                 {       /* Outgoing direction */
456                 if (AH_NONE == ips->ips_authalg)
457                 {
458                     cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_ENCRYPT;
459                 }
460                 else
461                 {
462                     cryptoAccCtx.operation = IX_CRYPTO_ACC_OP_ENCRYPT_AUTH;
463                 }
464                 PerformCallbk = &ipsec_tunnel_start_xmit_cb;
465             }
466             break;
467
468         /* Glue code is to create the crypto context from the freeswan security association
469                 which means it only maps the applicable freeswan SA to the crypto context. In
470                 other words IPPROTO_IPIP, IPPROTO_COMP, IPPROTO_INT, and case 0 do not relate
471                 to the IXDP425 crypto context and only applicable to IPSEC/Freeswan. */ 
472         case IPPROTO_IPIP:
473             status = IPSEC_GLUE_STATUS_NOT_SUPPORTED;
474             break;
475
476 #ifdef CONFIG_IPSEC_IPCOMP
477         case IPPROTO_COMP:
478             status = IPSEC_GLUE_STATUS_NOT_SUPPORTED;
479             break;
480 #endif /* CONFIG_IPSEC_IPCOMP */
481
482         case IPPROTO_INT:
483             status = IPSEC_GLUE_STATUS_NOT_SUPPORTED;
484             break;
485
486         case 0: /* Security association with no authentication algorithm and encryption algorithm */
487             status = IPSEC_GLUE_STATUS_NOT_SUPPORTED;
488             break;
489
490         default:
491             KLIPS_PRINT(debug_xform,
492                         "klips_error:compose_context: "
493                         "unknown proto=%d.\n",
494                         ips->ips_said.proto);
495             status = IPSEC_GLUE_STATUS_FAIL;
496             break;
497     }
498
499     /* The data is read and write to the source */
500     cryptoAccCtx.useDifferentSrcAndDestMbufs = FALSE;
501
502 #ifdef SA_GLUE_DEBUG
503     printk ("Context compose status:  %d\n", status);
504     print_show_algo();
505 #endif /* SA_GLUE_DEBUG */
506
507     return status;
508 }
509
510 #ifdef IX_OSAL_MBUF_PRIV
511 /*
512  * emulate some changes we made to older CSR libs so
513  * we don;t need to keep modding them
514  */
515
516 static struct CTXREG {
517         UINT32 cryptoCtxId;
518         struct ipsec_sa *ips;
519         struct CTXREG *next;
520 } *ipsec_ctxips_list = NULL;
521
522 static int
523 ixCryptoAccSetUserCtx(UINT32 cryptoCtxId, struct ipsec_sa *ips)
524 {
525     struct CTXREG *n = (struct CTXREG *) kmalloc(sizeof(*n), GFP_ATOMIC);
526     if (!n)
527         return IX_CRYPTO_ACC_STATUS_FAIL;
528     n->cryptoCtxId = cryptoCtxId;
529     n->ips = ips;
530     n->next = ipsec_ctxips_list;
531         ipsec_ctxips_list = n;
532     return IX_CRYPTO_ACC_STATUS_SUCCESS;
533 }
534
535 static int
536 ixCryptoAccGetUserCtx(UINT32 cryptoCtxId, struct ipsec_sa **ips)
537 {
538     struct CTXREG *p;
539
540     for (p = ipsec_ctxips_list; p; p = p->next) {
541         if (p->cryptoCtxId == cryptoCtxId) {
542             *ips = p->ips;
543             return IX_CRYPTO_ACC_STATUS_SUCCESS;
544         }
545     }
546     return IX_CRYPTO_ACC_STATUS_FAIL;
547 }
548
549 #define ixCryptoAccDelUserCtx _ixCryptoAccDelUserCtx
550 static void
551 _ixCryptoAccDelUserCtx(UINT32 cryptoCtxId)
552 {
553     struct CTXREG *p, *last = NULL;
554
555     for (p = ipsec_ctxips_list; p; last = p, p = p->next) {
556         if (p->cryptoCtxId == cryptoCtxId) {
557             if (last)
558                 last->next = p->next;
559             else
560                 ipsec_ctxips_list = p->next;
561             kfree(p);
562                 break;
563         }
564     }
565 }
566
567 #endif /* IX_OSAL_MBUF_PRIV */
568
569 UINT32
570 ipsec_glue_crypto_context_put(struct ipsec_sa *ips)
571 {
572     UINT32 status = IPSEC_GLUE_STATUS_SUCCESS;
573     UINT32 ret_status;
574     IxCryptoAccStatus reg_status;
575     IxCryptoAccStatus cb_status;
576     unsigned long flags;
577     UINT32 cryptoCtxId;
578
579     pMbufPrimaryChainVar = NULL;
580     pMbufSecondaryChainVar = NULL;
581
582     /* Contruct the crypto context      */
583     ret_status = ipsec_compose_context(ips);
584
585     if (IPSEC_GLUE_STATUS_FAIL == ret_status)
586     {
587         KLIPS_PRINT(debug_xform,
588                     "klips_error:context_put: "
589                     "Composed crypto context failed \n");
590         return (IPSEC_GLUE_STATUS_FAIL);
591     }
592     else if (IPSEC_GLUE_STATUS_NOT_SUPPORTED == ret_status)
593     {
594         KLIPS_PRINT(debug_xform,
595             "klips_debug:context_put: "
596                     "Composed crypto context not supported \n");
597         
598         spin_lock_bh(&tdb_lock);
599         ips->ips_crypto_state = IPSEC_GLUE_UNSUPPORTED_CTXID;
600         spin_unlock_bh(&tdb_lock);
601
602         return status;
603      }
604
605     if (PerformCallbk == NULL)
606     {
607         KLIPS_PRINT(debug_xform,
608             "klips_error:context_put: "
609             "PerformCallbk is NULL.\n");
610         return IPSEC_GLUE_STATUS_FAIL;
611     }
612
613     /*  allocate Mbuf for crypto registration */
614     /* ESP with authentication or AH */
615     if ((IX_CRYPTO_ACC_OP_ENCRYPT != cryptoAccCtx.operation) ||
616             (IX_CRYPTO_ACC_OP_DECRYPT != cryptoAccCtx.operation))
617     {
618         if (IPSEC_GLUE_STATUS_FAIL == ipsec_glue_mbuf_get (&pMbufPrimaryChainVar))
619         {
620             KLIPS_PRINT(debug_xform,
621                 "klips_error:context_put: "
622                 "Unable to allocate MBUF.\n");
623             return (IPSEC_GLUE_STATUS_FAIL);
624         }
625
626         if (IPSEC_GLUE_STATUS_FAIL == ipsec_glue_mbuf_get (&pMbufSecondaryChainVar))
627         {
628             if (pMbufPrimaryChainVar)
629                 ipsec_glue_mbuf_rel (pMbufPrimaryChainVar);
630
631             KLIPS_PRINT(debug_xform,
632                 "klips_error:context_put: "
633                 "Unable to allocate MBUF.\n");
634             return (IPSEC_GLUE_STATUS_FAIL);
635         }
636     }
637
638
639     /*  The tdb table better *NOT* be locked before it is handed in,
640         or SMP locks will happen */
641     spin_lock_bh(&tdb_lock);
642     ips->ips_state = SADB_SASTATE_LARVAL;
643     spin_unlock_bh(&tdb_lock);
644
645     /* Register crypto context  */
646     spin_lock_irqsave(&tdb_lock, flags);
647     reg_status = ixCryptoAccCtxRegister (&cryptoAccCtx,
648                     pMbufPrimaryChainVar,
649                     pMbufSecondaryChainVar,
650                     register_crypto_cb,
651                     PerformCallbk,
652                     &cryptoCtxId);
653
654     if (IX_CRYPTO_ACC_STATUS_SUCCESS == reg_status)
655     {
656         ixCryptoAccSetUserCtx(cryptoCtxId, ips);
657         ips->ips_crypto_state = IPSEC_GLUE_VALID_CTXID;
658         ips->ips_crypto_context_id = cryptoCtxId;
659         spin_unlock_irqrestore(&tdb_lock, flags);
660     }
661     else
662     {
663         spin_unlock_irqrestore(&tdb_lock, flags);
664         spin_lock_bh(&tdb_lock);
665         ips->ips_state = SADB_SASTATE_DEAD;
666         spin_unlock_bh(&tdb_lock);
667
668         if (pMbufPrimaryChainVar)
669             ipsec_glue_mbuf_rel (pMbufPrimaryChainVar);
670         if (pMbufSecondaryChainVar)
671             ipsec_glue_mbuf_rel (pMbufSecondaryChainVar);
672
673         if (IX_CRYPTO_ACC_STATUS_FAIL == reg_status)
674         {
675             KLIPS_PRINT(debug_xform,
676                 "klips_error:glue_crypto_context_put: "
677                 "Registration failed for some unspecified internal reasons!");
678         } else if (IX_CRYPTO_ACC_STATUS_EXCEED_MAX_TUNNELS == reg_status)
679                 {
680             KLIPS_PRINT(debug_xform,
681                 "klips_error:glue_crypto_context_put: "
682                 "Registration failed as we have exceeded max active tunnels");
683         } else if (IX_CRYPTO_ACC_STATUS_OPERATION_NOT_SUPPORTED == reg_status)
684                 {
685             KLIPS_PRINT(debug_xform,
686                 "klips_error:glue_crypto_context_put: "
687                 "Registration failed as the requested operation is not suppored");
688         } else {
689             KLIPS_PRINT(debug_xform,
690                 "klips_error:glue_crypto_context_put: "
691                 "Registration failed - Invalid parameters!");
692         }
693
694         status = IPSEC_GLUE_STATUS_FAIL;
695     }
696 #ifdef SA_GLUE_DEBUG
697     printk ("Context Put: Status: %d\n", status);
698         ixCryptoAccShowWithId(cryptoCtxId);
699 #endif /* SA_GLUE_DEBUG */
700     return status;
701 }
702
703 void register_crypto_cb(UINT32 cryptoCtxId,IX_MBUF *empty_mbuf, IxCryptoAccStatus state)
704 {
705     unsigned long flags;
706     struct ipsec_sa *sa;
707     IxCryptoAccStatus status;
708
709     if (empty_mbuf != NULL)
710     {
711         /* free the mbuf */
712         ipsec_glue_mbuf_rel (empty_mbuf);
713     }
714
715     /* prints the returned pointer to cryptoCtxId*/
716     KLIPS_PRINT(debug_xform,
717                 "klips_glue:crypto_cb: "
718                 "cryptoCtxId is %d\n",
719                 cryptoCtxId);
720
721         spin_lock_irqsave(&tdb_lock, flags);
722     status = ixCryptoAccGetUserCtx(cryptoCtxId, (void **)&sa);
723     if (IX_CRYPTO_ACC_STATUS_SUCCESS == status)
724                 ipsec_glue_update_state(sa, state);
725         spin_unlock_irqrestore(&tdb_lock, flags);
726 }
727
728
729 UINT32
730 ipsec_glue_crypto_context_del (UINT32 crypto_context_id)
731 {
732     UINT32 status = IPSEC_GLUE_STATUS_SUCCESS;
733     IxCryptoAccStatus unregister_status;
734     UINT32 tries = 0;
735
736 #ifdef ixCryptoAccDelUserCtx
737 {
738         unsigned long flags;
739         spin_lock_irqsave(&tdb_lock, flags);
740     ixCryptoAccDelUserCtx(crypto_context_id);
741         spin_unlock_irqrestore(&tdb_lock, flags);
742 }
743 #endif
744
745     do
746     {
747         unregister_status = ixCryptoAccCtxUnregister (crypto_context_id);
748         if(100 == tries++)
749         {
750                 printk("ERROR: Crypto unregistration failure\n");
751                 break;
752         }
753     } while (IX_CRYPTO_ACC_STATUS_RETRY == unregister_status);
754
755     if (IX_CRYPTO_ACC_STATUS_SUCCESS == unregister_status)
756     {
757     }
758     else
759     {
760         if (IX_CRYPTO_ACC_STATUS_FAIL == unregister_status)
761         {
762             KLIPS_PRINT(debug_xform,
763                 "klips_error:glue_crypto_context_del: "
764                 "Cannot unregister crypto context!");
765         }
766         else if (IX_CRYPTO_ACC_STATUS_CRYPTO_CTX_NOT_VALID == unregister_status)
767             {   KLIPS_PRINT(debug_xform,
768                             "klips_error:glue_crypto_context_del: "
769                             "invalid cryptoCtxId.!\n");
770             }
771             else
772             {
773                 KLIPS_PRINT(debug_xform,
774                             "klips_error:glue_crypto_context_del: "
775                             "retry the unregister operation.!");
776             }
777
778             status = IPSEC_GLUE_STATUS_FAIL;
779     }
780
781 #ifdef SA_GLUE_DEBUG
782         printk ("Context Del: Status: %d\n", status);
783         ixCryptoAccShowWithId(crypto_context_id);
784 #endif /* SA_GLUE_DEBUG */
785     return status;
786 }
787
788 #ifdef SA_GLUE_DEBUG
789 void print_show_algo()
790 {
791     printk("Cipher Operation : %d\n", cryptoAccCtx.operation);
792     printk("Cipher Algo: %d\n", cryptoAccCtx.cipherCtx.cipherAlgo);
793     printk("Cipher Mode: %d\n", cryptoAccCtx.cipherCtx.cipherMode);
794     printk("Cipher Key Length: %d\n", cryptoAccCtx.cipherCtx.cipherKeyLen);
795     printk("Cipher key : 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.cipherCtx.key.desKey)) + 0)));
796     printk("Cipher key : 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.cipherCtx.key.desKey)) + 1))); 
797     printk("Cipher key : 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.cipherCtx.key.desKey)) + 2))); 
798     printk("Cipher key : 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.cipherCtx.key.desKey)) + 3))); 
799     printk("Cipher key : 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.cipherCtx.key.desKey)) + 4))); 
800     printk("Cipher key : 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.cipherCtx.key.desKey)) + 5))); 
801     printk("Cipher Block Len: %d\n", cryptoAccCtx.cipherCtx.cipherBlockLen);
802     printk("Cipher IV Length: %d\n", cryptoAccCtx.cipherCtx.cipherInitialVectorLen);
803
804      
805     printk("Auth Algo: %d\n", cryptoAccCtx.authCtx.authAlgo);
806     printk("Auth Digetst Len: %d\n", cryptoAccCtx.authCtx.authDigestLen);
807     printk("Auth key Len: %d\n", cryptoAccCtx.authCtx.authKeyLen);
808     printk("Auth Key: 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.authCtx.key.authKey)) + 0)));
809     printk("Auth Key: 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.authCtx.key.authKey)) + 1)));
810     printk("Auth Key: 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.authCtx.key.authKey)) + 2)));
811     printk("Auth Key: 0x%x\n", (*(((UINT32 *)(cryptoAccCtx.authCtx.key.authKey)) + 3)));
812 }
813 #endif /* SA_GLUE_DEBUG */ 
814
815 void addRcvDesc_to_salist(struct ipsec_sa *tdbp, IpsecRcvDesc *pRcvDesc) {
816         if (tdbp->RcvDesc_head == NULL) {
817                 tdbp->RcvDesc_head = pRcvDesc;
818         } else {
819                 if (tdbp->RcvDesc_tail != NULL)
820                         tdbp->RcvDesc_tail->RcvDesc_next = pRcvDesc;
821         }
822         tdbp->RcvDesc_tail = pRcvDesc;
823         pRcvDesc->RcvDesc_next = NULL;
824 }
825
826 void delRcvDesc_from_salist(struct ipsec_sa *tdbp, IpsecRcvDesc *pRcvDesc) {
827         struct _IpsecRcvDesc *p = NULL;
828         struct _IpsecRcvDesc *q = NULL;
829
830         for (p = tdbp->RcvDesc_head; p != NULL; p = p->RcvDesc_next) {
831                 if (p == pRcvDesc) {
832                         if (p == tdbp->RcvDesc_head) {
833                                 /* pRcvDesc is at the head of the list */
834                                 tdbp->RcvDesc_head = p->RcvDesc_next;
835                                 if (p == tdbp->RcvDesc_tail) {
836                                         tdbp->RcvDesc_tail = NULL;
837                                 }
838                         } else {
839                                 q->RcvDesc_next = p->RcvDesc_next;
840                                 if (p == tdbp->RcvDesc_tail) {
841                                         tdbp->RcvDesc_tail = q;
842                                 }
843                         }
844                         p->RcvDesc_next = NULL;
845                         break;
846                 }
847                 q = p;
848         }
849 }
850
851 void addXmitDesc_to_salist(struct ipsec_sa *tdbp, IpsecXmitDesc *pXmitDesc) {
852         if (tdbp->XmitDesc_head == NULL) {
853                 tdbp->XmitDesc_head = pXmitDesc;
854         } else {
855                 if (tdbp->XmitDesc_tail != NULL)
856                         tdbp->XmitDesc_tail->XmitDesc_next = pXmitDesc;
857         }
858         tdbp->XmitDesc_tail = pXmitDesc;
859         pXmitDesc->XmitDesc_next = NULL;
860 }
861
862 void delXmitDesc_from_salist(struct ipsec_sa *tdbp, IpsecXmitDesc *pXmitDesc) {
863         struct _IpsecXmitDesc *p = NULL;
864         struct _IpsecXmitDesc *q = NULL;
865
866         for (p = tdbp->XmitDesc_head; p != NULL; p = p->XmitDesc_next) {
867                 if (p == pXmitDesc) {
868                         if (p == tdbp->XmitDesc_head) {
869                                 /* pRcvDesc is at the head of the list */
870                                 tdbp->XmitDesc_head = p->XmitDesc_next;
871                                 if (p == tdbp->XmitDesc_tail) {
872                                         tdbp->XmitDesc_tail = NULL;
873                                 }
874                         } else {
875                                 q->XmitDesc_next = p->XmitDesc_next;
876                                 if (p == tdbp->XmitDesc_tail) {
877                                         tdbp->XmitDesc_tail = q;
878                                         break;
879                                 }
880                         }
881                         p->XmitDesc_next = NULL;
882                         break;
883                 }
884                 q = p;
885         }
886 }