2009/2/18 Ger Hobbelt <g...@hobbelt.com> > 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). > > Dear Ger: Thanks for your PLENTY help. :) I have to digest first. Sincerely Yours,
sofian sindhi