• Advertisement
Sign in to follow this  

OpenSSL BIO_* Bug?

This topic is 1646 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So, I'm having a really weird issue... i'm trying simple file encryption/decryption with BIO_*, but if the encrypted file is in a subdirectory.. i get garbage data,

 
I'll post the code i'm using, with a brief elaboration on how i'm using it and what behaviour i'm getting:
 
/*
  Example of ssl read and write to a file

  gcc ssl_write_read.c -lssl
  ./a.out


*/



#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>

int read_whole_file( char* filename, char** data ){
	FILE* file = fopen( filename, "rb" );
	fseek( file, 0, SEEK_END );
	long fileSize = ftell( file );
	rewind( file );
	*data = malloc( fileSize );
	fread( *data, fileSize, 1, file );
	fclose( file );
	return fileSize;
}
void encrypt_file( char* filename ){
	char new_filename[strlen( filename ) + 5];
	strcpy( new_filename, filename );
	strcat( new_filename, ".enc" );
	char* data;
	int fileSize = read_whole_file( filename, &data );
	write_data( new_filename, data, fileSize, (unsigned char*)"mykey" );
	free( data );
}

int write_data(const char *filename, char *out, int len, unsigned char *key)
{
  int total, written;
  BIO *cipher, *buffer, *file;
 
  /* Create a buffered file BIO for writing */
  file = BIO_new_file(filename, "wb");
  if (!file)
    return 0;
 
  /* Create a buffering filter BIO to buffer writes to the file */
  buffer = BIO_new(BIO_f_buffer(  ));
 
  /* Create a base64 encoding filter BIO */
//  b64 = BIO_new(BIO_f_base64(  ));
 
  /* Create the cipher filter BIO and set the key.  The last parameter of
     BIO_set_cipher is 1 for encryption and 0 for decryption */
  cipher = BIO_new(BIO_f_cipher(  ));
  BIO_set_cipher(cipher, EVP_des_ede3_cbc(  ), key, NULL, 1);
 
  /* Assemble the BIO chain to be in the order cipher-b64-buffer-file */
//  BIO_push(cipher, b64);
//  BIO_push(b64, buffer);
BIO_push(cipher,buffer);
  BIO_push(buffer, file);

  /* This loop writes the data to the file.  It checks for errors as if the
     underlying file were non-blocking */
  for (total = 0;  total < len;  total += written)
    {
      if ((written = BIO_write(cipher, out + total, len - total)) <= 0)
        {
	  if (BIO_should_retry(cipher))
            {
	      written = 0;
	      continue;
            }
	  break;
        }
    }
 
  /* Ensure all of our data is pushed all the way to the file */
  BIO_flush(cipher);
 
  BIO_free_all(cipher);
}

BIO* decrypt_open( const char *filename, unsigned char *key ){
  int total, written;
  BIO *cipher, *buffer, *file;
  //char *b = malloc(len);
 
  /* Create a buffered file BIO for reading */
  file = BIO_new_file(filename, "rb");
  if (!file)
    return 0;
 
  /* Create a buffering filter BIO to buffer writes to the file */
  buffer = BIO_new(BIO_f_buffer(  ));
 
  /* Create a base64 encoding filter BIO */
//  b64 = BIO_new(BIO_f_base64(  ));
 
  /* Create the cipher filter BIO and set the key.  The last parameter of
     BIO_set_cipher is 1 for encryption and 0 for decryption */
  cipher = BIO_new(BIO_f_cipher(  ));
  BIO_set_cipher(cipher, EVP_des_ede3_cbc(  ), key, NULL, 0);
 
  /* Assemble the BIO chain to be in the order cipher-b64-buffer-file */
//  BIO_push(cipher, b64);
//  BIO_push(b64, buffer);
BIO_push(cipher,buffer);
  BIO_push(buffer, file);
  return cipher;
}
char* decrypt_read( BIO* cipher, int len, char* b ){
  int total, written;

//	char b[len + 1];
  for (total = 0;  total < len;  total += written)
    {
      if ((written = BIO_read(cipher, b, len - total)) <= 0)
        {
	  if (BIO_should_retry(cipher))
            {
	      written = 0;
	      continue;
            }
	  break;
        }
    }
 
  b[total] = '\0';
  
  return b;
}

int main(void)
{
//chdir("subdirectory");
	char *file_="test.txt";
	char* data = "howdy\n";
	write_data( file_, data, strlen(data), "mykey");

	BIO* cipher = decrypt_open( file_, (unsigned char*)"mykey" );
	char b[999999];
	decrypt_read( cipher, 999999, b );
		BIO_flush( cipher );
	BIO_free_all( cipher );
	printf(">%s\n",b);

//char* test="plain.txt";
//encrypt_file(test);

}
 
1. So, first run creates and writes encrypted file "test.txt" and then decrypts and prints out the contents, "howdy",
 
2. Now, comment out line 141 // write_data( ... re-run to verify "howdy", works fine
 
3. make directory "temp", move "test.txt" into "temp" and change line 139 to reflect that: char *file_="temp/test.txt";.. re-run - I get no results ??
 
4. Even more weird: change line 139 back to just "test.txt", and replace file_ on line 143 with "temp/test.txt" ... so it reads: BIO* cipher = decrypt_open( "temp/test.txt", (unsigned char*)"mykey" ); // re-run... now it works again all of a sudden. BUT - if you comment out line 139 // char *file_="test.txt";.... then it doesn't work again? Even though *file_ isn't being used??? 

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement