Hi,

    I wrote a simple pkcs12 demo(under Windows), it just read from a PKCS12
file and got private key and certificate.
    If I use single thread, it works fine.
    If I use multi-thread, it works fine for a while ,then popups an error
dialogue "heap is corrupt".If I debug it in Visual Studio,it points to
PKCS12_parse() .
    If I use EnterCriticalSection and LeaveCriticalSection with
multi-thread, it works fine too, but as you know, the effect is as same as
single thread does.

   So I want to know , what shared resource is protected by
CriticalSection? Is PKCS12_parse() not thread-safe? Can it  be executed in
multi-threads without mutex?

   Thank you in advance.

    Here is the source code.
===========================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <windows.h>
#include <fcntl.h>
#include <sys/stat.h>

#include <openssl/pkcs12.h>

char p12file[256]="C:/test/ABCD.p12";
char p12pswd[10]="123456";
unsigned char *p12buf = NULL;
int p12buflen = 0;
#define N 30  //  amount of threads
#define M 20  //  amount of executions per thread

/* read the content from a  PKCS12 file */
int Load_File(char * filename, unsigned char *pbuf, int * plen)
{
 int   fd = -1;
 struct stat  stat_buf;
 int   len=0,count=0,size=0;

 if ((fd = open(filename, O_RDONLY|O_BINARY, S_IREAD)) < 0)
 {
  return 1;
 }

 if (stat(filename, &stat_buf) != 0)
 {
  close(fd);
  return 1;
 }
 len = stat_buf.st_size;

 if (pbuf == NULL)
 {
  *plen = len;
 }
 else
 {
  count=0;
  while (count < len)
  {
   size = read(fd, pbuf + count, len - count);
   if (size <= 0)
   {
    close(fd);
    if (pbuf != NULL)
     free(pbuf);
    return 1;
   }
   count += size;
  }
  *plen = len;
 }
 close(fd);


 return 0;
}


int pkcs12test(unsigned char *p12buf, int p12buflen, unsigned char *p12pswd)
{
 PKCS12           *p12;
 X509             *cert;
 EVP_PKEY         *prvkey;
 int              len;
 char             buf[4096];
 int              i=0;
 char     desc[1000];

 OpenSSL_add_all_algorithms();

 if ((p12buf==NULL)||(p12buflen<=0))
 {
  printf("parameter error\n");
  return -1;
 }


 p12 = d2i_PKCS12(NULL,(const unsigned char **)&p12buf,p12buflen);
 if(p12 == NULL)
 {

  printf("d2i_PKCS12 error\n");
  return -1;
 }

 if(PKCS12_parse(p12,p12pswd,&prvkey,&cert,NULL)!=1)
 {
  if (p12!=NULL)
  {
   PKCS12_free(p12);
   p12=NULL;
  }
  printf("PKCS12_parse error\n");
  return -1;
 }

 PKCS12_free(p12);
 p12=NULL;

 return 0;
}

typedef struct _param{
 int threadidx;
 int type;
} THREADPARAM;

DWORD WINAPI ThreadProc( LPVOID param )
{
 THREADPARAM *pa;
 int i = 0;
 int ret = 0;

 pa = (THREADPARAM *)param;
 printf("[%d]thread BEGIN\n",pa->threadidx);

 for (i=0;i<M;i++)
 {
  ret = pkcs12test(p12buf,p12buflen,p12pswd);
  if (ret == 0)
  {
   printf("pkcs12test success[%d_%d]\n",pa->threadidx,i);
  }
  else
  {
   printf("pkcs12test error[%d_%d]\n",pa->threadidx,i);
  }

 }

 printf("[%d]thread END\n",pa->threadidx);
 _sleep(10*1000);

 return 0;
}

void main()
{
 DWORD dwThreadId[N];
 HANDLE hThread[N];
 THREADPARAM *param[N];
 int ret = 0;
 int i=0,j=0;


 ret = Load_File(p12file, NULL, &p12buflen);
 if (ret != 0)
 {
  return ;
 }

 p12buf = (unsigned char *)malloc(p12buflen+1);
 if (p12buf == NULL)
 {
  printf("malloc(%d) fail\n",p12buflen);
  return ;
 }

 ret = Load_File(p12file, p12buf, &p12buflen);
 if (ret != 0)
 {
  return ;
 }

 for( i=0; i<N; i++ )
 {
  param[i] = (THREADPARAM *)malloc(sizeof(THREADPARAM));
  if (param[i] == NULL)
  {
   printf("malloc fail\n");
   return ;
  }
  param[i]->threadidx = i;
  param[i]->type = 1;

  hThread[i] = CreateThread(
   NULL,
   0,
   ThreadProc,
   param[i],
   0,
   &dwThreadId[i]);

  if (hThread[i] == NULL)
  {
   ExitProcess(i);
  }
 }

 printf("before wait...");
 WaitForMultipleObjects(N, hThread, TRUE, INFINITE);
 printf("...end wait\n");

 _sleep(5*60*1000);

 for(i=0; i<N; i++)
 {
  CloseHandle(hThread[i]);
  if (param[i]!=NULL)
  {
   free(param[i]);
   param[i]=NULL;
  }
 }

 return ;
}

Reply via email to