make update (libeay.num has been edited to match 0.9.7-stable)
[openssl.git] / crypto / engine / hw_aep.c
index c661dfa14d39b6a402371b2419da7585776f6a6a..cf4507cff11a383d8efbafc97cad236a3a2221be 100644 (file)
@@ -81,6 +81,8 @@ typedef int pid_t;
 #endif
 
 #define AEP_LIB_NAME "aep engine"
+#define FAIL_TO_SW 0x10101010
+
 #include "hw_aep_err.c"
 
 static int aep_init(ENGINE *e);
@@ -90,6 +92,7 @@ static int aep_destroy(ENGINE *e);
 
 static AEP_RV aep_get_connection(AEP_CONNECTION_HNDL_PTR hConnection);
 static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection);
+static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection);
 static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use);
 
 /* BIGNUM stuff */
@@ -134,8 +137,8 @@ static int aep_rand_status(void);
 #endif
 
 /* Bignum conversion stuff */
-static AEP_RV GetBigNumSize(void* ArbBigNum, AEP_U32* BigNumSize);
-static AEP_RV MakeAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
+static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize);
+static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
        unsigned char* AEP_BigNum);
 static AEP_RV ConvertAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
        unsigned char* AEP_BigNum);
@@ -233,6 +236,8 @@ static AEP_U32  rand_block_bytes = 0;
 static const char *engine_aep_id = "aep";
 static const char *engine_aep_name = "Aep hardware engine support";
 
+static int max_key_len = 2176;
+
 
 /* This internal function is used by ENGINE_aep() and possibly by the
  * "dynamic" ENGINE support too */
@@ -399,7 +404,6 @@ static int aep_init(ENGINE *e)
        t_AEP_CloseConnection *p8;
 
        int to_return = 0;
-       AEP_RV rv;
  
        if(aep_dso != NULL)
                {
@@ -558,15 +562,25 @@ static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
        const BIGNUM *m, BN_CTX *ctx)
        {
        int to_return = 0;
+       int     r_len = 0;
        AEP_CONNECTION_HNDL hConnection;
        AEP_RV rv;
+       
+       r_len = BN_num_bits(m);
+
+       /* Perform in software if modulus is too large for hardware. */
+
+       if (r_len > max_key_len){
+               AEPHKerr(AEPHK_F_AEP_MOD_EXP, AEPHK_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+               return BN_mod_exp(r, a, p, m, ctx);
+       } 
 
        /*Grab a connection from the pool*/
        rv = aep_get_connection(&hConnection);
        if (rv != AEP_R_OK)
                {     
                AEPHKerr(AEPHK_F_AEP_MOD_EXP,AEPHK_R_GET_HANDLE_FAILED);
-               goto err;
+               return BN_mod_exp(r, a, p, m, ctx);
                }
 
        /*To the card with the mod exp*/
@@ -575,8 +589,8 @@ static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
        if (rv !=  AEP_R_OK)
                {
                AEPHKerr(AEPHK_F_AEP_MOD_EXP,AEPHK_R_MOD_EXP_FAILED);
-               rv = aep_return_connection(hConnection);
-               goto err;
+               rv = aep_close_connection(hConnection);
+               return BN_mod_exp(r, a, p, m, ctx);
                }
 
        /*Return the connection to the pool*/
@@ -604,7 +618,7 @@ static AEP_RV aep_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
        if (rv != AEP_R_OK)
                {
                AEPHKerr(AEPHK_F_AEP_MOD_EXP_CRT,AEPHK_R_GET_HANDLE_FAILED);
-               goto err;
+               return FAIL_TO_SW;
                }
 
        /*To the card with the mod exp*/
@@ -613,8 +627,8 @@ static AEP_RV aep_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
        if (rv != AEP_R_OK)
                {
                AEPHKerr(AEPHK_F_AEP_MOD_EXP_CRT,AEPHK_R_MOD_EXP_CRT_FAILED);
-               rv = aep_return_connection(hConnection);
-               goto err;
+               rv = aep_close_connection(hConnection);
+               return FAIL_TO_SW;
                }
 
        /*Return the connection to the pool*/
@@ -636,9 +650,6 @@ static int aep_rand(unsigned char *buf,int len )
        AEP_RV rv = AEP_R_OK;
        AEP_CONNECTION_HNDL hConnection;
 
-       int to_return = 0;
-
-  
        CRYPTO_w_lock(CRYPTO_LOCK_RAND);
 
        /*Can the request be serviced with what's already in the buffer?*/
@@ -731,7 +742,13 @@ static int aep_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
        if (rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp)
                {
                rv =  aep_mod_exp_crt(r0,I,rsa->p,rsa->q, rsa->dmp1,rsa->dmq1,rsa->iqmp,ctx);
-               if (rv != AEP_R_OK)
+
+               if (rv == FAIL_TO_SW){
+                       const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+                       to_return = (*meth->rsa_mod_exp)(r0, I, rsa);
+                       goto err;
+               }
+               else if (rv != AEP_R_OK)
                        goto err;
                }
        else
@@ -931,10 +948,36 @@ static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection)
        return AEP_R_OK;
        }
 
