langcrypt.c

Go to the documentation of this file.
00001 
00002 /*  $Id: langcrypt.c 1254 2006-04-12 20:27:14Z sethdill $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "langinternal.h"
00032 #include "kernelverbs.h"
00033 #include "kernelverbdefs.h"
00034 #include "resources.h"
00035 #include "tablestructure.h"
00036 #include "lang.h"
00037 #include "frontierconfig.h"
00038 
00039 #include "langcrypt.h"
00040 
00041 #include "md5.h"
00042 #include "whirlpool.h"
00043 #include "sha.h"
00044 #include "sha_locl.h"
00045 
00046 
00047 typedef enum tycryptverbtoken { /* verbs that are processed by crypt.c */
00048 
00049     whirlpoolfunc,
00050 
00051     hmacmd5func,
00052     
00053     md5func,
00054     
00055     sha1func,
00056     
00057     hmacsha1func,
00058     
00059     ctcryptverbs
00060     } tycryptverbtoken;
00061 
00062 
00063 static boolean cryptfunctionvalue (short token, hdltreenode hparam1, tyvaluerecord *vreturned, bigstring bserror) {
00064     
00065     /*
00066     2006-03-07 creedon: created, cribbed from htmlfunctionvalue
00067     */
00068     
00069     hdltreenode hp1 = hparam1;
00070     tyvaluerecord *v = vreturned;
00071     
00072     setbooleanvalue (false, v); /* by default, crypt functions return false */
00073     
00074     switch (token) {
00075         
00076         case whirlpoolfunc: { /* 2006-03-04 creedon: Whirlpool hash */
00077 
00078             Handle h;
00079             struct NESSIEstruct w;
00080             u8 digest [DIGESTBYTES];
00081             short ctconsumed = 1;
00082             short ctpositional = 1;
00083             tyvaluerecord vtranslate;
00084 
00085             setbooleanvalue (true, &vtranslate);
00086 
00087             if (!getreadonlytextvalue (hp1, 1, &h))
00088                 return (false);
00089 
00090             flnextparamislast = true;
00091 
00092             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x0b""flTranslate"), &vtranslate)) 
00093                 return (false);
00094 
00095             lockhandle (h);
00096 
00097             NESSIEinit (&w);
00098             NESSIEadd ((unsigned char *)(*h), 8 * gethandlesize (h), &w);
00099             NESSIEfinalize (&w, digest);
00100 
00101             unlockhandle (h);
00102 
00103             if (vtranslate.data.flvalue) { /* return a hex string */
00104                 bigstring bs;
00105                 unsigned char enc [] = "0123456789abcdef";
00106                 long ix;
00107                 Handle hresult;
00108 
00109                 for (ix = 0; ix < DIGESTBYTES; ix++) {
00110                     setstringcharacter (bs, 2 * ix, enc [(int) ((digest [ix]) / 16)]);
00111                     setstringcharacter (bs, 2 * ix + 1, enc [(int) ((digest [ix]) % 16)]);
00112                     } /* for */
00113 
00114                 setstringlength (bs, DIGESTBYTES * 2);
00115 
00116                 if (!newtexthandle (bs, &hresult))
00117                     return (false);
00118                 
00119                 return (setheapvalue (hresult, stringvaluetype, v));
00120                 }
00121                 
00122             else { /* return a binary of unknown type */
00123                 Handle hresult;
00124 
00125                 if (!newfilledhandle (digest, DIGESTBYTES, &hresult))
00126                     return (false);
00127 
00128                 return (setbinaryvalue (hresult, typeunknown, v));
00129                 }
00130             
00131             return (true);
00132             } /* whirlpoolfunc */
00133 
00134         case hmacmd5func: { /* 2006-03-05 creedon: keyed-hashing for message authentication using md5 */
00135 
00136             Handle hdata, hkey;
00137             unsigned char digest [16];
00138             short ctconsumed = 2;
00139             short ctpositional = 2;
00140             tyvaluerecord vtranslate;
00141 
00142             setbooleanvalue (true, &vtranslate);
00143 
00144             if (!getreadonlytextvalue (hp1, 1, &hdata))
00145                 return (false);
00146             
00147             if (!getreadonlytextvalue (hp1, 2, &hkey))
00148                 return (false);
00149 
00150             flnextparamislast = true;
00151 
00152             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x0b""flTranslate"), &vtranslate)) 
00153                 return (false);
00154 
00155             lockhandle (hkey);
00156             lockhandle (hdata);
00157             
00158             hmacmd5 ((unsigned char *)(*hdata), gethandlesize (hdata), (unsigned char *)(*hkey), gethandlesize (hkey), (unsigned char *) digest);
00159 
00160             unlockhandle (hkey);
00161             unlockhandle (hdata);
00162             
00163             if (vtranslate.data.flvalue) { /* return a hex string */
00164                 bigstring bs;
00165                 unsigned char enc [] = "0123456789abcdef";
00166                 long ix;
00167                 Handle hresult;
00168 
00169                 for (ix = 0; ix < 16; ix++) {
00170                     setstringcharacter (bs, 2 * ix, enc [(int) ((digest [ix]) / 16)]);
00171                     setstringcharacter (bs, 2 * ix + 1, enc [(int) ((digest [ix]) % 16)]);
00172                     } /* for */
00173 
00174                 setstringlength (bs, 32);
00175 
00176                 if (!newtexthandle (bs, &hresult))
00177                     return (false);
00178                 
00179                 return (setheapvalue (hresult, stringvaluetype, v));
00180                 }
00181                 
00182             else { /* return a binary of unknown type */
00183                 Handle hresult;
00184 
00185                 if (!newfilledhandle (digest, 16, &hresult))
00186                     return (false);
00187 
00188                 return (setbinaryvalue (hresult, typeunknown, v));
00189                 }
00190             
00191             return (true);
00192             } /* hmacmd5func */
00193 
00194         case md5func: { /* 2006-03-10 creedon: cribbed from stringverbs.c */
00195             Handle x;
00196             MD5_CTX hashcontext; /* MD5 context. */
00197             unsigned char checksum [16];
00198             short ctconsumed = 1;
00199             short ctpositional = 1;
00200             tyvaluerecord vtranslate;
00201         
00202             if (!getreadonlytextvalue (hp1, 1, &x))
00203                 return (false);
00204 
00205             setbooleanvalue (true, &vtranslate);
00206 
00207             flnextparamislast = true;
00208 
00209             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x0b""flTranslate"), &vtranslate)) 
00210                 return (false);
00211 
00212             lockhandle (x);
00213     
00214             MD5Init (&hashcontext);
00215             
00216             MD5Update (&hashcontext, (unsigned char *)(*x), gethandlesize (x));
00217             
00218             MD5Final (checksum, &hashcontext);
00219             
00220             unlockhandle (x);
00221 
00222             if (vtranslate.data.flvalue) { /* return a hex string */
00223                 bigstring bs;
00224                 unsigned char enc [] = "0123456789abcdef";
00225                 long ix;
00226                 Handle h;
00227 
00228                 for(ix = 0; ix < 16; ix++) {
00229                     setstringcharacter (bs, 2 * ix, enc [(int)((checksum [ix]) / 16)]);
00230                     setstringcharacter (bs, 2 * ix + 1, enc [(int)((checksum [ix]) % 16)]);
00231                     } /* for */
00232 
00233                 setstringlength (bs, 32);
00234 
00235                 if (!newtexthandle (bs, &h))
00236                     return (false);
00237 
00238                 return (setheapvalue (h, stringvaluetype, v));
00239                 }
00240 
00241             else { /* return a binary of unknown type */
00242                 Handle h;
00243 
00244                 if (!newfilledhandle (checksum, 16, &h))
00245                     return (false);
00246 
00247                 return (setbinaryvalue (h, typeunknown, v));
00248                 }
00249             
00250             return (true);
00251             } /* md5func */
00252             
00253         case sha1func: { /* 2006-03-11 creedon: SHA1 hash */
00254             Handle h;
00255             SHA_CTX hashcontext; /* SHA context */
00256             unsigned char digest [SHA_DIGEST_LENGTH];
00257             short ctconsumed = 1;
00258             short ctpositional = 1;
00259             tyvaluerecord vtranslate;
00260 
00261             if (!getreadonlytextvalue (hp1, 1, &h))
00262                 return (false);
00263 
00264             setbooleanvalue (true, &vtranslate);
00265 
00266             flnextparamislast = true;
00267 
00268             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x0b""flTranslate"), &vtranslate)) 
00269                 return (false);
00270 
00271             lockhandle (h);
00272     
00273             SHA1_Init (&hashcontext);
00274             
00275             SHA1_Update (&hashcontext, (unsigned char *)(*h), gethandlesize (h));
00276             
00277             SHA1_Final (digest, &hashcontext);
00278 
00279             unlockhandle (h);
00280 
00281             if (vtranslate.data.flvalue) { /* return a hex string */
00282                 bigstring bs;
00283                 unsigned char enc [] = "0123456789abcdef";
00284                 long ix;
00285                 Handle hresult;
00286 
00287                 for(ix = 0; ix < SHA_DIGEST_LENGTH; ix++) {
00288                     setstringcharacter (bs, 2 * ix, enc [(int)((digest [ix]) / 16)]);
00289                     setstringcharacter (bs, 2 * ix + 1, enc [(int)((digest [ix]) % 16)]);
00290                     } /* for */
00291 
00292                 setstringlength (bs, SHA_DIGEST_LENGTH * 2);
00293 
00294                 if (!newtexthandle (bs, &hresult))
00295                     return (false);
00296 
00297                 return (setheapvalue (hresult, stringvaluetype, v));
00298                 }
00299 
00300             else { /* return a binary of unknown type */
00301                 Handle hresult;
00302 
00303                 if (!newfilledhandle (digest, SHA_DIGEST_LENGTH, &hresult))
00304                     return (false);
00305 
00306                 return (setbinaryvalue (hresult, typeunknown, v));
00307                 }
00308             
00309             return (true);
00310             } /* sha1func */
00311             
00312         case hmacsha1func: { /* 2006-03-11 creedon: keyed-hashing for message authentication using sha1 */
00313 
00314             Handle hdata, hkey;
00315             unsigned char digest [SHA_DIGEST_LENGTH];
00316             short ctconsumed = 2;
00317             short ctpositional = 2;
00318             tyvaluerecord vtranslate;
00319 
00320             setbooleanvalue (true, &vtranslate);
00321 
00322             if (!getreadonlytextvalue (hp1, 1, &hdata))
00323                 return (false);
00324             
00325             if (!getreadonlytextvalue (hp1, 2, &hkey))
00326                 return (false);
00327 
00328             flnextparamislast = true;
00329 
00330             if (!getoptionalparamvalue (hp1, &ctconsumed, &ctpositional, BIGSTRING ("\x0b""flTranslate"), &vtranslate)) 
00331                 return (false);
00332 
00333             lockhandle (hkey);
00334             lockhandle (hdata);
00335             
00336             hmacsha1 ((unsigned char *)(*hdata), gethandlesize (hdata), (unsigned char *)(*hkey), gethandlesize (hkey), (unsigned char *) digest);
00337 
00338             unlockhandle (hkey);
00339             unlockhandle (hdata);
00340             
00341             if (vtranslate.data.flvalue) { /* return a hex string */
00342                 bigstring bs;
00343                 unsigned char enc [] = "0123456789abcdef";
00344                 long ix;
00345                 Handle hresult;
00346 
00347                 for (ix = 0; ix < SHA_DIGEST_LENGTH; ix++) {
00348                     setstringcharacter (bs, 2 * ix, enc [(int) ((digest [ix]) / 16)]);
00349                     setstringcharacter (bs, 2 * ix + 1, enc [(int) ((digest [ix]) % 16)]);
00350                     } /* for */
00351 
00352                 setstringlength (bs, SHA_DIGEST_LENGTH * 2);
00353 
00354                 if (!newtexthandle (bs, &hresult))
00355                     return (false);
00356                 
00357                 return (setheapvalue (hresult, stringvaluetype, v));
00358                 }
00359                 
00360             else { /* return a binary of unknown type */
00361                 Handle hresult;
00362 
00363                 if (!newfilledhandle (digest, SHA_DIGEST_LENGTH, &hresult))
00364                     return (false);
00365 
00366                 return (setbinaryvalue (hresult, typeunknown, v));
00367                 }
00368             
00369             return (true);
00370             } /* hmacsha1func */
00371 
00372         default:
00373             getstringlist (langerrorlist, unimplementedverberror, bserror);
00374             
00375             return (false);
00376         } /* switch */
00377     } /* cryptfunctionvalue */
00378 
00379 
00380 boolean cryptinitverbs (void) {
00381     
00382     /*
00383     2006-03-07 creedon: created, cribbed from htmlinitverbs
00384     */
00385     
00386     return (loadfunctionprocessor (idcryptverbs, &cryptfunctionvalue));
00387     } /* cryptinitverbs */
00388 
00389 
00390 boolean hmacmd5 (unsigned char * text, int text_len, unsigned char * key, int key_len, unsigned char * digest) {
00391 
00392     /*
00393     2006-03-05 creedon: created, cribbed from rfc2104, with a few alterations to fit our code and style
00394                         aradke had implemented this function as part of his crypto.dll also
00395     
00396     text; pointer to data stream
00397     text_len; length of data stream
00398     key; pointer to authentication key
00399     key_len; length of authentication key
00400     digest; caller digest to be filled in
00401     */
00402 
00403         MD5_CTX context;
00404         unsigned char k_ipad [65];  /* inner padding - key XORd with ipad */
00405         unsigned char k_opad [65];  /* outer padding - key XORd with opad */
00406         unsigned char tk [16];
00407         int i;
00408 
00409     if (key_len > 64) { /* if key is longer than 64 bytes reset it to key=MD5(key) */
00410 
00411         MD5_CTX tctx;
00412 
00413         MD5Init (&tctx);
00414         MD5Update (&tctx, key, key_len);
00415         MD5Final (tk, &tctx);
00416 
00417         key = tk;
00418         key_len = 16;
00419         }
00420 
00421     /*
00422     the HMAC_MD5 transform looks like:
00423     
00424     MD5(K XOR opad, MD5(K XOR ipad, text))
00425     
00426     where K is an n byte key
00427     ipad is the byte 0x36 repeated 64 times
00428     opad is the byte 0x5c repeated 64 times
00429     and text is the data being protected
00430     */
00431 
00432     memset (k_ipad, 0, sizeof (k_ipad)); /* start out by storing key in pads */
00433     memset (k_opad, 0, sizeof (k_opad));
00434     memcpy (k_ipad, key, key_len);
00435     memcpy (k_opad, key, key_len);
00436     
00437     for (i = 0; i < 64; i++) { /* XOR key with ipad and opad values */
00438         k_ipad [i] ^= 0x36;
00439         k_opad [i] ^= 0x5c;
00440         }
00441     
00442         /* perform inner MD5 */
00443     
00444     MD5Init (&context);                 /* init context for 1st pass */
00445     MD5Update (&context, k_ipad, 64);       /* start with inner pad */
00446     MD5Update (&context, text, text_len);   /* then text of datagram */
00447     MD5Final (digest, &context);            /* finish up 1st pass */
00448     
00449     /* perform outer MD5 */
00450     
00451     MD5Init (&context);                 /* init context for 2nd pass */
00452     MD5Update (&context, k_opad, 64);       /* start with outer pad */
00453     MD5Update (&context, digest, 16);       /* then results of 1st hash */
00454     MD5Final (digest, &context);            /* finish up 2nd pass */
00455     
00456     return (true);
00457     } /* hmacmd5 */
00458 
00459 
00460 boolean hmacsha1 (unsigned char * text, int text_len, unsigned char * key, int key_len, unsigned char * digest) {
00461 
00462     /*
00463     2006-03-10 creedon: created, cribbed from hmacmd5 function
00464     
00465     text; pointer to data stream
00466     text_len; length of data stream
00467     key; pointer to authentication key
00468     key_len; length of authentication key
00469     digest; caller digest to be filled in
00470     */
00471 
00472         SHA_CTX context;
00473         unsigned char k_ipad [SHA_CBLOCK + 1];      /* inner padding - key XORd with ipad */
00474         unsigned char k_opad [SHA_CBLOCK + 1];  /* outer padding - key XORd with opad */
00475         unsigned char tk [SHA_DIGEST_LENGTH];
00476         int i;
00477 
00478     if (key_len > SHA_CBLOCK) { /* if key is longer than 64 bytes reset it to key=SHA1(key) */
00479 
00480         SHA_CTX tctx;
00481 
00482         SHA1_Init (&tctx);
00483         SHA1_Update (&tctx, key, key_len);
00484         SHA1_Final (tk, &tctx);
00485 
00486         key = tk;
00487         key_len = SHA_DIGEST_LENGTH;
00488         }
00489 
00490     /*
00491     the HMAC_SHA1 transform looks like:
00492     
00493     SHA1(K XOR opad, SHA1(K XOR ipad, text))
00494     
00495     where K is an n byte key
00496     ipad is the byte 0x36 repeated 64 times
00497     opad is the byte 0x5c repeated 64 times
00498     and text is the data being protected
00499     */
00500 
00501     memset (k_ipad, 0, sizeof (k_ipad)); /* start out by storing key in pads */
00502     memset (k_opad, 0, sizeof (k_opad));
00503     memcpy (k_ipad, key, key_len);
00504     memcpy (k_opad, key, key_len);
00505     
00506     for (i = 0; i < SHA_CBLOCK; i++) { /* XOR key with ipad and opad values */
00507         k_ipad [i] ^= 0x36;
00508         k_opad [i] ^= 0x5c;
00509         }
00510     
00511         /* perform inner SHA1 */
00512     
00513     SHA1_Init (&context);                       /* init context for 1st pass */
00514     SHA1_Update (&context, k_ipad, SHA_CBLOCK); /* start with inner pad */
00515     SHA1_Update (&context, text, text_len);         /* then text of datagram */
00516     SHA1_Final (digest, &context);                  /* finish up 1st pass */
00517     
00518     /* perform outer SHA1 */
00519     
00520     SHA1_Init (&context);                           /* init context for 2nd pass */
00521     SHA1_Update (&context, k_opad, SHA_CBLOCK);     /* start with outer pad */
00522     SHA1_Update (&context, digest, SHA_DIGEST_LENGTH);  /* then results of 1st hash */
00523     SHA1_Final (digest, &context);                      /* finish up 2nd pass */
00524     
00525     return (true);
00526     } /* hmacsha1 */
00527 

Generated on Wed May 31 18:19:51 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6