Dear all,
I wrote a function like this:
DLL_INT ECryptEncryptData(char* certFile, char* dataFile, char*
encryptedFile, char* errMsg, int errMsgLen)
{
static char* func = "ECryptEncryptData";
int rc = 0;
char msg[MSG_LEN];
BIO *in = NULL, *out = NULL;//, *tbio = NULL;//, *dout = NULL;
BIO *bio_err_out = NULL;
X509 *rcert = NULL;
STACK_OF(X509) *recips = NULL;
CMS_ContentInfo *cms = NULL;
EVP_PKEY *publickey = NULL;
EVP_CIPHER *eAlgt = NULL;
int flags = CMS_BINARY;// | CMS_STREAM;// | CMS_DETACHED;
if (errMsg == NULL || errMsgLen <= 0) {
WriteLog(ERROR, "%s[%d] invalid input\n", func, __LINE__);
return -1;
}
errMsg[0] = 0;
printf_s("%s[%d] Infor dataFile[%s] encryptedFile[%s]\n", func,
__LINE__, dataFile, encryptedFile);
//OpenSSL_add_all_algorithms();
//ERR_load_crypto_strings();
eAlgt = (EVP_CIPHER*)EVP_des_ede3_cbc();
/* Read in recipient certificate */
if ((publickey = getPublicKey(certFile, &rcert, msg, sizeof(msg), &rc))
== NULL) {
sprintf_s(errMsg, errMsgLen, "%s[%d] getPublicKey fail %s\n", func,
__LINE__, msg);
goto cleanup;
}
else {
EVP_PKEY_free(publickey);
}
/* Create recipient STACK and add recipient cert to it */
if ((recips = sk_X509_new_null()) == NULL || !sk_X509_push(recips,
rcert)) {
sprintf_s(errMsg, errMsgLen, "%s[%d] sk_X509_new_null fail\n",
func, __LINE__);
goto cleanup;
}
/* sk_X509_pop_free will free up recipient STACK and its contents
* so set rcert to NULL so it isn't freed up twice.
*/
rcert = NULL;
/* Open content being encrypted */
if ((in = BIO_new_file(dataFile, "r")) == NULL) {
sprintf_s(errMsg, errMsgLen, "%s[%d] BIO_new_file fail\n", func,
__LINE__);
goto cleanup;
}
/* encrypt content */
else if ((cms = CMS_encrypt(recips, in, eAlgt, flags)) == NULL) {
sprintf_s(errMsg, errMsgLen, "%s[%d] CMS_encrypt_WithHeader
fail\n", func, __LINE__);
goto cleanup;
}
else if ((out = BIO_new_file(encryptedFile, "wb")) == NULL) {
sprintf_s(errMsg, errMsgLen, "%s[%d] BIO_new_file fail\n", func,
__LINE__);
goto cleanup;
}
/* Write out S/MIME message */
else if (!i2d_CMS_bio_stream(out, cms, in, flags)) {
sprintf_s(errMsg, errMsgLen, "%s[%d] i2d_CMS_bio_stream fail\n",
func, __LINE__);
goto cleanup;
}
cleanup:
if (strlen(errMsg)) {
WriteLog(ERROR, "%s", errMsg);
if (!rc)
rc = -1;
bio_err_out = OpenLog();
}
if (cms)
CMS_ContentInfo_free(cms);
if (rcert)
X509_free(rcert);
if (recips)
sk_X509_pop_free(recips, X509_free);
if (in)
BIO_free(in);
if (out)
BIO_free(out);
/*if (dout)
BIO_free(dout);*/
/*if (tbio)
BIO_free(tbio);*/
if (bio_err_out) {
if (MEM_LEAK_CHEK)
CRYPTO_mem_leaks(bio_err_out);
ERR_print_errors(bio_err_out);
BIO_free(bio_err_out);
}
return rc;
}
I export it to an external dll for other application to call it.
Everything is OK for a single call to it. But when it be called concurrent
in multi threads (one thread proceeded a difference file), the return
encrypted file will fail (the file size some times has 0 bytes...).
I also try not use it in multi threads. I ran many applications at the same
time to encrypt multiple files (one application proceeded a difference
file) but it still failed.
I very much appreciate for any help
Thank you,
Vu Le