blob: 8db05fc63fd1f5a92882b08f286fb200c273689e [file] [log] [blame]
/*
* 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];
}