(linenum→info "unix/slp.c:2238")

openssl/0.9.8g/engines/e_aep.c

    1: /* ====================================================================
    2:  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
    3:  *
    4:  * Redistribution and use in source and binary forms, with or without
    5:  * modification, are permitted provided that the following conditions
    6:  * are met:
    7:  *
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer. 
   10:  *
   11:  * 2. Redistributions in binary form must reproduce the above copyright
   12:  *    notice, this list of conditions and the following disclaimer in
   13:  *    the documentation and/or other materials provided with the
   14:  *    distribution.
   15:  *
   16:  * 3. All advertising materials mentioning features or use of this
   17:  *    software must display the following acknowledgment:
   18:  *    "This product includes software developed by the OpenSSL Project
   19:  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
   20:  *
   21:  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
   22:  *    endorse or promote products derived from this software without
   23:  *    prior written permission. For written permission, please contact
   24:  *    licensing@OpenSSL.org.
   25:  *
   26:  * 5. Products derived from this software may not be called "OpenSSL"
   27:  *    nor may "OpenSSL" appear in their names without prior written
   28:  *    permission of the OpenSSL Project.
   29:  *
   30:  * 6. Redistributions of any form whatsoever must retain the following
   31:  *    acknowledgment:
   32:  *    "This product includes software developed by the OpenSSL Project
   33:  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
   34:  *
   35:  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
   36:  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   37:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   38:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
   39:  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   40:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   41:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   42:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   43:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   44:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   45:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   46:  * OF THE POSSIBILITY OF SUCH DAMAGE.
   47:  * ====================================================================
   48:  *
   49:  * This product includes cryptographic software written by Eric Young
   50:  * (eay@cryptsoft.com).  This product includes software written by Tim
   51:  * Hudson (tjh@cryptsoft.com).
   52:  *
   53:  */
   54: 
   55: #include <stdio.h>
   56: #include <openssl/bn.h>
   57: #include <string.h>
   58: 
   59: #include <openssl/e_os2.h>
   60: #if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
   61: #include <sys/types.h>
   62: #include <unistd.h>
   63: #else
   64: #include <process.h>
   65: typedef int pid_t;
   66: #endif
   67: 
   68: #include <openssl/crypto.h>
   69: #include <openssl/dso.h>
   70: #include <openssl/engine.h>
   71: #include <openssl/buffer.h>
   72: #ifndef OPENSSL_NO_RSA
   73: #include <openssl/rsa.h>
   74: #endif
   75: #ifndef OPENSSL_NO_DSA
   76: #include <openssl/dsa.h>
   77: #endif
   78: #ifndef OPENSSL_NO_DH
   79: #include <openssl/dh.h>
   80: #endif
   81: #include <openssl/bn.h>
   82: 
   83: #ifndef OPENSSL_NO_HW
   84: #ifndef OPENSSL_NO_HW_AEP
   85: #ifdef FLAT_INC
   86: #include "aep.h"
   87: #else
   88: #include "vendor_defns/aep.h"
   89: #endif
   90: 
   91: #define AEP_LIB_NAME "aep engine"
   92: #define FAIL_TO_SW 0x10101010
   93: 
   94: #include "e_aep_err.c"
   95: 
   96: static int aep_init(ENGINE *e);
   97: static int aep_finish(ENGINE *e);
   98: static int aep_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
   99: static int aep_destroy(ENGINE *e);
  100: 
  101: static AEP_RV aep_get_connection(AEP_CONNECTION_HNDL_PTR hConnection);
  102: static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection);
  103: static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection);
  104: static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use);
  105: 
  106: /* BIGNUM stuff */
  107: #ifndef OPENSSL_NO_RSA
  108: static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
  109:         const BIGNUM *m, BN_CTX *ctx);
  110: 
  111: static AEP_RV aep_mod_exp_crt(BIGNUM *r,const  BIGNUM *a, const BIGNUM *p,
  112:         const BIGNUM *q, const BIGNUM *dmp1,const BIGNUM *dmq1,
  113:         const BIGNUM *iqmp, BN_CTX *ctx);
  114: #endif
  115: 
  116: /* RSA stuff */
  117: #ifndef OPENSSL_NO_RSA
  118: static int aep_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
  119: #endif
  120: 
  121: /* This function is aliased to mod_exp (with the mont stuff dropped). */
  122: #ifndef OPENSSL_NO_RSA
  123: static int aep_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
  124:         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
  125: #endif
  126: 
  127: /* DSA stuff */
  128: #ifndef OPENSSL_NO_DSA
  129: static int aep_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
  130:         BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
  131:         BN_CTX *ctx, BN_MONT_CTX *in_mont);
  132: 
  133: static int aep_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
  134:         const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
  135:         BN_MONT_CTX *m_ctx);
  136: #endif
  137: 
  138: /* DH stuff */
  139: /* This function is aliased to mod_exp (with the DH and mont dropped). */
  140: #ifndef OPENSSL_NO_DH
  141: static int aep_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
  142:         const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
  143: #endif
  144: 
  145: /* rand stuff   */
  146: #ifdef AEPRAND
  147: static int aep_rand(unsigned char *buf, int num);
  148: static int aep_rand_status(void);
  149: #endif
  150: 
  151: /* Bignum conversion stuff */
  152: static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize);
  153: static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
  154:         unsigned char* AEP_BigNum);
  155: static AEP_RV ConvertAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
  156:         unsigned char* AEP_BigNum);
  157: 
  158: /* The definitions for control commands specific to this engine */
  159: #define AEP_CMD_SO_PATH         ENGINE_CMD_BASE
  160: static const ENGINE_CMD_DEFN aep_cmd_defns[] =
  161:         {
  162:         { AEP_CMD_SO_PATH,
  163:           "SO_PATH",
  164:           "Specifies the path to the 'aep' shared library",
  165:           ENGINE_CMD_FLAG_STRING
  166:         },
  167:         {0, NULL, NULL, 0}
  168:         };
  169: 
  170: #ifndef OPENSSL_NO_RSA
  171: /* Our internal RSA_METHOD that we provide pointers to */
  172: static RSA_METHOD aep_rsa =
  173:         {
  174:         "Aep RSA method",
  175:         NULL,                /*rsa_pub_encrypt*/
  176:         NULL,                /*rsa_pub_decrypt*/
  177:         NULL,                /*rsa_priv_encrypt*/
  178:         NULL,                /*rsa_priv_encrypt*/
  179:         aep_rsa_mod_exp,     /*rsa_mod_exp*/
  180:         aep_mod_exp_mont,    /*bn_mod_exp*/
  181:         NULL,                /*init*/
  182:         NULL,                /*finish*/
  183:         0,                   /*flags*/
  184:         NULL,                /*app_data*/
  185:         NULL,                /*rsa_sign*/
  186:         NULL,                /*rsa_verify*/
  187:         NULL                 /*rsa_keygen*/
  188:         };
  189: #endif
  190: 
  191: #ifndef OPENSSL_NO_DSA
  192: /* Our internal DSA_METHOD that we provide pointers to */
  193: static DSA_METHOD aep_dsa =
  194:         {
  195:         "Aep DSA method",
  196:         NULL,                /* dsa_do_sign */
  197:         NULL,                /* dsa_sign_setup */
  198:         NULL,                /* dsa_do_verify */
  199:         aep_dsa_mod_exp,     /* dsa_mod_exp */
  200:         aep_mod_exp_dsa,     /* bn_mod_exp */
  201:         NULL,                /* init */
  202:         NULL,                /* finish */
  203:         0,                   /* flags */
  204:         NULL,                /* app_data */
  205:         NULL,                /* dsa_paramgen */
  206:         NULL                 /* dsa_keygen */
  207:         };
  208: #endif
  209: 
  210: #ifndef OPENSSL_NO_DH
  211: /* Our internal DH_METHOD that we provide pointers to */
  212: static DH_METHOD aep_dh =
  213:         {
  214:         "Aep DH method",
  215:         NULL,
  216:         NULL,
  217:         aep_mod_exp_dh,
  218:         NULL,
  219:         NULL,
  220:         0,
  221:         NULL,
  222:         NULL
  223:         };
  224: #endif
  225: 
  226: #ifdef AEPRAND
  227: /* our internal RAND_method that we provide pointers to  */
  228: static RAND_METHOD aep_random =
  229:         {
  230:         /*"AEP RAND method", */
  231:         NULL,
  232:         aep_rand,
  233:         NULL,
  234:         NULL,
  235:         aep_rand,
  236:         aep_rand_status,
  237:         };
  238: #endif
  239: 
  240: /*Define an array of structures to hold connections*/
  241: static AEP_CONNECTION_ENTRY aep_app_conn_table[MAX_PROCESS_CONNECTIONS];
  242: 
  243: /*Used to determine if this is a new process*/
  244: static pid_t    recorded_pid = 0;
  245: 
  246: #ifdef AEPRAND
  247: static AEP_U8   rand_block[RAND_BLK_SIZE];
  248: static AEP_U32  rand_block_bytes = 0;
  249: #endif
  250: 
  251: /* Constants used when creating the ENGINE */
  252: static const char *engine_aep_id = "aep";
  253: static const char *engine_aep_name = "Aep hardware engine support";
  254: 
  255: static int max_key_len = 2176;
  256: 
  257: 
  258: /* This internal function is used by ENGINE_aep() and possibly by the
  259:  * "dynamic" ENGINE support too */
  260: static int bind_aep(ENGINE *e)
  261:         {
  262: #ifndef OPENSSL_NO_RSA
  263:         const RSA_METHOD  *meth1;
  264: #endif
  265: #ifndef OPENSSL_NO_DSA
  266:         const DSA_METHOD  *meth2;
  267: #endif
  268: #ifndef OPENSSL_NO_DH
  269:         const DH_METHOD          *meth3;
  270: #endif
  271: 
  272:         if(!ENGINE_set_id(e, engine_aep_id) ||
  273:                 !ENGINE_set_name(e, engine_aep_name) ||
  274: #ifndef OPENSSL_NO_RSA
  275:                 !ENGINE_set_RSA(e, &aep_rsa) ||
  276: #endif
  277: #ifndef OPENSSL_NO_DSA
  278:                 !ENGINE_set_DSA(e, &aep_dsa) ||
  279: #endif
  280: #ifndef OPENSSL_NO_DH
  281:                 !ENGINE_set_DH(e, &aep_dh) ||
  282: #endif
  283: #ifdef AEPRAND
  284:                 !ENGINE_set_RAND(e, &aep_random) ||
  285: #endif
  286:                 !ENGINE_set_init_function(e, aep_init) ||
  287:                 !ENGINE_set_destroy_function(e, aep_destroy) ||
  288:                 !ENGINE_set_finish_function(e, aep_finish) ||
  289:                 !ENGINE_set_ctrl_function(e, aep_ctrl) ||
  290:                 !ENGINE_set_cmd_defns(e, aep_cmd_defns))
  291:                 return 0;
  292: 
  293: #ifndef OPENSSL_NO_RSA
  294:         /* We know that the "PKCS1_SSLeay()" functions hook properly
  295:          * to the aep-specific mod_exp and mod_exp_crt so we use
  296:          * those functions. NB: We don't use ENGINE_openssl() or
  297:          * anything "more generic" because something like the RSAref
  298:          * code may not hook properly, and if you own one of these
  299:          * cards then you have the right to do RSA operations on it
  300:          * anyway! */
  301:         meth1 = RSA_PKCS1_SSLeay();
  302:         aep_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
  303:         aep_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
  304:         aep_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
  305:         aep_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
  306: #endif
  307: 
  308: 
  309: #ifndef OPENSSL_NO_DSA
  310:         /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
  311:          * bits. */
  312:         meth2 = DSA_OpenSSL();
  313:         aep_dsa.dsa_do_sign    = meth2->dsa_do_sign;
  314:         aep_dsa.dsa_sign_setup = meth2->dsa_sign_setup;
  315:         aep_dsa.dsa_do_verify  = meth2->dsa_do_verify;
  316: 
  317:         aep_dsa = *DSA_get_default_method(); 
  318:         aep_dsa.dsa_mod_exp = aep_dsa_mod_exp; 
  319:         aep_dsa.bn_mod_exp = aep_mod_exp_dsa;
  320: #endif
  321: 
  322: #ifndef OPENSSL_NO_DH
  323:         /* Much the same for Diffie-Hellman */
  324:         meth3 = DH_OpenSSL();
  325:         aep_dh.generate_key = meth3->generate_key;
  326:         aep_dh.compute_key  = meth3->compute_key;
  327:         aep_dh.bn_mod_exp   = meth3->bn_mod_exp;
  328: #endif
  329: 
  330:         /* Ensure the aep error handling is set up */
  331:         ERR_load_AEPHK_strings();
  332: 
  333:         return 1;
  334: }
  335: 
  336: #ifndef OPENSSL_NO_DYNAMIC_ENGINE
  337: static int bind_helper(ENGINE *e, const char *id)
  338:         {
  339:         if(id && (strcmp(id, engine_aep_id) != 0))
  340:                 return 0;
  341:         if(!bind_aep(e))
  342:                 return 0;
  343:         return 1;
  344:         }       
  345: IMPLEMENT_DYNAMIC_CHECK_FN()
  346: IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
  347: #else
  348: static ENGINE *engine_aep(void)
  349:         {
  350:         ENGINE *ret = ENGINE_new();
  351:         if(!ret)
  352:                 return NULL;
  353:         if(!bind_aep(ret))
  354:                 {
  355:                 ENGINE_free(ret);
  356:                 return NULL;
  357:                 }
  358:         return ret;
  359:         }
  360: 
  361: void ENGINE_load_aep(void)
  362:         {
  363:         /* Copied from eng_[openssl|dyn].c */
  364:         ENGINE *toadd = engine_aep();
  365:         if(!toadd) return;
  366:         ENGINE_add(toadd);
  367:         ENGINE_free(toadd);
  368:         ERR_clear_error();
  369:         }
  370: #endif
  371: 
  372: /* This is a process-global DSO handle used for loading and unloading
  373:  * the Aep library. NB: This is only set (or unset) during an
  374:  * init() or finish() call (reference counts permitting) and they're
  375:  * operating with global locks, so this should be thread-safe
  376:  * implicitly. */
  377: static DSO *aep_dso = NULL;
  378: 
  379: /* These are the static string constants for the DSO file name and the function
  380:  * symbol names to bind to. 
  381: */
  382: static const char *AEP_LIBNAME = NULL;
  383: static const char *get_AEP_LIBNAME(void)
  384:         {
  385:         if(AEP_LIBNAME)
  386:                 return AEP_LIBNAME;
  387:         return "aep";
  388:         }
  389: static void free_AEP_LIBNAME(void)
  390:         {
  391:         if(AEP_LIBNAME)
  392:                 OPENSSL_free((void*)AEP_LIBNAME);
  393:         AEP_LIBNAME = NULL;
  394:         }
  395: static long set_AEP_LIBNAME(const char *name)
  396:         {
  397:         free_AEP_LIBNAME();
  398:         return ((AEP_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
  399:         }
  400: 
  401: static const char *AEP_F1    = "AEP_ModExp";
  402: static const char *AEP_F2    = "AEP_ModExpCrt";
  403: #ifdef AEPRAND
  404: static const char *AEP_F3    = "AEP_GenRandom";
  405: #endif
  406: static const char *AEP_F4    = "AEP_Finalize";
  407: static const char *AEP_F5    = "AEP_Initialize";
  408: static const char *AEP_F6    = "AEP_OpenConnection";
  409: static const char *AEP_F7    = "AEP_SetBNCallBacks";
  410: static const char *AEP_F8    = "AEP_CloseConnection";
  411: 
  412: /* These are the function pointers that are (un)set when the library has
  413:  * successfully (un)loaded. */
  414: static t_AEP_OpenConnection    *p_AEP_OpenConnection  = NULL;
  415: static t_AEP_CloseConnection   *p_AEP_CloseConnection = NULL;
  416: static t_AEP_ModExp            *p_AEP_ModExp          = NULL;
  417: static t_AEP_ModExpCrt         *p_AEP_ModExpCrt       = NULL;
  418: #ifdef AEPRAND
  419: static t_AEP_GenRandom         *p_AEP_GenRandom       = NULL;
  420: #endif
  421: static t_AEP_Initialize        *p_AEP_Initialize      = NULL;
  422: static t_AEP_Finalize          *p_AEP_Finalize        = NULL;
  423: static t_AEP_SetBNCallBacks    *p_AEP_SetBNCallBacks  = NULL;
  424: 
  425: /* (de)initialisation functions. */
  426: static int aep_init(ENGINE *e)
  427:         {
  428:         t_AEP_ModExp          *p1;
  429:         t_AEP_ModExpCrt       *p2;
  430: #ifdef AEPRAND
  431:         t_AEP_GenRandom       *p3;
  432: #endif
  433:         t_AEP_Finalize        *p4;
  434:         t_AEP_Initialize      *p5;
  435:         t_AEP_OpenConnection  *p6;
  436:         t_AEP_SetBNCallBacks  *p7;
  437:         t_AEP_CloseConnection *p8;
  438: 
  439:         int to_return = 0;
  440:  
  441:         if(aep_dso != NULL)
  442:                 {
  443:                 AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_ALREADY_LOADED);
  444:                 goto err;
  445:                 }
  446:         /* Attempt to load libaep.so. */
  447: 
  448:         aep_dso = DSO_load(NULL, get_AEP_LIBNAME(), NULL, 0);
  449:   
  450:         if(aep_dso == NULL)
  451:                 {
  452:                 AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_NOT_LOADED);
  453:                 goto err;
  454:                 }
  455: 
  456:         if(    !(p1 = (t_AEP_ModExp *)     DSO_bind_func( aep_dso,AEP_F1))  ||
  457:                 !(p2 = (t_AEP_ModExpCrt*)   DSO_bind_func( aep_dso,AEP_F2))  ||
  458: #ifdef AEPRAND
  459:                 !(p3 = (t_AEP_GenRandom*)   DSO_bind_func( aep_dso,AEP_F3))  ||
  460: #endif
  461:                 !(p4 = (t_AEP_Finalize*)    DSO_bind_func( aep_dso,AEP_F4))  ||
  462:                 !(p5 = (t_AEP_Initialize*)  DSO_bind_func( aep_dso,AEP_F5))  ||
  463:                 !(p6 = (t_AEP_OpenConnection*) DSO_bind_func( aep_dso,AEP_F6))  ||
  464:                 !(p7 = (t_AEP_SetBNCallBacks*) DSO_bind_func( aep_dso,AEP_F7))  ||
  465:                 !(p8 = (t_AEP_CloseConnection*) DSO_bind_func( aep_dso,AEP_F8)))
  466:                 {
  467:                 AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_NOT_LOADED);
  468:                 goto err;
  469:                 }
  470: 
  471:         /* Copy the pointers */
  472:   
  473:         p_AEP_ModExp           = p1;
  474:         p_AEP_ModExpCrt        = p2;
  475: #ifdef AEPRAND
  476:         p_AEP_GenRandom        = p3;
  477: #endif
  478:         p_AEP_Finalize         = p4;
  479:         p_AEP_Initialize       = p5;
  480:         p_AEP_OpenConnection   = p6;
  481:         p_AEP_SetBNCallBacks   = p7;
  482:         p_AEP_CloseConnection  = p8;
  483:  
  484:         to_return = 1;
  485:  
  486:         return to_return;
  487: 
  488:  err: 
  489: 
  490:         if(aep_dso)
  491:                 DSO_free(aep_dso);
  492:         aep_dso = NULL;
  493:                 
  494:         p_AEP_OpenConnection    = NULL;
  495:         p_AEP_ModExp            = NULL;
  496:         p_AEP_ModExpCrt         = NULL;
  497: #ifdef AEPRAND
  498:         p_AEP_GenRandom         = NULL;
  499: #endif
  500:         p_AEP_Initialize        = NULL;
  501:         p_AEP_Finalize          = NULL;
  502:         p_AEP_SetBNCallBacks    = NULL;
  503:         p_AEP_CloseConnection   = NULL;
  504: 
  505:         return to_return;
  506:         }
  507: 
  508: /* Destructor (complements the "ENGINE_aep()" constructor) */
  509: static int aep_destroy(ENGINE *e)
  510:         {
  511:         free_AEP_LIBNAME();
  512:         ERR_unload_AEPHK_strings();
  513:         return 1;
  514:         }
  515: 
  516: static int aep_finish(ENGINE *e)
  517:         {
  518:         int to_return = 0, in_use;
  519:         AEP_RV rv;
  520: 
  521:         if(aep_dso == NULL)
  522:                 {
  523:                 AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_NOT_LOADED);
  524:                 goto err;
  525:                 }
  526: 
  527:         rv = aep_close_all_connections(0, &in_use);
  528:         if (rv != AEP_R_OK)
  529:                 {
  530:                 AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_CLOSE_HANDLES_FAILED);
  531:                 goto err;
  532:                 }
  533:         if (in_use)
  534:                 {
  535:                 AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_CONNECTIONS_IN_USE);
  536:                 goto err;
  537:                 }
  538: 
  539:         rv = p_AEP_Finalize();
  540:         if (rv != AEP_R_OK)
  541:                 {
  542:                 AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_FINALIZE_FAILED);
  543:                 goto err;
  544:                 }
  545: 
  546:         if(!DSO_free(aep_dso))
  547:                 {
  548:                 AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_UNIT_FAILURE);
  549:                 goto err;
  550:                 }
  551: 
  552:         aep_dso = NULL;
  553:         p_AEP_CloseConnection   = NULL;