On Tue, Feb 17, 2009 at 12:49 PM, sofian sindhi <sofiansis...@gmail.com> wrote: > Dear all: > I trace openssl recently and I cannot find where the location of EVP_CIPHERs > defined in evp.h. > In evp.h, it is declared as const EVP_CIPHER *EVP_camellia_128_ecb(void); > But where is the trully EVP_camellia_128_ecb(void) located? > I have grepped the source but I cannot get any hint.
In your question you are mixing up two things: EVP_CIPHER is a data structure type (used to carry around cipher context needed by the user & the cipher to perform the task in multiple phases while the data is fed piecemeal to the system at the same time). grep EVP_CIPHER --> ossl_typ.h: typedef struct evp_cipher_st EVP_CIPHER; --> grep "struct evp_cipher_st" --> evp.h: struct evp_cipher_st { ...... }; (which, incidentally, also has /* EVP_CIPHER */ as a comment/hint at the end, so we are heartened in knowing we've hit the jackpot there) When, instead, you want to find where the _function_ EVP_camellia_128_ecb() is defined in the code, and, as you found, cannot track it's definition down using grep (regular text search), then you can go about it various ways, but the oldest and most sure way is this: when you are in such a situation (and otherwise ;-) ), remember that 'C' also comes with a *preprocessor*. That one is used to conditionally include / exclude chunks of source code at compile time, but also offers 'macro' functionality, which in the 'C' realm, can be used to implement something similar to 'templates' (as we know them in, for example, 'C++'. FYI: OpenSSL uses this possibility to great effect in various spots (EVP & ASN1 most particularly). Nothing fancy or difficult, it's just that people tend to forget or, more often, never got taught the language properly (and then complain about others' lack of minding their forgetfulness :-) ). No worries, it's just got to be my Grumpy Day today. ;-) So, can't find a function or data definition anywhere? Here's the general process of digging them up: Run the code through the *preprocessor* and then have a grep through that (intermediate) output. (After all, all the preprocessor does is munch source code and spit out 'preprocessed' *source code* for the actual *compiler*. (Almost) all compilers (and at least ALL the ones I've met in non-embedded environments) offer an option to do exactly that: generally, this is command line option '-E' (~ 'execute preprocessing phase only'). for example: gcc has '-E' MSVC cl has '-E' and '-EP' the hard(er) part is getting the '-E' option added to your compiler commandline argument set (easy on most systems by temporarily redefining GCC or CC environment args so that CC='gcc -E' instead of CC='gcc' but this can cause some trouble in your makefiles as they won't expect this, but alas, you're interested in preprocessed sourcecode there now, not working executables, so ignore the alarm bells and let it rip. Most systems will write such -E preprocessed output to either a .i file (<sourcefilename>.i, e.g. apps.c --> apps.i) or the .o or .obj file if such a target was specified explicitly on the commandline using '-o'. There's no 'always so' rule to this bit, hence me saying it's 'harder', meaning: you must check how it acts on your system and environment, whichever it is. The alternative is running your suspects through 'gcc -E' or your local equivalent *by hand*. ( = copy&paste commandlines issued from make, add the -E yourself and have a go.) The second alternative, when '-E' is not available or otherwise unwilling to cooperate, is to trace the code using a source-viewing debugger: as you run through the code you will notice that function calls will instead sometimes show macro invocations outside any function scope. That's a sure sign there's some templating / code generation going on under the hood right there. --> from there, find those macro definitions and inspect their source code. Further drilldown takes a tool like grep again. So far, Preprocessor Ed 102. (Giving you just the result is pretty useless; the above is needed to enable you to reproduce the result and answer subsequent, similar questions on your own.) The result of this search will find you EVP_camellia_128_ecb() here: evp_locl.h: const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; } which is a function returning the static/const structure defining the cipher and its requirements, such as block length, IV size, ASN.1 aspects such as object ID (nid), plus: the functions (in object/class oriented terms that would be 'methods' rather) used to perform the action on chunks of data (cname##_##mode##_cipher), cleanup the EVP_CIPHER object when you're done (cleanup), etc. When you follow the preprocessor (i.e. answer the question: "how did this bit get expanded into that EVP_camellia_128_ecb() we were looking for?"), you'll find it starts here: e_camellia.c: IMPLEMENT_BLOCK_CIPHER(camellia_128, ks, Camellia, EVP_CAMELLIA_KEY, ....... which is defined here: evp_locl.h: #define IMPLEMENT_BLOCK_CIPHER(cname, ksched, cprefix, kstruct, nid, \ .... and the part of that macro which leads us further is this bit in there: BLOCK_CIPHER_defs(cname, kstruct, nid, block_size, key_len, iv_len, \ as that expands, thanks to the definition here: evp_locl.h: #define BLOCK_CIPHER_defs(cname, kstruct, \ .... via this macro's bit: ... \ BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, iv_len, flags, \ ...... via evp_locl.h: #define BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, \ ... --> BLOCK_CIPHER_def1(cname, ecb, ecb, ECB, kstruct, nid, block_size, key_len, \ ... via #define BLOCK_CIPHER_def1(cname, nmode, mode, MODE, kstruct, nid, block_size, \ ... *** BINGO! *** ... const EVP_CIPHER *EVP_##cname##_##mode(void) { return &cname##_##mode; } Granted, first time around, this may give you a headache, unless you're like me and wondered, after reading the C language specs (before starting to code), where one would use the ## operator to good effect in daily practice, and then discover to your extreme joy a piece of code where this is used to create 'code templates' in C, very much like what we have today as templates in C++. The code which got me that happy[*] is long gone (something written close to 20 years ago by a man named Sim Yskes for Shell), but here is another prime example. [*] finally, I _learned_ something, instead of hearing the IT equivalent again of chewing gum fixing gas tank leaks as they already did way back in WWII. Apparently, software in peace time is not expected to live any longer than Spitfires in war time, but I digress. For your edification: Another very nice use of this ability to make code manageable yet concise (and, yes, we expect one has received (and picked up) an education other than primary school alone when going to work on this sort of thing) is the typechecking safestack template code (see <safestack.h> which wraps compile typechecking around the generic core functionality in <stack.h>; C++ coders would, today, do exactly the same using templates. So would Java coders or anybody else who's got a (strictly typed) language with built-in template ability and a need/want for strict type checking. This <safestack> is a very simple use of macros this way, so this bit of code is preferable to read when you're learning this kind of thing for the first time. When you 'grok' (understand) how the macros in <safestack.h> provide this compile-time typechecking ability, you can take it up to the next level and either 'read' the EVP macros in evp_locl.h and see how they are used, or better (because the format is a general standard so you can read up anywhere about what it should do, so you can think about how you'd do it and see how the OpenSSL creators have solved this problem) read the ASN.1 code, which is another example of typesafe template code [generation] in C, just like EVP. (for ASN.1 study, start at the ans1parse.c code, from there it'll take you to tasn_typ.c and asn1t.h, among others.) (for EVP study, start at apps/enc.c, which will lead you to evp_enc.c and consequently, evp.h and evp_locl.h.) TIP: the MSVC IDE has a nice feature, which works once you use project files for this stuff (available at hebbut.net, for example): click on a function or type, right-click -> 'Go to definition' and it jumps to the line and sourcefile where it believes that bit has been defined. (Same for declarations, by the way.) It's not a 'sure thing' as the IDE can be easily misled, but generally, when it lands on such a macro instead of the name proper, it takes only a little thought and further drilldown using right-click->"go to definition", to find where the structure or function name is constructed from its parts, using ##. That is, at least, how I did it while writing this. ;-) (grep works too, but I'm lazy and this is just a tad faster) I wrote this in hopes I only need to write it once, as others arriving at that same junction where you are: "where the heck is that function gone now?!" will read this and know what to do next after all. Some stuff requires a longer answer to really get you something. (And next time, I can refer back. Saves me the trouble of typing tomorrow.) The key to it all is standard C 'preprocessor parameter concatenation' a.k.a. ## (plus students reading language (grammar) specifications instead of having to stumble forward by trial & error as they receive 'practice-oriented' ed). -- Met vriendelijke groeten / Best regards, Ger Hobbelt -------------------------------------------------- web: http://www.hobbelt.com/ http://www.hebbut.net/ mail: g...@hobbelt.com mobile: +31-6-11 120 978 -------------------------------------------------- ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org