Here are examples, from my code, of both 3DES and AES. Any questions,
ask away.
Chaz.
Harald Latzko wrote:
Hi!
Do you have a solution for deryption of big files using des3 and/or
aes256, too? The openSSL command line smime utility eats up all my
memory and crashes after a while...
Greetings,
Harald
Am 17.05.2007 um 01:15 schrieb Chaz.:
[EMAIL PROTECTED] wrote:
Hi, all
I have encrypted the file with the manpage example (blowfish), and then
decrypt it. It will be fine if I try some small files, however, when I
test some big files (e.g.: 100M), the decryption will not work.
Is there anybody can suggest me an available way to do big file
encryption and decryption with symmetric algorithm?
Any comments/suggestions will be welcome!
Best regards Gong
This should do what you want. Any questions just ask.
Chuck Wegrzyn
<blowfish.c>
______________________________________________________________________
OpenSSL Project http://www.openssl.org
User Support Mailing List openssl-users@openssl.org
Automated List Manager [EMAIL PROTECTED]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h> // flock
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "portable.h"
#include "exception.h"
#include "dir.h"
#include "ltscrypto.h"
#include "logger.h"
#include "crypto.h"
extern Exc_t enomore;
extern Exc_t ecrypto;
#ifndef CRYPT_BUFSIZE
#define CRYPT_BUFSIZE (1024)
#endif
typedef struct {
EVP_CIPHER_CTX ctx;
t_key_iv kiv;
int first;
} t_CONTEXT,*p_CONTEXT;
static void EncryptData(const EVP_CIPHER *cipher,int inFid, int outFid, char
*key, char *iv, const char *pTitle)
THROWS(efile)
THROWS(ecrypto)
{
unsigned char buffer[CRYPT_BUFSIZE],obuffer[2*CRYPT_BUFSIZE];
int oLen,iLen;
// Setup the crypto context...
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx,cipher, NULL, key,iv);
// Until we exhaust input file data...
for( ;1; )
{
// Set the buffer to zeros...
memset(buffer,0,sizeof(buffer));
// Read in some data. If it comes back 0, we are done.
iLen = read(inFid,buffer,sizeof(buffer));
if( 0 == iLen ) break;
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
// Encrypt it now.
if( 0 == EVP_EncryptUpdate(&ctx,obuffer,&oLen,buffer,iLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File write error
(%s)",pTitle,strerror(errno))); }
}
// Finish up taking whatever is left in the encryption system and writing
it out...
if( 0 == EVP_EncryptFinal_ex(&ctx,obuffer,&oLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File write error
(%s)",pTitle,strerror(errno))); }
// Cleanup..
EVP_CIPHER_CTX_cleanup(&ctx);
}
static void DecryptData(const EVP_CIPHER *cipher,int inFid, int outFid, char
*key, char *iv, const char *pTitle)
{
unsigned char buffer[CRYPT_BUFSIZE],obuffer[2*CRYPT_BUFSIZE];
int oLen,iLen;
// Initialize things.
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, cipher, NULL, key, iv);
// PRocess the file until we are done with it....
for( ;1; )
{
// Get some file input...
memset(buffer,0,sizeof(buffer));
iLen = read(inFid,buffer,sizeof(buffer));
// If there is no more, we are done.
if( 0 == iLen ) break;
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
// Decrypt it.
if( 0 == EVP_DecryptUpdate(&ctx,obuffer,&oLen,buffer,iLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
// Write things out...
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
}
// Collect the final amount and write it out.
if( 0 == EVP_DecryptFinal_ex(&ctx,obuffer,&oLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
// Cleanup
EVP_CIPHER_CTX_cleanup(&ctx);
}
/** \fn void *doInit(void *confHandle, int argc, char **argv)
* \brief Does nothing in this implementation.
* \param confHandle The conf instance pointer.
* \param argc The number of CLI arguments.
* \param argv An array of the CLI arguments.
* \return Return the init context, which is NULL in this routine.
*/
void *doInit(void *hConf,int argc,char **argv)
{
// Print out our version ID
loggerWrite(NULL,LOGGER_FAC_VERSION,LOGGER_PRI_NOTICE,"%s Version:
%s\n",__FILE__,VERSION);
// We do nothing!
return( 0 );
}
/** \fn int doCrypt(void *hHandle,e_OpType op,p_key_iv keyandiv,char
*infile,char *outfile)
* \brief This function generates crypto keys, encrypts or decrypts a file.
* \param hHandle Handle to thing returned from doInit().
* \param op The operation to be performed.
* \param keyandiv Pointer to structure holding key and iv data.
* \param infile Pointer to input file name, or NULL if not needed.
* \param outfile Pointer to buffer to hold output file name.
* \return If the op is GETKEYSIZE or GETIVSIZE, it returns the size.
Otherwise 0.
*
* Exceptions thrown efile, ememory.
*
*/
static void DoCrypto(const EVP_CIPHER *cipher,char *infile, char *outfile,
p_key_iv keyandiv, int bEncrypt, const char *pTitle)
{
int outFid = -1;
try
// Create the new output file ...
outFid = CreateCryptFile(outfile);
try
// Open the input file...
int inFid = open(infile,O_RDONLY);
if( -1 == inFid )
{ eraise2(efile, ("(%s) : Couldn't open file %s
(%s)",pTitle,infile,strerror(errno))); }
try
// Let others know that we are using the file.
if (flock(inFid,LOCK_SH) != 0)
{ eraise2(efile,("(%s) : Unable to lock input file %s
(%s)\n",pTitle,infile,strerror(errno))); }
try
// We now have an input and outfile ready to go. We might
need to generate crypto keys if we are
// encrypting the file.
if( bEncrypt )
{
// Now encrypt the file.
EncryptData(cipher,inFid,outFid,keyandiv->key,keyandiv->iv,pTitle);
}
else {
// This is a decryption so we are given the keys and
iv...
DecryptData(cipher,inFid,outFid,keyandiv->key,keyandiv->iv,pTitle);
}
finally
(void)flock(inFid,LOCK_UN);
end
finally
(void)close(inFid);
end
finally
(void)flock(outFid,LOCK_UN);
if (close(outFid) != 0)
{ eraise2(efile,("(%s) : Unable to close output file %s
(%s)\n",pTitle,outfile,strerror(errno))); }
end
except (enomoredir)
// Couldn't find a place for one...
eraise2(efile,("(%s) : Couldn't find a place to write the data
file.",pTitle));
end
}
static void FreeCtx(p_CONTEXT pCtx)
{
if( pCtx )
{
if( pCtx->kiv.key ) free( pCtx->kiv.key );
if( pCtx->kiv.iv ) free( pCtx->kiv.iv );
free( pCtx );
}
}
int doCrypt(void *hHandle,e_OpType op,void *kiv,void *infile,void *outfile)
{
// Figure out what operation the caller wants of us.
const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
const char *pCrypt = "3DES";
p_key_iv keyandiv = kiv;
p_CONTEXT pCtx,*pInd;
p_Buffer pIn,pOut;
switch(op)
{
case GENERATE:
// Generate the key and iv information for the caller.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
keyandiv->keysize = EVP_CIPHER_key_length(cipher);
keyandiv->ivsize = EVP_CIPHER_iv_length(cipher);
keyandiv->key = calloc(1,keyandiv->keysize);
keyandiv->iv = calloc(1,keyandiv->ivsize);
if( (0 == keyandiv->key) || (0 == keyandiv->iv) )
{
if( keyandiv->key ) free(keyandiv->key);
if( keyandiv->iv ) free(keyandiv->iv);
eraise2(ememory,("(%s) : Couldn't allocate
memory for key or initialization vector.",pCrypt));
}
GenerateCryptoKeys(keyandiv);
break;
case GETKEYSIZE:
// Returns the size of the encrypt/decrypt key.
return(EVP_CIPHER_key_length(cipher));
case GETIVSIZE:
// Return the size of the initialization vector.
return(EVP_CIPHER_iv_length(cipher));
case INITKIV:
// Return the sizes of things....
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
keyandiv->keysize = EVP_CIPHER_key_length(cipher);
keyandiv->ivsize = EVP_CIPHER_iv_length(cipher);
keyandiv->key = keyandiv->iv = NULL;
break;
case FILE_ENCRYPT:
// Encrypt the file data.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
if( NULL == infile ) { eraise2(eparam,("(%s) : Null input
file parameter.",pCrypt)); }
if( NULL == outfile ) { eraise2(eparam,("(%s) : Null output
file parameter.",pCrypt)); }
DoCrypto(cipher,infile,outfile,keyandiv,1,pCrypt);
break;
case FILE_DECRYPT:
// Decrypt the file.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
if( NULL == infile ) { eraise2(eparam,("(%s) : Null input
file parameter.",pCrypt)); }
if( NULL == outfile ) { eraise2(eparam,("(%s) : Null output
file parameter.",pCrypt)); }
DoCrypto(cipher,infile,outfile,keyandiv,0,pCrypt);
break;
case MEM_INIT:
// Init the buffer context information.
pCtx = calloc( 1,sizeof(t_CONTEXT));
if( NULL == pCtx ) { eraise2(ememory,("(%s) : Couldn't
allocate memory.",pCrypt)); }
EVP_CIPHER_CTX_init(&pCtx->ctx);
pCtx->first = 1;
// Figure out if we need to generate a key/iv pair or we
are given them.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
if( keyandiv->key && keyandiv->iv )
{
// We have them both, so we will set up things
now.
pCtx->kiv.keysize = keyandiv->keysize;
pCtx->kiv.ivsize = keyandiv->ivsize;
pCtx->kiv.key = calloc( 1,keyandiv->keysize );
if( NULL == pCtx->kiv.key ) { FreeCtx( pCtx );
eraise(ememory); }
memcpy(pCtx->kiv.key,keyandiv->key,keyandiv->keysize);
pCtx->kiv.iv = calloc( 1,keyandiv->ivsize );
if( NULL == pCtx->kiv.iv ) { FreeCtx(pCtx);
eraise(ememory); }
memcpy(pCtx->kiv.iv,keyandiv->iv,keyandiv->ivsize);
}
else if( (NULL == keyandiv->key) && (NULL == keyandiv->iv) )
{
// We have neither, so generate a key and
initialization vector.
doCrypt(hHandle,GENERATE,&pCtx->kiv,NULL,NULL);
}
else {
// parameter error!
eraise2(eparam,("(%s) : Key and iv must both be
null or not null.",pCrypt));
}
// Return the pointer to the caller.
pInd = infile;
*pInd = pCtx;
break;
case MEM_ENCRYPT:
// Encrypt a memory buffer.
pCtx = kiv;
if( 1 == pCtx->first )
{
if( 0 ==
EVP_EncryptInit_ex(&pCtx->ctx,cipher,NULL,pCtx->kiv.key,pCtx->kiv.iv) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
pCtx->first = 0;
}
// Do we have an input buffer? If so this is an update.
Otherwise it is a final!
if( NULL == outfile ) { eraise2(eparam,("(%s) : Output
buffer pointer is NULL.",pCrypt)); }
// This is an update...some input to process and output to
receive.
pIn = infile;
pOut = outfile;
if( infile )
{
// We are still adding to the input side...
if( 0 ==
EVP_EncryptUpdate(&pCtx->ctx,pOut->pBuffer,&pOut->size,pIn->pBuffer,pIn->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
else {
// This is a final! We will just collect
whatever is left over.
if( 0 ==
EVP_EncryptFinal_ex(&pCtx->ctx,pOut->pBuffer,&pOut->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
break;
case MEM_DECRYPT:
// Decreypt a memory buffer.
pCtx = kiv;
if( 1 == pCtx->first )
{
if( 0 ==
EVP_DecryptInit_ex(&pCtx->ctx,cipher,NULL,pCtx->kiv.key,pCtx->kiv.iv) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
pCtx->first = 0;
}
// Do we have an input buffer? If so this is an update.
Otherwise it is a final!
if( NULL == outfile ) { eraise2(eparam,("(%s) : Output
buffer pointer is NULL.",pCrypt)); }
// This is an update...some input to process and output to
receive.
pIn = infile;
pOut = outfile;
if( infile )
{
if( 0 ==
EVP_DecryptUpdate(&pCtx->ctx,pOut->pBuffer,&pOut->size,pIn->pBuffer,pIn->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
else {
// This is a final!
if( 0 ==
EVP_DecryptFinal_ex(&pCtx->ctx,pOut->pBuffer,&pOut->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
break;
case FREE_INIT:
// Free up the context.
pCtx = kiv;
if( NULL == pCtx ) { eraise2(eparam,("(%s) : Must provide
context pointer.",pCrypt)); }
if( 0 == EVP_CIPHER_CTX_cleanup(&pCtx->ctx) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
FreeCtx(pCtx);
break;
case FREE:
// Free up key and iv space.
if( keyandiv->key ) free( keyandiv->key );
if( keyandiv->iv ) free( keyandiv->iv );
break;
default:
// Garbage-in, garbage-out
break;
}
return(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h> // flock
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "portable.h"
#include "exception.h"
#include "dir.h"
#include "ltscrypto.h"
#include "logger.h"
#include "crypto.h"
extern Exc_t enomore;
extern Exc_t ecrypto;
#ifndef CRYPT_BUFSIZE
#define CRYPT_BUFSIZE (1024)
#endif
typedef struct {
EVP_CIPHER_CTX ctx;
t_key_iv kiv;
int first;
} t_CONTEXT,*p_CONTEXT;
static void EncryptData(const EVP_CIPHER *cipher,int inFid, int outFid, char
*key, char *iv, const char *pTitle)
THROWS(efile)
THROWS(ecrypto)
{
unsigned char buffer[CRYPT_BUFSIZE],obuffer[2*CRYPT_BUFSIZE];
int oLen,iLen;
// Setup the crypto context...
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_EncryptInit_ex(&ctx,cipher, NULL, key,iv);
// Until we exhaust input file data...
for( ;1; )
{
// Set the buffer to zeros...
memset(buffer,0,sizeof(buffer));
// Read in some data. If it comes back 0, we are done.
iLen = read(inFid,buffer,sizeof(buffer));
if( 0 == iLen ) break;
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
// Encrypt it now.
if( 0 == EVP_EncryptUpdate(&ctx,obuffer,&oLen,buffer,iLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File write error
(%s)",pTitle,strerror(errno))); }
}
// Finish up taking whatever is left in the encryption system and writing
it out...
if( 0 == EVP_EncryptFinal_ex(&ctx,obuffer,&oLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File write error
(%s)",pTitle,strerror(errno))); }
// Cleanup..
EVP_CIPHER_CTX_cleanup(&ctx);
}
static void DecryptData(const EVP_CIPHER *cipher,int inFid, int outFid, char
*key, char *iv, const char *pTitle)
{
unsigned char buffer[CRYPT_BUFSIZE],obuffer[2*CRYPT_BUFSIZE];
int oLen,iLen;
// Initialize things.
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX_init(&ctx);
EVP_DecryptInit_ex(&ctx, cipher, NULL, key, iv);
// PRocess the file until we are done with it....
for( ;1; )
{
// Get some file input...
memset(buffer,0,sizeof(buffer));
iLen = read(inFid,buffer,sizeof(buffer));
// If there is no more, we are done.
if( 0 == iLen ) break;
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
// Decrypt it.
if( 0 == EVP_DecryptUpdate(&ctx,obuffer,&oLen,buffer,iLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
// Write things out...
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
}
// Collect the final amount and write it out.
if( 0 == EVP_DecryptFinal_ex(&ctx,obuffer,&oLen) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
iLen = write(outFid,obuffer,oLen);
if( -1 == iLen ) { eraise2(efile, ("(%s) : File read error
(%s)",pTitle,strerror(errno))); }
// Cleanup
EVP_CIPHER_CTX_cleanup(&ctx);
}
/** \fn void *doInit(void *confHandle, int argc, char **argv)
* \brief Does nothing in this implementation.
* \param confHandle The conf instance pointer.
* \param argc The number of CLI arguments.
* \param argv An array of the CLI arguments.
* \return Return the init context, which is NULL in this routine.
*/
void *doInit(void *hConf,int argc,char **argv)
{
// Print out our version ID
loggerWrite(NULL,LOGGER_FAC_VERSION,LOGGER_PRI_NOTICE,"%s Version:
%s\n",__FILE__,VERSION);
// We do nothing!
return( 0 );
}
/** \fn int doCrypt(void *hHandle,e_OpType op,p_key_iv keyandiv,char
*infile,char *outfile)
* \brief This function generates crypto keys, encrypts or decrypts a file.
* \param hHandle Handle to thing returned from doInit().
* \param op The operation to be performed.
* \param keyandiv Pointer to structure holding key and iv data.
* \param infile Pointer to input file name, or NULL if not needed.
* \param outfile Pointer to buffer to hold output file name.
* \return If the op is GETKEYSIZE or GETIVSIZE, it returns the size.
Otherwise 0.
*
* Exceptions thrown efile, ememory.
*
*/
static void DoCrypto(const EVP_CIPHER *cipher,char *infile, char *outfile,
p_key_iv keyandiv, int bEncrypt, const char *pTitle)
{
int outFid = -1;
try
// Create the new output file ...
outFid = CreateCryptFile(outfile);
try
// Open the input file...
int inFid = open(infile,O_RDONLY);
if( -1 == inFid )
{ eraise2(efile, ("(%s) : Couldn't open file %s
(%s)",pTitle,infile,strerror(errno))); }
try
// Let others know that we are using the file.
if (flock(inFid,LOCK_SH) != 0)
{ eraise2(efile,("(%s) : Unable to lock input file %s
(%s)\n",pTitle,infile,strerror(errno))); }
try
// We now have an input and outfile ready to go. We might
need to generate crypto keys if we are
// encrypting the file.
if( bEncrypt )
{
// Now encrypt the file.
EncryptData(cipher,inFid,outFid,keyandiv->key,keyandiv->iv,pTitle);
}
else {
// This is a decryption so we are given the keys and
iv...
DecryptData(cipher,inFid,outFid,keyandiv->key,keyandiv->iv,pTitle);
}
finally
(void)flock(inFid,LOCK_UN);
end
finally
(void)close(inFid);
end
finally
(void)flock(outFid,LOCK_UN);
if (close(outFid) != 0)
{ eraise2(efile,("(%s) : Unable to close output file %s
(%s)\n",pTitle,outfile,strerror(errno))); }
end
except (enomoredir)
// Couldn't find a place for one...
eraise2(efile,("(%s) : Couldn't find a place to write the data
file.",pTitle));
end
}
static void FreeCtx(p_CONTEXT pCtx)
{
if( pCtx )
{
if( pCtx->kiv.key ) free( pCtx->kiv.key );
if( pCtx->kiv.iv ) free( pCtx->kiv.iv );
free( pCtx );
}
}
int doCrypt(void *hHandle,e_OpType op,void *kiv,void *infile,void *outfile)
{
// Figure out what operation the caller wants of us.
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
const char *pCrypt = "AES";
p_key_iv keyandiv = kiv;
p_CONTEXT pCtx,*pInd;
p_Buffer pIn,pOut;
switch(op)
{
case GENERATE:
// Generate the key and iv information for the caller.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
keyandiv->keysize = EVP_CIPHER_key_length(cipher);
keyandiv->ivsize = EVP_CIPHER_iv_length(cipher);
keyandiv->key = calloc(1,keyandiv->keysize);
keyandiv->iv = calloc(1,keyandiv->ivsize);
if( (0 == keyandiv->key) || (0 == keyandiv->iv) )
{
if( keyandiv->key ) free(keyandiv->key);
if( keyandiv->iv ) free(keyandiv->iv);
eraise2(ememory,("(%s) : Couldn't allocate
memory for key or initialization vector.",pCrypt));
}
GenerateCryptoKeys(keyandiv);
break;
case GETKEYSIZE:
// Returns the size of the encrypt/decrypt key.
return(EVP_CIPHER_key_length(cipher));
case GETIVSIZE:
// Return the size of the initialization vector.
return(EVP_CIPHER_iv_length(cipher));
case INITKIV:
// Return the sizes of things....
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
keyandiv->keysize = EVP_CIPHER_key_length(cipher);
keyandiv->ivsize = EVP_CIPHER_iv_length(cipher);
keyandiv->key = keyandiv->iv = NULL;
break;
case FILE_ENCRYPT:
// Encrypt the file data.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
if( NULL == infile ) { eraise2(eparam,("(%s) : Null input
file parameter.",pCrypt)); }
if( NULL == outfile ) { eraise2(eparam,("(%s) : Null output
file parameter.",pCrypt)); }
DoCrypto(cipher,infile,outfile,keyandiv,1,pCrypt);
break;
case FILE_DECRYPT:
// Decrypt the file.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
if( NULL == infile ) { eraise2(eparam,("(%s) : Null input
file parameter.",pCrypt)); }
if( NULL == outfile ) { eraise2(eparam,("(%s) : Null output
file parameter.",pCrypt)); }
DoCrypto(cipher,infile,outfile,keyandiv,0,pCrypt);
break;
case MEM_INIT:
// Init the buffer context information.
pCtx = calloc( 1,sizeof(t_CONTEXT));
if( NULL == pCtx ) { eraise2(ememory,("(%s) : Couldn't
allocate memory.",pCrypt)); }
EVP_CIPHER_CTX_init(&pCtx->ctx);
pCtx->first = 1;
// Figure out if we need to generate a key/iv pair or we
are given them.
if( NULL == keyandiv ) { eraise2(eparam,("(%s) : Null
p_key_iv parameter.",pCrypt)); }
if( keyandiv->key && keyandiv->iv )
{
// We have them both, so we will set up things
now.
pCtx->kiv.keysize = keyandiv->keysize;
pCtx->kiv.ivsize = keyandiv->ivsize;
pCtx->kiv.key = calloc( 1,keyandiv->keysize );
if( NULL == pCtx->kiv.key ) { FreeCtx( pCtx );
eraise(ememory); }
memcpy(pCtx->kiv.key,keyandiv->key,keyandiv->keysize);
pCtx->kiv.iv = calloc( 1,keyandiv->ivsize );
if( NULL == pCtx->kiv.iv ) { FreeCtx(pCtx);
eraise(ememory); }
memcpy(pCtx->kiv.iv,keyandiv->iv,keyandiv->ivsize);
}
else if( (NULL == keyandiv->key) && (NULL == keyandiv->iv) )
{
// We have neither, so generate a key and
initialization vector.
doCrypt(hHandle,GENERATE,&pCtx->kiv,NULL,NULL);
}
else {
// parameter error!
eraise2(eparam,("(%s) : Key and iv must both be
null or not null.",pCrypt));
}
// Return the pointer to the caller.
pInd = infile;
*pInd = pCtx;
break;
case MEM_ENCRYPT:
// Encrypt a memory buffer.
pCtx = kiv;
if( 1 == pCtx->first )
{
if( 0 ==
EVP_EncryptInit_ex(&pCtx->ctx,cipher,NULL,pCtx->kiv.key,pCtx->kiv.iv) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
pCtx->first = 0;
}
// Do we have an input buffer? If so this is an update.
Otherwise it is a final!
if( NULL == outfile ) { eraise2(eparam,("(%s) : Output
buffer pointer is NULL.",pCrypt)); }
// This is an update...some input to process and output to
receive.
pIn = infile;
pOut = outfile;
if( infile )
{
// We are still adding to the input side...
if( 0 ==
EVP_EncryptUpdate(&pCtx->ctx,pOut->pBuffer,&pOut->size,pIn->pBuffer,pIn->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
else {
// This is a final! We will just collect
whatever is left over.
if( 0 ==
EVP_EncryptFinal_ex(&pCtx->ctx,pOut->pBuffer,&pOut->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
break;
case MEM_DECRYPT:
// Decreypt a memory buffer.
pCtx = kiv;
if( 1 == pCtx->first )
{
if( 0 ==
EVP_DecryptInit_ex(&pCtx->ctx,cipher,NULL,pCtx->kiv.key,pCtx->kiv.iv) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
pCtx->first = 0;
}
// Do we have an input buffer? If so this is an update.
Otherwise it is a final!
if( NULL == outfile ) { eraise2(eparam,("(%s) : Output
buffer pointer is NULL.",pCrypt)); }
// This is an update...some input to process and output to
receive.
pIn = infile;
pOut = outfile;
if( infile )
{
if( 0 ==
EVP_DecryptUpdate(&pCtx->ctx,pOut->pBuffer,&pOut->size,pIn->pBuffer,pIn->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
else {
// This is a final!
if( 0 ==
EVP_DecryptFinal_ex(&pCtx->ctx,pOut->pBuffer,&pOut->size) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
}
break;
case FREE_INIT:
// Free up the context.
pCtx = kiv;
if( NULL == pCtx ) { eraise2(eparam,("(%s) : Must provide
context pointer.",pCrypt)); }
if( 0 == EVP_CIPHER_CTX_cleanup(&pCtx->ctx) )
{
unsigned long int x = ERR_get_error();
char szBuff[256];
ERR_error_string_n(x,szBuff,sizeof(szBuff));
eraise2(ecrypto,(szBuff));
}
FreeCtx(pCtx);
break;
case FREE:
// Free up key and iv space.
if( keyandiv->key ) free( keyandiv->key );
if( keyandiv->iv ) free( keyandiv->iv );
break;
default:
// Garbage-in, garbage-out
break;
}
return(0);
}