> 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