[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


===========================================================================================
The privileged confidential information contained in this email is intended for 
use only by the addressees as indicated by the original sender of this email. 
If you are not the addressee indicated in this email or are not responsible for 
delivery of the email to such  a person, please kindly reply to the sender 
indicating this fact and delete all copies of it from your computer and network 
server immediately. Your cooperation is highly appreciated. It is advised that 
any unauthorized use of confidential information of Winbond is strictly 
prohibited; and any information in this email irrelevant to the official 
business of Winbond shall be deemed as neither given nor endorsed by Winbond.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

This should do what you want. Any questions just ask.

Chuck Wegrzyn

/** \file blowfish.c
 *  \brief Provides encryption/decryption services for the Blowfish algorithm.
 */

#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_bf_cbc();
    const char *pCrypt = "Blowfish";
    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