/* 
 * Copyright (c) 1999-2002 AEP Systems Ltd.
 * Bray Business Park, Southern Cross Route, Bray, Co. Wicklow, Ireland.
 * All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright notice, 
 * this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation 
 * and/or other materials provided with the distribution.
 * 
 * 3. Neither the name of AEP Systems Ltd. nor the names of its contributors 
 * may be used to endorse or promote products derived from this software 
 * without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 * 
 */

#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "aeptok_api.h"

extern int cryptoki_aep_avail;

static int aep_initialised = FALSE;

static AEP_CONNECTION_ENTRY aep_app_conn_table[MAX_PROCESS_CONNECTIONS];
static pid_t	recorded_pid = 0;

static pthread_mutex_t AEP_ThreadPool_mutex=PTHREAD_MUTEX_INITIALIZER;


static
AEP_RV 
GetAEPConnection(AEP_CONNECTION_HNDL *hConnection)
{
	int count;
	AEP_RV rv = AEP_R_OK;
	pid_t curr_pid = getpid();
	
	pthread_mutex_lock(&AEP_ThreadPool_mutex);
	
	// Check if this is the first time this is being called
	// from the current process
	//	if (recorded_pid != curr_pid) {

	if (aep_initialised != TRUE) {
		aep_initialised = TRUE;		
		recorded_pid = curr_pid;

		AEP_Finalize();
		
		/*Initialise the AEP API*/
		if ( (rv = AEP_Initialize(NULL)) != AEP_R_OK) {
			aep_initialised = FALSE;		
			recorded_pid = 0;
			goto end;
		}
		
		/*Set the AEP big num call back functions*/	
		rv = AEP_SetBNCallBacks(&GetBigNumSize, &MakeAEPBigNum,
					&ConvertAEPBigNum);
		
		if (rv != AEP_R_OK) {
			aep_initialised = FALSE;		
			recorded_pid = 0;
			goto end;
		}
		
		/*Init the structures*/
		for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) {
			aep_app_conn_table[count].conn_state = NotConnected;
			aep_app_conn_table[count].conn_hndl  = 0;
		}
		
		
		if ( (rv = AEP_OpenConnection(hConnection)) != AEP_R_OK) {
			/* a problem here, assume AEP subsystem is dead ! */
			cryptoki_aep_avail = FALSE;
			aep_initialised = FALSE;
			recorded_pid = 0;
			st_err_log(12, __FILE__, __LINE__);
			goto end;
		}
		
		aep_app_conn_table[0].conn_state = InUse;
		aep_app_conn_table[0].conn_hndl = *hConnection;
		goto end;
	}
	for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) {
		if (aep_app_conn_table[count].conn_state == Connected) {
			aep_app_conn_table[count].conn_state = InUse;
			*hConnection = aep_app_conn_table[count].conn_hndl;
			goto end;
		}
	}
	
	/*If no connections available, we try to open a new one*/
	for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) {
		if (aep_app_conn_table[count].conn_state == NotConnected) {
			rv = AEP_OpenConnection(hConnection);
			
			if ( rv != AEP_R_OK){
				// a problem here, assume AEP subsystem is dead !
				cryptoki_aep_avail = FALSE;
				st_err_log(12, __FILE__, __LINE__);
				goto end;
			}
			aep_app_conn_table[count].conn_state = InUse;		
			aep_app_conn_table[count].conn_hndl = *hConnection;
			goto end;
		}
	}
	rv = AEP_R_GENERAL_ERROR;
 end:
	pthread_mutex_unlock(&AEP_ThreadPool_mutex);
	return rv;
}


static
AEP_RV ReturnAEPConnection(AEP_CONNECTION_HNDL hConnection) 
{
	int count;
	
	pthread_mutex_lock(&AEP_ThreadPool_mutex);
	
	/*Find the connection */
	for(count = 0;count < MAX_PROCESS_CONNECTIONS;count ++) {
		if (aep_app_conn_table[count].conn_hndl == hConnection) {
			aep_app_conn_table[count].conn_state = Connected;
			break;
		}
	}
	
	pthread_mutex_unlock(&AEP_ThreadPool_mutex);	
	return AEP_R_OK;	
}


