RE: EVP_Decrypt function- AES cbc 128 bit mode- Input length?

2011-04-21 Thread Dave Thompson
   From: owner-openssl-us...@openssl.org On Behalf Of tera tellence
   Sent: Wednesday, 20 April, 2011 09:15

   I am trying in vain to find out why the AES decrypt won't work here.

   I have found where exactly is the problem  and now looking for 
 some wise-crack to help me solve it.

Small preliminary point not related to the actual question:
'wise-crack' in English means a joke, usually a hurtful one.
And worse, in US English at least 'wise-guy' has become 
slang for a member of organized crime, or mafia. 
You want some wise person or just somebody.

snip much of code to leave relevant parts

   cipher_type = EVP_aes_128_cbc();
   EVP_EncryptInit_ex(en, cipher_type, NULL, passkey, passiv);
   EVP_DecryptInit_ex(de, cipher_type, NULL, passkey, passiv);

   olen = len = strlen(input)+1;
 int c_len = len + AES_BLOCK_SIZE - 1;
 int f_len = 0;
 ciphertext = (unsigned char *)malloc(c_len);

 if(!EVP_EncryptInit_ex(en, NULL, NULL, NULL, NULL)){
   printf(ERROR in EVP_EncryptInit_ex \n);
   return NULL;
 }

A general comment: whenever you get an error return from EVP, 
and most other OpenSSL routines, you should look at the error stack, 
like you did for DecryptFinal with ERR_print_errors_fp(stderr). 

Also, NULL isn't safe as a return value of main().
NULL is just 0 in some cases but (void*)0 in others 
(the C standard allows either) and the latter is illegal.
And here it's semantically incorrect also; exit 0 
normally means 'success' and this is not a success case.
On some systems (including Unix and Windows) you can return 
a small integer (up to 99 at least) to indicate the level 
and/or type of problem. On all C systems you can return 
at least EXIT_SUCCESS or EXIT_FAILURE from stdlib.h.

 if(!EVP_EncryptUpdate(en, ciphertext, c_len, plain,
len)){
   printf(ERROR in EVP_EncryptUpdate \n);
   return NULL;
 }
 printf(len value after update \%d\\n, len);
// printf(size of ciphertext after update \%d\\n,
sizeof(ciphertext));
 printf(strlen value of ciphertext after update \%d\\n,
strlen(ciphertext));
 if(!EVP_EncryptFinal_ex(en, ciphertext+c_len, f_len)){
   printf(ERROR in EVP_EncryptFinal_ex \n);
   return NULL;
 }
 printf(len value  after final \%d\\n, len);

C is call by value, so len can never be changed by those calls.
You might want to look instead at c_len and f_len which can be, 
and in fact are set except possibly for errors.

 printf(strlen value of ciphertext after final \%d\\n,
strlen(ciphertext));
 EVP_CIPHER_CTX_cleanup(en);

   len = c_len + f_len;
   printf(len value after aes_encrypt \%d\\n, len);

   //HERE IS THE PROBLEM: IF I USE len= strlen(ciphertext) I GET
ERROR
   //len = strlen(ciphertext);

encrypted data (ciphertext) is binary. It can and usually does 
include the null byte that terminates a C string, so strlen() 
computes the WRONG length. Using the wrong length is an error.
You need to use the length(s) returned by the EVP_Encrypt routines, 
which in this simple case is exactly c_len + f_len.

Specifically, the/each EncryptUpdate call may produce *some* 
of the ciphertext and store the length in the output argument.
EncryptFinal will produce the *rest* (normally one block) 
and store that length in the output argument. That's why you 
provide ciphertext+c_len as the buffer to EncryptFinal, 
so it puts its ciphertext after any from EncryptUpdate.

snip more

   What I dont understand:

   What should I feed as the len parameter for the openSSL EVP
Decrypt routines?

The correct length of the ciphertext, in your case c_len+f_len.

   what is this magic len = c_len+ f_len?

See above.


   How should I get this in case I am given just the cipher 
 with the key and the iv? This should be always possible right? 
 I know strlen is a bad parametr especially for binary as the 
 ciphertext input to EVP Decrypt is binary: so how should I get this?

I don't know what your question is. To decrypt (for CBC) you need 
the key which is 16 octets for AES-128, the IV which is 16 octets 
for AES-anything, and the ciphertext whose length depends on the 
data that was encrypted and therefore generally you must keep 
track of (but will always be a multiple of 16 octets).

If you simply encrypt and then decrypt in one process, 
it's easy to keep track of. But this is basically useless.
Normally you want to encrypt data to be sent to another system, 
program, or person; or stored for later retrieval. In these 
cases, you must send or store it in some fashion that 

EVP_Decrypt function- AES cbc 128 bit mode- Input length?

2011-04-20 Thread tera tellence
Hi All,



I am trying in vain to find out why the AES decrypt won't work here.
I have found where exactly is the problem  and now looking for some
wise-crack to help me solve it.

Here is the code that I tested with(from various posts here):

#include string.h
#include stdio.h
#include stdlib.h
#include openssl/evp.h

int AES_BLOCK_SIZE = 128;

