embedded IPsec source code documentation


sha1.c

Go to the documentation of this file.
00001 /*
00002  * embedded IPsec       
00003  * Copyright (c) 2003 Niklaus Schild and Christian Scheurer, HTI Biel/Bienne
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without modification,
00007  * are permitted provided that the following conditions are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright notice,
00010  *    this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright notice,
00012  *    this list of conditions and the following disclaimer in the documentation
00013  *    and/or other materials provided with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote products
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00018  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00020  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00021  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00022  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00025  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00026  * OF SUCH DAMAGE.
00027  *
00028  */
00029 
00053 #include <string.h>
00054 
00055 #include "ipsec/sha1.h"
00056 #include "ipsec/debug.h"
00057 
00058 
00059 unsigned char *SHA1(const unsigned char *d, unsigned long n, unsigned char *md)
00060 {
00061         SHA_CTX c;
00062         static unsigned char m[SHA_DIGEST_LENGTH];
00063 
00064         if (md == NULL) md=m;
00065         SHA1_Init(&c);
00066         SHA1_Update(&c,d,n);
00067         SHA1_Final(md,&c);
00068         memset(&c,0,sizeof(c));
00069         return(md);
00070 }
00071 
00072 
00073 #define Xupdate(a,ix,ia,ib,ic,id)       ( (a)=(ia^ib^ic^id),    \
00074                                           ix=(a)=ROTATE((a),1)  \
00075                                         )
00076 
00077 void sha1_block_host_order (SHA_CTX *c, const void *p,int num);
00078 void sha1_block_data_order (SHA_CTX *c, const void *p,int num);
00079 
00080 
00081 
00082 #define SHA_CBLOCK      (SHA_LBLOCK*4)  /* SHA treats input data as a
00083                                          * contiguous array of 32 bit
00084                                          * wide big-endian values. */
00085 #define SHA_LAST_BLOCK  (SHA_CBLOCK-8)
00086 
00087 
00088 
00089 
00090 #ifndef SHA_LBLOCK
00091 #define SHA_LBLOCK      (SHA_CBLOCK/4)
00092 #endif
00093 
00094 
00095 /*
00096  * Engage compiler specific rotate intrinsic function if available.
00097  */
00098 
00099 #undef ROTATE
00100 
00101 // *** Keil C166 ***
00102 #ifdef __C166__
00103 #include <intrins.h>
00104 #define ROTATE(a,n)     _lrol_(a,n)
00105 #endif
00106 
00107 
00108 /* A nice byte order reversal from Wei Dai <weidai@eskimo.com> */
00109 #ifdef ROTATE
00110 /* 5 instructions with rotate instruction, else 9 */
00111 #define REVERSE_FETCH32(a,l)    (                                       \
00112                 l=*(const SHA_LONG *)(a),                               \
00113                 ((ROTATE(l,8)&0x00FF00FF)|(ROTATE((l&0x00FF00FF),24)))  \
00114                                 )
00115 #endif
00116 
00117 
00118 // #if defined(DATA_ORDER_IS_BIG_ENDIAN)
00119 #define HOST_c2l(c,l)   (l =(((unsigned long)(*((c)++)))<<24),          \
00120                          l|=(((unsigned long)(*((c)++)))<<16),          \
00121                          l|=(((unsigned long)(*((c)++)))<< 8),          \
00122                          l|=(((unsigned long)(*((c)++)))    ),          \
00123                          l)
00124 #define HOST_p_c2l(c,l,n)       {                                       \
00125                         switch (n) {                                    \
00126                         case 0: l =((unsigned long)(*((c)++)))<<24;     \
00127                         case 1: l|=((unsigned long)(*((c)++)))<<16;     \
00128                         case 2: l|=((unsigned long)(*((c)++)))<< 8;     \
00129                         case 3: l|=((unsigned long)(*((c)++)));         \
00130                                 } }
00131 #define HOST_p_c2l_p(c,l,sc,len) {                                      \
00132                         switch (sc) {                                   \
00133                         case 0: l =((unsigned long)(*((c)++)))<<24;     \
00134                                 if (--len == 0) break;                  \
00135                         case 1: l|=((unsigned long)(*((c)++)))<<16;     \
00136                                 if (--len == 0) break;                  \
00137                         case 2: l|=((unsigned long)(*((c)++)))<< 8;     \
00138                                 } }
00139 // NOTE the pointer is not incremented at the end of this
00140 #define HOST_c2l_p(c,l,n)       {                                       \
00141                         l=0; (c)+=n;                                    \
00142                         switch (n) {                                    \
00143                         case 3: l =((unsigned long)(*(--(c))))<< 8;     \
00144                         case 2: l|=((unsigned long)(*(--(c))))<<16;     \
00145                         case 1: l|=((unsigned long)(*(--(c))))<<24;     \
00146                                 } }
00147 #define HOST_l2c(l,c)   (*((c)++)=(unsigned char)(((l)>>24)&0xff),      \
00148                          *((c)++)=(unsigned char)(((l)>>16)&0xff),      \
00149                          *((c)++)=(unsigned char)(((l)>> 8)&0xff),      \
00150                          *((c)++)=(unsigned char)(((l)    )&0xff),      \
00151                          l)
00152 
00153 
00154 /*
00155  * Time for some action:-)
00156  */
00157 
00158 void SHA1_Update (SHA_CTX *c, const void *data_, unsigned long len)
00159 {
00160         const unsigned char *data=data_;
00161         SHA_LONG * p;
00162         unsigned long l;
00163         int sw,sc,ew,ec;
00164 
00165         if (len==0) return;
00166 
00167         l=(c->Nl+(len<<3))&0xffffffffL;
00168         /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to
00169          * Wei Dai <weidai@eskimo.com> for pointing it out. */
00170         if (l < c->Nl) /* overflow */
00171                 c->Nh++;
00172         c->Nh+=(len>>29);
00173         c->Nl=l;
00174 
00175         if (c->num != 0)
00176                 {
00177                 p=c->data;
00178                 sw=c->num>>2;
00179                 sc=c->num&0x03;
00180 
00181                 if ((c->num+len) >= SHA_CBLOCK)
00182                         {
00183                         l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
00184                         for (; sw<SHA_LBLOCK; sw++)
00185                                 {
00186                                 HOST_c2l(data,l); p[sw]=l;
00187                                 }
00188                         sha1_block_host_order (c,p,1);
00189                         len-=(SHA_CBLOCK-c->num);
00190                         c->num=0;
00191                         /* drop through and do the rest */
00192                         }
00193                 else
00194                         {
00195                         c->num+=len;
00196                         if ((sc+len) < 4) /* ugly, add char's to a word */
00197                                 {
00198                                 l=p[sw]; HOST_p_c2l_p(data,l,sc,len); p[sw]=l;
00199                                 }
00200                         else
00201                                 {
00202                                 ew=(c->num>>2);
00203                                 ec=(c->num&0x03);
00204                                 l=p[sw]; HOST_p_c2l(data,l,sc); p[sw++]=l;
00205                                 for (; sw < ew; sw++)
00206                                         {
00207                                         HOST_c2l(data,l); p[sw]=l;
00208                                         }
00209                                 if (ec)
00210                                         {
00211                                         HOST_c2l_p(data,l,ec); p[sw]=l;
00212                                         }
00213                                 }
00214                         return;
00215                         }
00216                 }
00217 
00218         sw=(int)(len/SHA_CBLOCK);
00219         if (sw > 0)
00220                 {
00221                         {
00222                         sha1_block_data_order(c,data,sw);
00223                         sw*=SHA_CBLOCK;
00224                         data+=sw;
00225                         len-=sw;
00226                         }
00227                 }
00228 
00229         if (len!=0)
00230                 {
00231                 p = c->data;
00232                 c->num = (int)len;
00233                 ew=(int)(len>>2);       /* words to copy */
00234                 ec=(int)(len&0x03);
00235                 for (; ew; ew--,p++)
00236                         {
00237                         HOST_c2l(data,l); *p=l;
00238                         }
00239                 HOST_c2l_p(data,l,ec);
00240                 *p=l;
00241                 }
00242 }
00243 
00244 
00245 void SHA1_Transform (SHA_CTX *c, const unsigned char *data)
00246 {
00247         sha1_block_data_order (c,data,1);
00248 }
00249 
00250 
00251 void SHA1_Final (unsigned char *md, SHA_CTX *c)
00252 {
00253         SHA_LONG *p;
00254         unsigned long l;
00255         int i,j;
00256         static const unsigned char end[4]={0x80,0x00,0x00,0x00};
00257         const unsigned char *cp=end;
00258 
00259         /* c->num should definitly have room for at least one more byte. */
00260         p=c->data;
00261         i=c->num>>2;
00262         j=c->num&0x03;
00263 
00264         l = (j==0) ? 0 : p[i];
00265 
00266         HOST_p_c2l(cp,l,j); p[i++]=l; /* i is the next 'undefined word' */
00267 
00268         if (i>(SHA_LBLOCK-2)) /* save room for Nl and Nh */
00269                 {
00270                 if (i<SHA_LBLOCK) p[i]=0;
00271                 sha1_block_host_order (c,p,1);
00272                 i=0;
00273                 }
00274         for (; i<(SHA_LBLOCK-2); i++)
00275                 p[i]=0;
00276 
00277         p[SHA_LBLOCK-2]=c->Nh;
00278         p[SHA_LBLOCK-1]=c->Nl;
00279 
00280         sha1_block_host_order (c,p,1);
00281 
00282         // HASH_MAKE_STRING(c,md);
00283         do {
00284         unsigned long ll;
00285         ll=(c)->h0; HOST_l2c(ll,(md));
00286         ll=(c)->h1; HOST_l2c(ll,(md));
00287         ll=(c)->h2; HOST_l2c(ll,(md));
00288         ll=(c)->h3; HOST_l2c(ll,(md));
00289         ll=(c)->h4; HOST_l2c(ll,(md));
00290         } while (0);
00291 
00292         c->num=0;
00293         /* clear stuff, HASH_BLOCK may be leaving some stuff on the stack
00294          * but I'm not worried :-)
00295         memset((void *)c,0,sizeof(SHA_CTX));
00296          */
00297 }
00298 
00299 
00300 
00301 #define INIT_DATA_h0 0x67452301UL
00302 #define INIT_DATA_h1 0xefcdab89UL
00303 #define INIT_DATA_h2 0x98badcfeUL
00304 #define INIT_DATA_h3 0x10325476UL
00305 #define INIT_DATA_h4 0xc3d2e1f0UL
00306 
00307 void SHA1_Init (SHA_CTX *c)
00308 {
00309         c->h0=INIT_DATA_h0;
00310         c->h1=INIT_DATA_h1;
00311         c->h2=INIT_DATA_h2;
00312         c->h3=INIT_DATA_h3;
00313         c->h4=INIT_DATA_h4;
00314         c->Nl=0;
00315         c->Nh=0;
00316         c->num=0;
00317 }
00318 
00319 #define K_00_19 0x5a827999UL
00320 #define K_20_39 0x6ed9eba1UL
00321 #define K_40_59 0x8f1bbcdcUL
00322 #define K_60_79 0xca62c1d6UL
00323 
00324 /* As  pointed out by Wei Dai <weidai@eskimo.com>, F() below can be
00325  * simplified to the code in F_00_19.  Wei attributes these optimisations
00326  * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
00327  * #define F(x,y,z) (((x) & (y))  |  ((~(x)) & (z)))
00328  * I've just become aware of another tweak to be made, again from Wei Dai,
00329  * in F_40_59, (x&a)|(y&a) -> (x|y)&a
00330  */
00331 #define F_00_19(b,c,d)  ((((c) ^ (d)) & (b)) ^ (d))
00332 #define F_20_39(b,c,d)  ((b) ^ (c) ^ (d))
00333 #define F_40_59(b,c,d)  (((b) & (c)) | (((b)|(c)) & (d)))
00334 #define F_60_79(b,c,d)  F_20_39(b,c,d)
00335 
00336 #define BODY_00_15(i,a,b,c,d,e,f,xi) \
00337         (f)=xi+(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
00338         (b)=ROTATE((b),30);
00339 
00340 #define BODY_16_19(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \
00341         Xupdate(f,xi,xa,xb,xc,xd); \
00342         (f)+=(e)+K_00_19+ROTATE((a),5)+F_00_19((b),(c),(d)); \
00343         (b)=ROTATE((b),30);
00344 
00345 #define BODY_20_31(i,a,b,c,d,e,f,xi,xa,xb,xc,xd) \
00346         Xupdate(f,xi,xa,xb,xc,xd); \
00347         (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
00348         (b)=ROTATE((b),30);
00349 
00350 #define BODY_32_39(i,a,b,c,d,e,f,xa,xb,xc,xd) \
00351         Xupdate(f,xa,xa,xb,xc,xd); \
00352         (f)+=(e)+K_20_39+ROTATE((a),5)+F_20_39((b),(c),(d)); \
00353         (b)=ROTATE((b),30);
00354 
00355 #define BODY_40_59(i,a,b,c,d,e,f,xa,xb,xc,xd) \
00356         Xupdate(f,xa,xa,xb,xc,xd); \
00357         (f)+=(e)+K_40_59+ROTATE((a),5)+F_40_59((b),(c),(d)); \
00358         (b)=ROTATE((b),30);
00359 
00360 #define BODY_60_79(i,a,b,c,d,e,f,xa,xb,xc,xd) \
00361         Xupdate(f,xa,xa,xb,xc,xd); \
00362         (f)=xa+(e)+K_60_79+ROTATE((a),5)+F_60_79((b),(c),(d)); \
00363         (b)=ROTATE((b),30);
00364 
00365 
00366 #define X(i)    XX##i
00367 
00368 void sha1_block_host_order (SHA_CTX *c, const void *d, int num)
00369 {
00370         const SHA_LONG *W=d;
00371         unsigned long A,B,C,D,E,T;
00372         unsigned long   XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
00373                         XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
00374 
00375         A=c->h0;
00376         B=c->h1;
00377         C=c->h2;
00378         D=c->h3;
00379         E=c->h4;
00380 
00381         for (;;)
00382                 {
00383         BODY_00_15( 0,A,B,C,D,E,T,W[ 0]);
00384         BODY_00_15( 1,T,A,B,C,D,E,W[ 1]);
00385         BODY_00_15( 2,E,T,A,B,C,D,W[ 2]);
00386         BODY_00_15( 3,D,E,T,A,B,C,W[ 3]);
00387         BODY_00_15( 4,C,D,E,T,A,B,W[ 4]);
00388         BODY_00_15( 5,B,C,D,E,T,A,W[ 5]);
00389         BODY_00_15( 6,A,B,C,D,E,T,W[ 6]);
00390         BODY_00_15( 7,T,A,B,C,D,E,W[ 7]);
00391         BODY_00_15( 8,E,T,A,B,C,D,W[ 8]);
00392         BODY_00_15( 9,D,E,T,A,B,C,W[ 9]);
00393         BODY_00_15(10,C,D,E,T,A,B,W[10]);
00394         BODY_00_15(11,B,C,D,E,T,A,W[11]);
00395         BODY_00_15(12,A,B,C,D,E,T,W[12]);
00396         BODY_00_15(13,T,A,B,C,D,E,W[13]);
00397         BODY_00_15(14,E,T,A,B,C,D,W[14]);
00398         BODY_00_15(15,D,E,T,A,B,C,W[15]);
00399 
00400         BODY_16_19(16,C,D,E,T,A,B,X( 0),W[ 0],W[ 2],W[ 8],W[13]);
00401         BODY_16_19(17,B,C,D,E,T,A,X( 1),W[ 1],W[ 3],W[ 9],W[14]);
00402         BODY_16_19(18,A,B,C,D,E,T,X( 2),W[ 2],W[ 4],W[10],W[15]);
00403         BODY_16_19(19,T,A,B,C,D,E,X( 3),W[ 3],W[ 5],W[11],X( 0));
00404 
00405         BODY_20_31(20,E,T,A,B,C,D,X( 4),W[ 4],W[ 6],W[12],X( 1));
00406         BODY_20_31(21,D,E,T,A,B,C,X( 5),W[ 5],W[ 7],W[13],X( 2));
00407         BODY_20_31(22,C,D,E,T,A,B,X( 6),W[ 6],W[ 8],W[14],X( 3));
00408         BODY_20_31(23,B,C,D,E,T,A,X( 7),W[ 7],W[ 9],W[15],X( 4));
00409         BODY_20_31(24,A,B,C,D,E,T,X( 8),W[ 8],W[10],X( 0),X( 5));
00410         BODY_20_31(25,T,A,B,C,D,E,X( 9),W[ 9],W[11],X( 1),X( 6));
00411         BODY_20_31(26,E,T,A,B,C,D,X(10),W[10],W[12],X( 2),X( 7));
00412         BODY_20_31(27,D,E,T,A,B,C,X(11),W[11],W[13],X( 3),X( 8));
00413         BODY_20_31(28,C,D,E,T,A,B,X(12),W[12],W[14],X( 4),X( 9));
00414         BODY_20_31(29,B,C,D,E,T,A,X(13),W[13],W[15],X( 5),X(10));
00415         BODY_20_31(30,A,B,C,D,E,T,X(14),W[14],X( 0),X( 6),X(11));
00416         BODY_20_31(31,T,A,B,C,D,E,X(15),W[15],X( 1),X( 7),X(12));
00417 
00418         BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));
00419         BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));
00420         BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));
00421         BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));
00422         BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));
00423         BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));
00424         BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));
00425         BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));
00426 
00427         BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));
00428         BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));
00429         BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));
00430         BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));
00431         BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));
00432         BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));
00433         BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));
00434         BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));
00435         BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));
00436         BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));
00437         BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));
00438         BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));
00439         BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));
00440         BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));
00441         BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));
00442         BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));
00443         BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));
00444         BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));
00445         BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));
00446         BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));
00447 
00448         BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));
00449         BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));
00450         BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));
00451         BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));
00452         BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));
00453         BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));
00454         BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));
00455         BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));
00456         BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));
00457         BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));
00458         BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));
00459         BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));
00460         BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));
00461         BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));
00462         BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));
00463         BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));
00464         BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));
00465         BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));
00466         BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));
00467         BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));
00468 
00469         c->h0=(c->h0+E)&0xffffffffL;
00470         c->h1=(c->h1+T)&0xffffffffL;
00471         c->h2=(c->h2+A)&0xffffffffL;
00472         c->h3=(c->h3+B)&0xffffffffL;
00473         c->h4=(c->h4+C)&0xffffffffL;
00474 
00475         if (--num <= 0) break;
00476 
00477         A=c->h0;
00478         B=c->h1;
00479         C=c->h2;
00480         D=c->h3;
00481         E=c->h4;
00482 
00483         W+=SHA_LBLOCK;
00484         }
00485 }
00486 
00487 void sha1_block_data_order (SHA_CTX *c, const void *p, int num)
00488 {
00489         const unsigned char *data=p;
00490         unsigned long A,B,C,D,E,T,l;
00491         unsigned long   XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7,
00492                         XX8, XX9,XX10,XX11,XX12,XX13,XX14,XX15;
00493 
00494         A=c->h0;
00495         B=c->h1;
00496         C=c->h2;
00497         D=c->h3;
00498         E=c->h4;
00499 
00500         for (;;)
00501                 {
00502 
00503         HOST_c2l(data,l); X( 0)=l;              HOST_c2l(data,l); X( 1)=l;
00504         BODY_00_15( 0,A,B,C,D,E,T,X( 0));       HOST_c2l(data,l); X( 2)=l;
00505         BODY_00_15( 1,T,A,B,C,D,E,X( 1));       HOST_c2l(data,l); X( 3)=l;
00506         BODY_00_15( 2,E,T,A,B,C,D,X( 2));       HOST_c2l(data,l); X( 4)=l;
00507         BODY_00_15( 3,D,E,T,A,B,C,X( 3));       HOST_c2l(data,l); X( 5)=l;
00508         BODY_00_15( 4,C,D,E,T,A,B,X( 4));       HOST_c2l(data,l); X( 6)=l;
00509         BODY_00_15( 5,B,C,D,E,T,A,X( 5));       HOST_c2l(data,l); X( 7)=l;
00510         BODY_00_15( 6,A,B,C,D,E,T,X( 6));       HOST_c2l(data,l); X( 8)=l;
00511         BODY_00_15( 7,T,A,B,C,D,E,X( 7));       HOST_c2l(data,l); X( 9)=l;
00512         BODY_00_15( 8,E,T,A,B,C,D,X( 8));       HOST_c2l(data,l); X(10)=l;
00513         BODY_00_15( 9,D,E,T,A,B,C,X( 9));       HOST_c2l(data,l); X(11)=l;
00514         BODY_00_15(10,C,D,E,T,A,B,X(10));       HOST_c2l(data,l); X(12)=l;
00515         BODY_00_15(11,B,C,D,E,T,A,X(11));       HOST_c2l(data,l); X(13)=l;
00516         BODY_00_15(12,A,B,C,D,E,T,X(12));       HOST_c2l(data,l); X(14)=l;
00517         BODY_00_15(13,T,A,B,C,D,E,X(13));       HOST_c2l(data,l); X(15)=l;
00518         BODY_00_15(14,E,T,A,B,C,D,X(14));
00519         BODY_00_15(15,D,E,T,A,B,C,X(15));
00520 
00521         BODY_16_19(16,C,D,E,T,A,B,X( 0),X( 0),X( 2),X( 8),X(13));
00522         BODY_16_19(17,B,C,D,E,T,A,X( 1),X( 1),X( 3),X( 9),X(14));
00523         BODY_16_19(18,A,B,C,D,E,T,X( 2),X( 2),X( 4),X(10),X(15));
00524         BODY_16_19(19,T,A,B,C,D,E,X( 3),X( 3),X( 5),X(11),X( 0));
00525 
00526         BODY_20_31(20,E,T,A,B,C,D,X( 4),X( 4),X( 6),X(12),X( 1));
00527         BODY_20_31(21,D,E,T,A,B,C,X( 5),X( 5),X( 7),X(13),X( 2));
00528         BODY_20_31(22,C,D,E,T,A,B,X( 6),X( 6),X( 8),X(14),X( 3));
00529         BODY_20_31(23,B,C,D,E,T,A,X( 7),X( 7),X( 9),X(15),X( 4));
00530         BODY_20_31(24,A,B,C,D,E,T,X( 8),X( 8),X(10),X( 0),X( 5));
00531         BODY_20_31(25,T,A,B,C,D,E,X( 9),X( 9),X(11),X( 1),X( 6));
00532         BODY_20_31(26,E,T,A,B,C,D,X(10),X(10),X(12),X( 2),X( 7));
00533         BODY_20_31(27,D,E,T,A,B,C,X(11),X(11),X(13),X( 3),X( 8));
00534         BODY_20_31(28,C,D,E,T,A,B,X(12),X(12),X(14),X( 4),X( 9));
00535         BODY_20_31(29,B,C,D,E,T,A,X(13),X(13),X(15),X( 5),X(10));
00536         BODY_20_31(30,A,B,C,D,E,T,X(14),X(14),X( 0),X( 6),X(11));
00537         BODY_20_31(31,T,A,B,C,D,E,X(15),X(15),X( 1),X( 7),X(12));
00538 
00539         BODY_32_39(32,E,T,A,B,C,D,X( 0),X( 2),X( 8),X(13));
00540         BODY_32_39(33,D,E,T,A,B,C,X( 1),X( 3),X( 9),X(14));
00541         BODY_32_39(34,C,D,E,T,A,B,X( 2),X( 4),X(10),X(15));
00542         BODY_32_39(35,B,C,D,E,T,A,X( 3),X( 5),X(11),X( 0));
00543         BODY_32_39(36,A,B,C,D,E,T,X( 4),X( 6),X(12),X( 1));
00544         BODY_32_39(37,T,A,B,C,D,E,X( 5),X( 7),X(13),X( 2));
00545         BODY_32_39(38,E,T,A,B,C,D,X( 6),X( 8),X(14),X( 3));
00546         BODY_32_39(39,D,E,T,A,B,C,X( 7),X( 9),X(15),X( 4));
00547 
00548         BODY_40_59(40,C,D,E,T,A,B,X( 8),X(10),X( 0),X( 5));
00549         BODY_40_59(41,B,C,D,E,T,A,X( 9),X(11),X( 1),X( 6));
00550         BODY_40_59(42,A,B,C,D,E,T,X(10),X(12),X( 2),X( 7));
00551         BODY_40_59(43,T,A,B,C,D,E,X(11),X(13),X( 3),X( 8));
00552         BODY_40_59(44,E,T,A,B,C,D,X(12),X(14),X( 4),X( 9));
00553         BODY_40_59(45,D,E,T,A,B,C,X(13),X(15),X( 5),X(10));
00554         BODY_40_59(46,C,D,E,T,A,B,X(14),X( 0),X( 6),X(11));
00555         BODY_40_59(47,B,C,D,E,T,A,X(15),X( 1),X( 7),X(12));
00556         BODY_40_59(48,A,B,C,D,E,T,X( 0),X( 2),X( 8),X(13));
00557         BODY_40_59(49,T,A,B,C,D,E,X( 1),X( 3),X( 9),X(14));
00558         BODY_40_59(50,E,T,A,B,C,D,X( 2),X( 4),X(10),X(15));
00559         BODY_40_59(51,D,E,T,A,B,C,X( 3),X( 5),X(11),X( 0));
00560         BODY_40_59(52,C,D,E,T,A,B,X( 4),X( 6),X(12),X( 1));
00561         BODY_40_59(53,B,C,D,E,T,A,X( 5),X( 7),X(13),X( 2));
00562         BODY_40_59(54,A,B,C,D,E,T,X( 6),X( 8),X(14),X( 3));
00563         BODY_40_59(55,T,A,B,C,D,E,X( 7),X( 9),X(15),X( 4));
00564         BODY_40_59(56,E,T,A,B,C,D,X( 8),X(10),X( 0),X( 5));
00565         BODY_40_59(57,D,E,T,A,B,C,X( 9),X(11),X( 1),X( 6));
00566         BODY_40_59(58,C,D,E,T,A,B,X(10),X(12),X( 2),X( 7));
00567         BODY_40_59(59,B,C,D,E,T,A,X(11),X(13),X( 3),X( 8));
00568 
00569         BODY_60_79(60,A,B,C,D,E,T,X(12),X(14),X( 4),X( 9));
00570         BODY_60_79(61,T,A,B,C,D,E,X(13),X(15),X( 5),X(10));
00571         BODY_60_79(62,E,T,A,B,C,D,X(14),X( 0),X( 6),X(11));
00572         BODY_60_79(63,D,E,T,A,B,C,X(15),X( 1),X( 7),X(12));
00573         BODY_60_79(64,C,D,E,T,A,B,X( 0),X( 2),X( 8),X(13));
00574         BODY_60_79(65,B,C,D,E,T,A,X( 1),X( 3),X( 9),X(14));
00575         BODY_60_79(66,A,B,C,D,E,T,X( 2),X( 4),X(10),X(15));
00576         BODY_60_79(67,T,A,B,C,D,E,X( 3),X( 5),X(11),X( 0));
00577         BODY_60_79(68,E,T,A,B,C,D,X( 4),X( 6),X(12),X( 1));
00578         BODY_60_79(69,D,E,T,A,B,C,X( 5),X( 7),X(13),X( 2));
00579         BODY_60_79(70,C,D,E,T,A,B,X( 6),X( 8),X(14),X( 3));
00580         BODY_60_79(71,B,C,D,E,T,A,X( 7),X( 9),X(15),X( 4));
00581         BODY_60_79(72,A,B,C,D,E,T,X( 8),X(10),X( 0),X( 5));
00582         BODY_60_79(73,T,A,B,C,D,E,X( 9),X(11),X( 1),X( 6));
00583         BODY_60_79(74,E,T,A,B,C,D,X(10),X(12),X( 2),X( 7));
00584         BODY_60_79(75,D,E,T,A,B,C,X(11),X(13),X( 3),X( 8));
00585         BODY_60_79(76,C,D,E,T,A,B,X(12),X(14),X( 4),X( 9));
00586         BODY_60_79(77,B,C,D,E,T,A,X(13),X(15),X( 5),X(10));
00587         BODY_60_79(78,A,B,C,D,E,T,X(14),X( 0),X( 6),X(11));
00588         BODY_60_79(79,T,A,B,C,D,E,X(15),X( 1),X( 7),X(12));
00589 
00590         c->h0=(c->h0+E)&0xffffffffL;
00591         c->h1=(c->h1+T)&0xffffffffL;
00592         c->h2=(c->h2+A)&0xffffffffL;
00593         c->h3=(c->h3+B)&0xffffffffL;
00594         c->h4=(c->h4+C)&0xffffffffL;
00595 
00596         if (--num <= 0) break;
00597 
00598         A=c->h0;
00599         B=c->h1;
00600         C=c->h2;
00601         D=c->h3;
00602         E=c->h4;
00603 
00604         }
00605 }
00606 
00607 
00608 
00609 
00610 /*
00611  * Function: RFC 2104 hmac_sha1 
00612  *
00613  *   unsigned char*  text          pointer to data stream
00614  *   int             text_len      length of data stream
00615  *   unsigned char*  key           pointer to authentication key
00616  *   int             key_len       length of authentication key
00617  *   unsigned char*  digest        caller digest to be filled in
00618  *
00619  */
00620 void hmac_sha1(unsigned char* text, int text_len, unsigned char*  key, int key_len, unsigned char*  digest)
00621 {
00622     SHA_CTX context;
00623     unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
00624     unsigned char k_opad[65];    /* outer padding - key XORd with opad */
00625     unsigned char tk[20];                /* L=20 for SHA1 (RFC 2141, 2. Definition of HMAC) */
00626     int i;
00627 
00628         IPSEC_LOG_TRC(IPSEC_TRACE_ENTER, 
00629                       "hmac_sha1", 
00630                                   ("text=%p, text_len=%d, key=%p, key_len=%d, digest=%p",
00631                               (void *)text, text_len, (void *)key, key_len, (void *)digest)
00632                                  );
00633 
00634     /* if key is longer than 64 bytes reset it to key=SHA1(key) */
00635     if (key_len > 64) {
00636 
00637             SHA_CTX      tctx;
00638 
00639             SHA1_Init(&tctx);
00640             SHA1_Update(&tctx, key, key_len);
00641             SHA1_Final(tk, &tctx);
00642 
00643             key = tk;
00644             key_len = 20;
00645     }
00646 
00647     /*
00648      * the HMAC_SHA1 transform looks like:
00649      *
00650      * SHA1(K XOR opad, SHA1(K XOR ipad, text))
00651      *
00652      * where K is an n byte key
00653      * ipad is the byte 0x36 repeated 64 times
00654      * opad is the byte 0x5c repeated 64 times
00655      * and text is the data being protected
00656      */
00657 
00658     /* start out by storing key in pads */
00659     memset(k_ipad, '\0', sizeof(k_ipad));  
00660     memset(k_opad, '\0', sizeof(k_opad));  
00661     memcpy(k_ipad, key, key_len);                  
00662     memcpy(k_opad, key, key_len);                  
00663 
00664 
00665     /* XOR key with ipad and opad values */
00666     for (i=0; i<64; i++) {
00667             k_ipad[i] ^= 0x36;
00668             k_opad[i] ^= 0x5c;
00669     }
00670     /*
00671      * perform inner MD5
00672      */
00673     SHA1_Init(&context);                 /* init context for 1st pass */
00674     SHA1_Update(&context, k_ipad, 64);   /* start with inner pad */
00675     SHA1_Update(&context, text, text_len);/* then text of datagram */
00676     SHA1_Final(digest, &context);         /* finish up 1st pass */
00677     /*
00678      * perform outer MD5
00679      */
00680     SHA1_Init(&context);                 /* init context for 2nd
00681                                           * pass */
00682     SHA1_Update(&context, k_opad, 64);   /* start with outer pad */
00683     SHA1_Update(&context, digest, 20);   /* then results of 1st hash */
00684     SHA1_Final(digest, &context);        /* finish up 2nd pass */
00685 
00686         IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "hmac_sha1", ("void") );
00687 }
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 

Copyright 2003 by Christian Scheurer and Niklaus Schild