int
AEP_RSA_public_encrypt(unsigned long in_data_len,
		       unsigned char *in_data,
		       unsigned char *out_data,
		       RSA *rsa)
{
	AEP_RV rv;
	AEP_CONNECTION_HNDL hConnection;
	BIGNUM rr;
	BIGNUM *a;

	if ( GetAEPConnection(&hConnection) != AEP_R_OK) {
		ReturnAEPConnection(hConnection);
		return 0;
	}
	
	if ( (a = BN_new()) == NULL) {
		ReturnAEPConnection(hConnection);
		return 0;
	}
	
	BN_bin2bn( in_data, in_data_len, a);
	
	rv = AEP_ModExp(hConnection, (void*)a, (void*) rsa->e,
			(void*) rsa->n, (void*)&rr, NULL);
	
	if (rv!=AEP_R_OK) {
		ReturnAEPConnection(hConnection);
		BN_free(a);
		return 0;
	}
	
	memset(out_data, 0, in_data_len);
	if ( rr.top * 4 > in_data_len) {
		ReturnAEPConnection(hConnection);
		BN_free(a);
		return 0;
	}
	invert( out_data, (unsigned char*) rr.d, rr.top*4);
	
	ReturnAEPConnection(hConnection);
	BN_free(a);
	return 1;
}

int
AEP_RSA_private_decrypt(unsigned long in_data_len,
			unsigned char *in_data,
			unsigned char *out_data,
			RSA *rsa)
{
	AEP_RV rv ;
	AEP_CONNECTION_HNDL hConnection;
	BIGNUM rr;
	BIGNUM* a;

	if ( GetAEPConnection(&hConnection) != AEP_R_OK) {	
		ReturnAEPConnection(hConnection);	
		return 0;
	}
	
	if(!rsa->d || !rsa->n )	{
		ReturnAEPConnection(hConnection);
		return 0;
	}
	if ( (a = BN_new()) == NULL) {
		ReturnAEPConnection(hConnection);	
		return 0;
	}
	
	BN_bin2bn( in_data, in_data_len, a);			
	
	if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
		rv = AEP_ModExp(hConnection, (void *)a,
				(void *)(rsa->d), (void *)(rsa->n),
				(void *)&rr, NULL);
	} else {
		rv = AEP_ModExpCrt(hConnection, (void *)a, (void *)(rsa->p),
				   (void *)(rsa->q), (void *)(rsa->dmp1),
				   (void *)(rsa->dmq1), (void *)(rsa->iqmp),
				   (void *)&rr, NULL);
	}

	if (rv!=AEP_R_OK) {
		ReturnAEPConnection(hConnection);
		BN_free(a);
		return 0;
	}

	memset(out_data, 0, in_data_len);
	if ( rr.top * 4 > in_data_len) {
		ReturnAEPConnection(hConnection);
		BN_free(a);
		return 0;
	}
	invert( out_data, (unsigned char *) rr.d, rr.top*4);

	ReturnAEPConnection(hConnection);	
	BN_free(a);

	return 1;
}	
	
/* BigNum call back functions, used to convert OpenSSL 
 * bignums into AEP bignums
 */

AEP_RV
GetBigNumSize(void* ArbBigNum, AEP_U32* BigNumSize)
{
	BIGNUM* bn;

	/*Cast the ArbBigNum pointer to our BIGNUM struct*/
	bn = (BIGNUM*) ArbBigNum;

	/*Size of the bignum in bytes is equal to the bn->top
	  (no of 32 bit words) multiplies by 4*/
	*BigNumSize = bn->top << 2;

	return AEP_R_OK;
}

AEP_RV MakeAEPBigNum(void* ArbBigNum,
		     AEP_U32 BigNumSize,
		     unsigned char* AEP_BigNum)
{
	BIGNUM* bn;
	unsigned char* buf;
	int i;

	/*Cast the ArbBigNum pointer to our BIGNUM struct*/
	bn = (BIGNUM*) ArbBigNum;

	if (BigNumSize != bn->top * 4) 
		return AEP_R_GENERAL_ERROR;
	
	memcpy(AEP_BigNum, (unsigned char *) bn->d, BigNumSize);

	return AEP_R_OK;
}

AEP_RV ConvertAEPBigNum(void* ArbBigNum,
			AEP_U32 BigNumSize,
			unsigned char* AEP_BigNum)
{
	BIGNUM* bn;
	int i;

	bn = (BIGNUM*)ArbBigNum;

	/*Make sure big num is a multiple of 4*/
	if (BigNumSize & 3 != 0) {
		exit(1);
	}
	bn->top = BigNumSize >> 2;
	
	bn->d = (unsigned long*)AEP_malloc(BigNumSize);

	memcpy( (unsigned char *) bn->d, AEP_BigNum, BigNumSize);
	
	return AEP_R_OK;
}

static
void
invert(unsigned char* dest, unsigned char* orig, int len)
{
  while (len--)
    *dest++ = orig[len];
}