int main(int argc, char **argv)
{

  EVP_CIPHER_CTX en;
  EVP_CIPHER_CTX de;
  EVP_CIPHER_CTX_init(en);
  EVP_CIPHER_CTX_init(de);
  const EVP_CIPHER *cipher_type;
  unsigned char *passkey, *passiv, *plaintxt;
  char *plain;
  char *plaintext;
  unsigned char *ciphertext;
  int olen, len;
  int i =0;

  unsigned char iv[]  =  { 0x00, 0x01, 0x02, 0x03,
  0x04, 0x05, 0x06, 0x07,
  0x08, 0x09, 0x0a, 0x0b,
  0x0c, 0x0d, 0x0e, 0x0f,  0 };

  unsigned char key[]=  { 0x2b, 0x7e, 0x15, 0x16,
  0x28, 0xae, 0xd2, 0xa6,
  0xab, 0xf7, 0x15, 0x88,
  0x09, 0xcf, 0x4f, 0x3c , 0 };
 unsigned char *input = hi this is patrick immling\n'Doctor'.\n'Doctor'
who ?\nPrecisely! 123910!§$$§% !%%$$(/=))?=(#ü++Ü**,.here we go sometimes
it i s difficult but 187! 1$5 78@2 14.TӒ��틪�ձ1z.$�?�U���y;

printf(AES ALGORITHM FOR 128 bit CBC MODE\n);
cipher_type = EVP_aes_128_cbc();
AES_BLOCK_SIZE = 128;
passkey = key;
passiv = iv;
plain = input;


printf(Initializing AES ALGORITHM FOR CBC MODE..\n);

EVP_EncryptInit_ex(en, cipher_type, NULL, passkey, passiv);


EVP_DecryptInit_ex(de, cipher_type, NULL, passkey, passiv);

olen = len = strlen(input)+1;
printf(len value before aes_encrypt \%d\\n, len);


  int c_len = len + AES_BLOCK_SIZE - 1;
  int f_len = 0;
  ciphertext = (unsigned char *)malloc(c_len);


  if(!EVP_EncryptInit_ex(en, NULL, NULL, NULL, NULL)){
printf(ERROR in EVP_EncryptInit_ex \n);
return NULL;
  }

  if(!EVP_EncryptUpdate(en, ciphertext, c_len, plain, len)){
printf(ERROR in EVP_EncryptUpdate \n);
return NULL;
  }
  printf(len value after update \%d\\n, len);
 // printf(size of ciphertext after update \%d\\n,
sizeof(ciphertext));
  printf(strlen value of ciphertext after update \%d\\n,
strlen(ciphertext));

  if(!EVP_EncryptFinal_ex(en, ciphertext+c_len, f_len)){
printf(ERROR in EVP_EncryptFinal_ex \n);
return NULL;
  }
  printf(len value  after final \%d\\n, len);
  printf(strlen value of ciphertext after final \%d\\n,
strlen(ciphertext));
  EVP_CIPHER_CTX_cleanup(en);

len = c_len + f_len;
printf(len value after aes_encrypt \%d\\n, len);

//HERE IS THE PROBLEM: IF I USE len= strlen(ciphertext) I GET ERROR
//len = strlen(ciphertext);

printf(strlen value of ciphertext after aes_encrypt \%d\\n,
len);

  int p_len = len;
   f_len = 0;
   plaintext = (unsigned char *)malloc(p_len);
  // memset(plaintext,0,sizeof(plaintext));
  if(!EVP_DecryptInit_ex(de, NULL, NULL, NULL, NULL)){
printf(ERROR in EVP_DecryptInit_ex \n);
return NULL;
  }
  EVP_CIPHER_CTX_set_padding(de, 0);

  if(!EVP_DecryptUpdate(de, plaintext, p_len, ciphertext, len)){
printf(ERROR in EVP_DecryptUpdate\n);
return NULL;
  }
  printf(len value after decrypt update \%d\\n, len);
  if(!EVP_DecryptFinal_ex(de, plaintext+p_len, f_len)){
printf(ERROR in EVP_DecryptFinal_ex\n);
ERR_print_errors_fp(stderr);
return NULL;
  }

  EVP_CIPHER_CTX_cleanup(de);
  len = p_len + f_len;
  printf(Decrypted value = %s\n, plaintext);

printf(len value after aes_decrypt \%d\\n, len);


if (strncmp(plaintext, input, olen))
  printf(FAIL: enc/dec failed for \%s\\n, input);
else
  printf(OK: enc/dec ok for \%s\\n, plaintext); // \%s\\n
  printf(\n);

   free(ciphertext);
   free(plaintext);

  return 0;
}

What I dont understand:

What should I feed as the len parameter for the openSSL EVP Decrypt
routines?
what is this magic len = c_len+ f_len?

How should I get this in case I am given just the cipher with the key and
the iv? This should be always possible right? I know strlen is a bad
parametr especially for binary as the ciphertext input to EVP Decrypt is
binary: so how should I get this?

I can already see that if I use len= strlen(ciphertext) gives me a wrong
answer and sizeof parameter is also not