+static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection)
+       {
+       int count;
+       AEP_RV rv = AEP_R_OK;
+
+       CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+
+       /*Find the connection item that matches this connection handle*/
+       for(count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+               {
+               if (aep_app_conn_table[count].conn_hndl == hConnection)
+                       {
+                       rv = p_AEP_CloseConnection(aep_app_conn_table[count].conn_hndl);
+                       if (rv != AEP_R_OK)
+                               goto end;
+                       aep_app_conn_table[count].conn_state = NotConnected;
+                       aep_app_conn_table[count].conn_hndl  = 0;
+                       break;
+                       }
+               }
+
+ end:
+       CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+       return rv;
+       }
+
 static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use)
        {
        int count;
-       AEP_RV rv;
+       AEP_RV rv = AEP_R_OK;
 
        *in_use = 0;
        if (use_engine_lock) CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
@@ -945,7 +988,7 @@ static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use)
                case Connected:
                        rv = p_AEP_CloseConnection(aep_app_conn_table[count].conn_hndl);
                        if (rv != AEP_R_OK)
-                               return rv;
+                               goto end;
                        aep_app_conn_table[count].conn_state = NotConnected;
                        aep_app_conn_table[count].conn_hndl  = 0;
                        break;
@@ -956,14 +999,15 @@ static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use)
                        break;
                        }
                }
+ end:
        if (use_engine_lock) CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-       return AEP_R_OK;
+       return rv;
        }
 
 /*BigNum call back functions, used to convert OpenSSL bignums into AEP bignums.
   Note only 32bit Openssl build support*/
 
-static AEP_RV GetBigNumSize(void* ArbBigNum, AEP_U32* BigNumSize)
+static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize)
        {
        BIGNUM* bn;
 
@@ -981,7 +1025,7 @@ static AEP_RV GetBigNumSize(void* ArbBigNum, AEP_U32* BigNumSize)
        return AEP_R_OK;
        }
 
-static AEP_RV MakeAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
+static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
        unsigned char* AEP_BigNum)
        {
        BIGNUM* bn;
@@ -1003,8 +1047,8 @@ static AEP_RV MakeAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
                {
                buf = (unsigned char*)&bn->d[i];
 
-               *((AEP_U32*)AEP_BigNum) =
-                       (AEP_U32) ((unsigned) buf[1] << 8 | buf[0]) |
+               *((AEP_U32*)AEP_BigNum) = (AEP_U32)
+                       ((unsigned) buf[1] << 8 | buf[0]) |
                        ((unsigned) buf[3] << 8 | buf[2])  << 16;
 
                AEP_BigNum += 4;