I copied the do_crypt routine (General encryption, decryption function example using FILE I/O and RC2 with an 80 bit key) from the EVP_EncryptInit(3) man page and used it to encrypt a 433282 byte file.   Function EVP_CipherFinal_ex fails and ERR_get_error returns `error:0606506D:lib(6):func(101):reason(109)', i.e. WRONG FINAL BLOCK LENGTH.  ctx.buf_len has a value of 2.  I thought EVP_CipherFinal_ex would pad the extra bytes and encrypt them.  
I get and out file of 433280 bytes, which using, the same routine to decode, results in a  433288 byte file.  i.e. the last two bytes of the orinigal file vanish and 8 bytes of garbage get appended.  Clearly I have misunderstood something.  Please help.  

Here is the code.
I inserted unsigned char before inbuf[1024] and the lines:
     char *errorString = ERR_error_string(ERR_get_error(),0);
  printf ("Error check> %s <\n", errorString);
  printf("number we have left: %d\n", ctx.buf_len);

after
  if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
Douglas Laing - Johannesburg

 


/* General encryption, decryption function example using FILE I/O and RC2
   with an 80 bit key */

#include <openssl/evp.h>
int do_crypt(FILE *in, FILE *out, int do_encrypt)
               {
               /* Allow enough space in output buffer for additional block */
               unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
               int inlen, outlen;
               /* Bogus key and IV: we’d normally set these from
                * another source.
                */
               unsigned char key[] = "0123456789";
               unsigned char iv[] = "12345678";
               EVP_CIPHER_CTX ctx;

/* Don’t set key or IV because we will modify the parameters */
               EVP_CIPHER_CTX_init(&ctx);
/* int EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);   &ctx
   initializes cipher contex ctx. */

               EVP_CipherInit_ex(&ctx, EVP_rc2_cbc(), NULL, NULL, NULL, do_encrypt);
/* int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,    &ctx
                         const EVP_CIPHER *type, EVP_rc2_cbc()
                         ENGINE *impl,           NULL
                         unsigned char *key,     NULL
                         unsigned char *iv,      NULL
                         int enc);               do_encryp
   EVP_CipherInit_ex(), EVP_CipherUpdate() and EVP_CipherFinal_ex() are
   functions that can be used for decryption or encryption. The operation
   performed depends on the value of the enc parameter. It should be set
   to 1 for encryption, 0 for decryption and -1 to leave the value
   unchanged (the actual value of ’enc’ being supplied in a previous
   call). */

               EVP_CIPHER_CTX_set_key_length(&ctx, 10);
/* sets the key length of the cipher ctx.
   If the cipher is a fixed length cipher then attempting to set the key
   length to any value other than the fixed value is an error. */

/* We finished modifying parameters so now we can set key and IV */
               EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, do_encrypt);
/* int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,    &ctx
                         const EVP_CIPHER *type, NULL,
                         ENGINE *impl,           NULL
                         unsigned char *key,     key
                         unsigned char *iv,      iv
                         int enc);               do_encryp       */

               for(;;)
                       {
                       inlen = fread(inbuf, 1, 1024, in);
                       if(inlen <= 0) break;
                       if(!EVP_CipherUpdate(&ctx, outbuf, &outlen, inbuf, inlen))
/* int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx,   &ctx
                        unsigned char *out,    outbuf
                        int *outl,             &outlen
                        unsigned char *in,     inbuf
                        int inl);              inlen         */

                               {
                               /* Error */
                               return 0;
                               }
                       fwrite(outbuf, 1, outlen, out);
                       }
               if(!EVP_CipherFinal_ex(&ctx, outbuf, &outlen))
/* If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
   the "final" data, that is any data that remains in a partial block.  It
   uses standard block padding (aka PKCS padding). The encrypted final
   data is written to out which should have sufficient space for one
   cipher block. The number of bytes written is placed in outl. After this
   function is called the encryption operation is finished and no further
   calls to EVP_EncryptUpdate() should be made. */

                       {
                       /* Error */
                       char *errorString = ERR_error_string(ERR_get_error(),0);
                       printf ("Error check> %s <\n", errorString);
                       printf("number we have left: %d\n", ctx.buf_len);
                       return 0;
                       }
               fwrite(outbuf, 1, outlen, out);

               EVP_CIPHER_CTX_cleanup(&ctx);
/* clears all information from a cipher context
   and free up any allocated memory associate with it. It should be called
   after all operations using a cipher are complete so sensitive informa-
   tion does not remain in memory. */

               return 1;
               }

Reply via email to