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);
}

Reply via email to