>       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 keeps 
track of the length so the decryptor knows the length. For 
different ways of sending and storing the ways are different.
        
>       I can already see that if I use len= strlen(ciphertext) gives me 
> a wrong answer and sizeof parameter is also not the one as it returns 4.

Yes to the first; in your code ciphertext is a pointer 
(which you point to malloc'ed space) and sizeof a pointer 
is the size of the pointer NOT the size of the memory 
pointed to. On most systems today all pointers are size 4.
If you know in advance the size of the data to be encrypted, 
you can make ciphertext an array that is the correct size, 
and sizeof an array is the size of the array.* 

Note however if you make the array "at least big enough", 
then sizeof is the size of the array but NOT necessarily 
the length of the ciphertext *in* the array.
        
If you think (or have been told) in C arrays and pointers 
are "the same", they ARE NOT. This is a common mistake.
See http://c-faq.com section 6.

(* But if you write array *syntax* for a parameter, like 
void foo (int x [10]) ..., it is NOT an array, it is a 
pointer, and sizeof accordingly gives the pointer size.)



______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to