(Top-posting since this mail is not a direct reply)

Hi Ger,

Thanks for leading me in the right direction. The problem is solved. It was
my silly mistake.

Actually, my main build was also linking with another library that in turn
was linking with openssl. This is a 3rd party library, and I did not know
that it indeed had openssl symbols.

Linking:
g++ -o output.bin appssl.o /dir/libssl.a
/dir/libcrypto.a -L/dir/lib -laccess

The above linking is correct. It statically links the ssl and crypto
library, and shared links with a library called libaccess. Now, this library
also has openssl symbols, which I checked by doing "nm". If I link both of
these in a shared library manner (-l), then there is symbols conflict, and
so it deos not work according to expectation. Now, with static linkage, it
works.

Thanks!



-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] Behalf Of Ger Hobbelt
Sent: Thursday, August 14, 2008 8:33 PM
To: openssl-users@openssl.org
Subject: Re: EVP_CipherInit_ex because cipher->do_cipher is NULL


On Thu, Aug 14, 2008 at 3:30 PM, Ambarish Mitra
<[EMAIL PROTECTED]> wrote:
> ------------
> AM: Either the corruption happens in this call, or in the preceeding
> EVP_CIPHER_CTX_init call.
> ------------

Since the assert() already fails before the init_ex call, it looks
like my guess is probably correct: the point in my last email is that
the 'cipher' struct must already be incorrect /some time before/ the
init_ex() call. In other words: the error is not in the init_ex() call
(thast's why I said I was barking up the wrong tree) but in the code
that precedes it. I do not know where the 'cipher' variable starts
it's life in your code, but right when it starts, I would put the
first
  assert(cipher->ctrl != NULL)
check. If THAT assert() fails (which I expect it will), it means the
OpenSSL internal (constant!) data pointed at by the EVP_des_ede3_cbc()
gets corrupted permanently even earlier. Which is why I said you might
want to (a) use a debugger which can break on data change -- so you
can detect which bit of code is changing the 'ctrl' pointer value --
or use the global var + assert() set as described lateron in my last
email.

I am fairly certain now that we are looking at some sort of memory
corruption issue - and the trouble is locating where that corruption
is caused. One thing I am willing to bet on by now: the corruption
will have taken place before you reach that last
EVP_CipherInit_ex(...,cipher,...) call and my guess is that it already
happened /before/ your last call to EVP_des_ede3_cbc() as well.


> ---------
> AM: I am on OpenSSL 0.9.8h 28 May 2008. So, reasonably recent.
> ---------

Good. Shouldn't be too different then when you look at the source code
of OpenSSL itself.

> ------
> AM: This is now very clear. Thanks for explaining how the function is
being
> defined.
> Initial doubts on this function is gone.
> -------

Excellent. You have a type of bug which (IMO) requires the ability to
see what's going on under the hood as well; not because OpenSSL is at
fault (my guess it's something hidden in your application code, but we
need to check further to find out who and where exactly).



> typedef int dbg_ctrl_func_t(EVP_CIPHER_CTX *, int, int, void *);
[...]
> ----------
> AM: error: cannot convert `int (* const*)(EVP_CIPHER_CTX*, int, int,
>   void*)' to `int (*)(EVP_CIPHER_CTX*, int, int, void*)' in assignment

My mistake. Make sure the typedef matches the type for the 'ctrl'
member in the 'cipher' struct type exactly. I forgot one level of
indirection ('*'), hence the error.

What the global var should store is a pointer to the DATA space of
'EVP_des_ede3_cbc()->ctrl', i.e. the bytes which store the value in
'EVP_des_ede3_cbc()->ctrl'.
When that value changes, it means someone/something just assigned a
new value to 'EVP_des_ede3_cbc()->ctrl' and THAT is wrong (as
'EVP_des_ede3_cbc()->ctrl' is a constant value, which is set at
run-time start (pointer to function) before main() is called and
should NEVER be changed afterwards.

That's what all the
> assert(*dbg_var != NULL); /* *dbg_var == EVP...()->cipher */
> assert(*dbg_var == EVP_des_ede3_cbc()->ctrl);
should be able to find out: the error occurs before the first assert()
that reports a failure, so you see that using these assert()s is
really the hard way of finding the offending code where a
memory-breakpoint able debugger can do this much faster.

>From the fact that you use the assert()s in your code, I take it that
you do not have such a debugger?

--- side track -----------------------------
If you use gdb, see
http://sourceware.org/gdb/current/onlinedocs/gdb_6.html#SEC34
for info how to set such 'watchpoints'.

Just in case you use gdb, here's a bit of howto:

at the start of main(), make sure you get the proper address to watch,
which is '&EVP_des_ede3_cbc()->ctrl' (note the &; just as with the
global var and asserts).
Then add a watchpoint for that value like this: *(int *)0xabcd1234
where 0xabcd1234 is the value of the '&EVP_des_ede3_cbc()->ctrl'
expression right at the start of main().
*(int *)0xabcd1234 should not be a NULL value, by the way.

Read up on gdb at that URL if you use it and did not use it like this
before.
It's faster than tracking down this bugger using a series of assert()s
as the assert()s can only 'narrow down the area' where the illegal
ctrl field overwrite occurs, so you will need an increasing number of
assert()s in your code to pinpoint the offending statement(s).
-----------------------------------

> ------------------
> AM: The assert fails right at the start of the function. If I remove that
> and put it after the
> EVP_CIPHER_CTX_init call, even then it fails. It means, that somehow this
is
> not taking. I will have
> to investigate more.
> ------------------

You misunderstood. The assert()s should go in the code /preceding/ the
init_ex call as we must find who (re)set that ->ctrl member value to
NULL. EVP...init_ex() there is only the /receiver/ of the damage
already done /before/.


I hope you can use gdb or another debugger instead as that would speed
up tracking down the offending code bit quite a bit. If you can't,
copy those two assert() lines throughout the code, more is better,
because we are looking for a moment since start of main() when the
assert()s start to fail. When they fail, it means the bit of code that
was prior (before) that and after the previous assert() block is the
culprit. Add more assert()s in there to narrow down to a single line
of code.

As you see this is hard to do when you don't have a debugger around
which can watch memory breakpoints (I checked the manual and gdb calls
these 'watchpoints'; if you use another debugger, it may have this
feature as all modern hardware can do this, but the name to identify
it may be different, so checking your debugger's manual may help here
-- the 'assert()' approach is the very last ditch and very basic
approach if you don't have a debugger on the target system (which can
happen to you when you develop on smaller embedded hardware)).




Anyway: the important bit is: the bug is in the code /before/ the call
to that OpenSSL init_ex function. Now all we need to do is find where
the cipher static struct object gets corrupted.


--
Met vriendelijke groeten / Best regards,

Ger Hobbelt

--------------------------------------------------
web: http://www.hobbelt.com/
 http://www.hebbut.net/
mail: [EMAIL PROTECTED]
mobile: +31-6-11 120 978
--------------------------------------------------
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]


DISCLAIMER
==========
This e-mail may contain privileged and confidential information which is the 
property of Persistent Systems Ltd. It is intended only for the use of the 
individual or entity to which it is addressed. If you are not the intended 
recipient, you are not authorized to read, retain, copy, print, distribute or 
use this message. If you have received this communication in error, please 
notify the sender and delete all copies of this message. Persistent Systems 
Ltd. does not accept any liability for virus infected mails.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to