]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/snmp/lib/v2_0/src/md5.c
Merge branch 'master' of git+ssh://git.kernelconcepts.de/karo-tx-redboot
[karo-tx-redboot.git] / packages / net / snmp / lib / v2_0 / src / md5.c
1 //==========================================================================
2 //
3 //      ./lib/current/src/md5.c
4 //
5 //
6 //==========================================================================
7 //####ECOSGPLCOPYRIGHTBEGIN####
8 // -------------------------------------------
9 // This file is part of eCos, the Embedded Configurable Operating System.
10 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
11 //
12 // eCos is free software; you can redistribute it and/or modify it under
13 // the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 2 or (at your option) any later version.
15 //
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19 // for more details.
20 //
21 // You should have received a copy of the GNU General Public License along
22 // with eCos; if not, write to the Free Software Foundation, Inc.,
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
24 //
25 // As a special exception, if other files instantiate templates or use macros
26 // or inline functions from this file, or you compile this file and link it
27 // with other works to produce a work based on this file, this file does not
28 // by itself cause the resulting work to be covered by the GNU General Public
29 // License. However the source code for this file must still be made available
30 // in accordance with section (3) of the GNU General Public License.
31 //
32 // This exception does not invalidate any other reasons why a work based on
33 // this file might be covered by the GNU General Public License.
34 //
35 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
36 // at http://sources.redhat.com/ecos/ecos-license/
37 // -------------------------------------------
38 //####ECOSGPLCOPYRIGHTEND####
39 //####UCDSNMPCOPYRIGHTBEGIN####
40 //
41 // -------------------------------------------
42 //
43 // Portions of this software may have been derived from the UCD-SNMP
44 // project,  <http://ucd-snmp.ucdavis.edu/>  from the University of
45 // California at Davis, which was originally based on the Carnegie Mellon
46 // University SNMP implementation.  Portions of this software are therefore
47 // covered by the appropriate copyright disclaimers included herein.
48 //
49 // The release used was version 4.1.2 of May 2000.  "ucd-snmp-4.1.2"
50 // -------------------------------------------
51 //
52 //####UCDSNMPCOPYRIGHTEND####
53 //==========================================================================
54 //#####DESCRIPTIONBEGIN####
55 //
56 // Author(s):    hmt
57 // Contributors: hmt
58 // Date:         2000-05-30
59 // Purpose:      Port of UCD-SNMP distribution to eCos.
60 // Description:  
61 //              
62 //
63 //####DESCRIPTIONEND####
64 //
65 //==========================================================================
66 /********************************************************************
67        Copyright 1989, 1991, 1992 by Carnegie Mellon University
68
69                           Derivative Work -
70 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
71
72                          All Rights Reserved
73
74 Permission to use, copy, modify and distribute this software and its
75 documentation for any purpose and without fee is hereby granted,
76 provided that the above copyright notice appears in all copies and
77 that both that copyright notice and this permission notice appear in
78 supporting documentation, and that the name of CMU and The Regents of
79 the University of California not be used in advertising or publicity
80 pertaining to distribution of the software without specific written
81 permission.
82
83 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
84 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
85 WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL CMU OR
86 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
87 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
88 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
89 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
90 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
91 *********************************************************************/
92 /* 
93 ** **************************************************************************
94 ** md5.c -- Implementation of MD5 Message Digest Algorithm                 **
95 ** Updated: 2/16/90 by Ronald L. Rivest                                    **
96 ** (C) 1990 RSA Data Security, Inc.                                        **
97 ** **************************************************************************
98 */
99
100 /* 
101 ** To use MD5:
102 **   -- Include md5.h in your program
103 **   -- Declare an MDstruct MD to hold the state of the digest computation.
104 **   -- Initialize MD using MDbegin(&MD)
105 **   -- For each full block (64 bytes) X you wish to process, call
106 **          MDupdate(&MD,X,512)
107 **      (512 is the number of bits in a full block.)
108 **   -- For the last block (less than 64 bytes) you wish to process,
109 **          MDupdate(&MD,X,n)
110 **      where n is the number of bits in the partial block. A partial
111 **      block terminates the computation, so every MD computation should
112 **      terminate by processing a partial block, even if it has n = 0.
113 **   -- The message digest is available in MD.buffer[0] ... MD.buffer[3].
114 **      (Least-significant byte of each word should be output first.)
115 **   -- You can print out the digest using MDprint(&MD)
116 */
117
118 /* Implementation notes:
119 ** This implementation assumes that ints are 32-bit quantities.
120 ** If the machine stores the least-significant byte of an int in the
121 ** least-addressed byte (eg., VAX and 8086), then LOWBYTEFIRST should be
122 ** set to TRUE.  Otherwise (eg., SUNS), LOWBYTEFIRST should be set to
123 ** FALSE.  Note that on machines with LOWBYTEFIRST FALSE the routine
124 ** MDupdate modifies has a side-effect on its input array (the order of bytes
125 ** in each word are reversed).  If this is undesired a call to MDreverse(X) can
126 ** reverse the bytes of X back into order after each call to MDupdate.
127 */
128
129 /* code uses WORDS_BIGENDIAN defined by configure now  -- WH 9/27/95 */
130
131 /* Compile-time includes 
132 */
133
134 #include <config.h>
135
136 #include <stdio.h>
137 #include <sys/types.h>
138 #if HAVE_STRING_H
139 #include <string.h>
140 #else
141 #include <strings.h>
142 #endif
143 #if HAVE_WINSOCK_H
144 #include <winsock.h>
145 #endif
146
147 #include "md5.h"
148
149 /* Compile-time declarations of MD5 ``magic constants''.
150 */
151 #define I0  0x67452301       /* Initial values for MD buffer */
152 #define I1  0xefcdab89
153 #define I2  0x98badcfe
154 #define I3  0x10325476
155 #define fs1  7               /* round 1 shift amounts */
156 #define fs2 12   
157 #define fs3 17  
158 #define fs4 22  
159 #define gs1  5               /* round 2 shift amounts */
160 #define gs2  9   
161 #define gs3 14   
162 #define gs4 20  
163 #define hs1  4               /* round 3 shift amounts */
164 #define hs2 11 
165 #define hs3 16 
166 #define hs4 23
167 #define is1  6               /* round 4 shift amounts */
168 #define is2 10
169 #define is3 15
170 #define is4 21
171
172
173 /* Compile-time macro declarations for MD5.
174 ** Note: The ``rot'' operator uses the variable ``tmp''.
175 ** It assumes tmp is declared as unsigned int, so that the >>
176 ** operator will shift in zeros rather than extending the sign bit.
177 */
178 #define f(X,Y,Z)             ((X&Y) | ((~X)&Z))
179 #define g(X,Y,Z)             ((X&Z) | (Y&(~Z)))
180 #define h(X,Y,Z)             (X^Y^Z)
181 #define i_(X,Y,Z)            (Y ^ ((X) | (~Z)))
182 #define rot(X,S)             (tmp=X,(tmp<<S) | (tmp>>(32-S)))
183 #define ff(A,B,C,D,i,s,lp)   A = rot((A + f(B,C,D) + X[i] + lp),s) + B
184 #define gg(A,B,C,D,i,s,lp)   A = rot((A + g(B,C,D) + X[i] + lp),s) + B
185 #define hh(A,B,C,D,i,s,lp)   A = rot((A + h(B,C,D) + X[i] + lp),s) + B
186 #define ii(A,B,C,D,i,s,lp)   A = rot((A + i_(B,C,D) + X[i] + lp),s) + B
187
188 #ifdef STDC_HEADERS
189 #define Uns(num) num##U
190 #else
191 #define Uns(num) num
192 #endif /* STDC_HEADERS */
193
194 void MDreverse (unsigned int *);
195 static void MDblock (MDptr, unsigned int *);
196
197 #ifdef SNMP_TESTING_CODE
198 /* MDprint(MDp)
199 ** Print message digest buffer MDp as 32 hexadecimal digits.
200 ** Order is from low-order byte of buffer[0] to high-order byte of buffer[3].
201 ** Each byte is printed with high-order hexadecimal digit first.
202 ** This is a user-callable routine.
203 */
204 void 
205 MDprint(MDptr MDp)
206
207     int i,j;
208     for (i=0;i<4;i++)
209         for (j=0;j<32;j=j+8)
210             printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
211     printf("\n");
212     fflush(stdout);
213 }
214 #endif /* SNMP_TESTING_CODE */
215
216 /* MDbegin(MDp)
217 ** Initialize message digest buffer MDp. 
218 ** This is a user-callable routine.
219 */
220 void 
221 MDbegin(MDptr MDp)
222
223     int i;
224     MDp->buffer[0] = I0;  
225     MDp->buffer[1] = I1;  
226     MDp->buffer[2] = I2;  
227     MDp->buffer[3] = I3; 
228     for (i=0;i<8;i++) MDp->count[i] = 0;
229     MDp->done = 0;
230 }
231
232 /* MDreverse(X)
233 ** Reverse the byte-ordering of every int in X.
234 ** Assumes X is an array of 16 ints.
235 ** The macro revx reverses the byte-ordering of the next word of X.
236 */
237 #define revx { t = (*X << 16) | (*X >> 16); \
238                *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
239
240 void MDreverse(unsigned int *X)
241
242     register unsigned int t;
243     revx; revx; revx; revx; revx; revx; revx; revx;
244     revx; revx; revx; revx; revx; revx; revx; revx;
245 }
246
247 /* MDblock(MDp,X)
248 ** Update message digest buffer MDp->buffer using 16-word data block X.
249 ** Assumes all 16 words of X are full of data.
250 ** Does not update MDp->count.
251 ** This routine is not user-callable. 
252 */
253 static void
254 MDblock(MDptr MDp,
255         unsigned int *X)
256
257     register unsigned int tmp, A, B, C, D;  /* hpux sysv sun */
258 #ifdef WORDS_BIGENDIAN
259     MDreverse(X);
260 #endif
261     A = MDp->buffer[0];
262     B = MDp->buffer[1];
263     C = MDp->buffer[2];
264     D = MDp->buffer[3];
265     
266     /* Update the message digest buffer */
267     ff(A , B , C , D ,  0 , fs1 , Uns(3614090360)); /* Round 1 */
268     ff(D , A , B , C ,  1 , fs2 , Uns(3905402710)); 
269     ff(C , D , A , B ,  2 , fs3 ,  Uns(606105819)); 
270     ff(B , C , D , A ,  3 , fs4 , Uns(3250441966)); 
271     ff(A , B , C , D ,  4 , fs1 , Uns(4118548399)); 
272     ff(D , A , B , C ,  5 , fs2 , Uns(1200080426)); 
273     ff(C , D , A , B ,  6 , fs3 , Uns(2821735955)); 
274     ff(B , C , D , A ,  7 , fs4 , Uns(4249261313)); 
275     ff(A , B , C , D ,  8 , fs1 , Uns(1770035416)); 
276     ff(D , A , B , C ,  9 , fs2 , Uns(2336552879)); 
277     ff(C , D , A , B , 10 , fs3 , Uns(4294925233)); 
278     ff(B , C , D , A , 11 , fs4 , Uns(2304563134)); 
279     ff(A , B , C , D , 12 , fs1 , Uns(1804603682)); 
280     ff(D , A , B , C , 13 , fs2 , Uns(4254626195)); 
281     ff(C , D , A , B , 14 , fs3 , Uns(2792965006)); 
282     ff(B , C , D , A , 15 , fs4 , Uns(1236535329)); 
283     gg(A , B , C , D ,  1 , gs1 , Uns(4129170786)); /* Round 2 */
284     gg(D , A , B , C ,  6 , gs2 , Uns(3225465664)); 
285     gg(C , D , A , B , 11 , gs3 ,  Uns(643717713)); 
286     gg(B , C , D , A ,  0 , gs4 , Uns(3921069994)); 
287     gg(A , B , C , D ,  5 , gs1 , Uns(3593408605)); 
288     gg(D , A , B , C , 10 , gs2 ,   Uns(38016083)); 
289     gg(C , D , A , B , 15 , gs3 , Uns(3634488961)); 
290     gg(B , C , D , A ,  4 , gs4 , Uns(3889429448)); 
291     gg(A , B , C , D ,  9 , gs1 ,  Uns(568446438)); 
292     gg(D , A , B , C , 14 , gs2 , Uns(3275163606)); 
293     gg(C , D , A , B ,  3 , gs3 , Uns(4107603335)); 
294     gg(B , C , D , A ,  8 , gs4 , Uns(1163531501)); 
295     gg(A , B , C , D , 13 , gs1 , Uns(2850285829)); 
296     gg(D , A , B , C ,  2 , gs2 , Uns(4243563512)); 
297     gg(C , D , A , B ,  7 , gs3 , Uns(1735328473)); 
298     gg(B , C , D , A , 12 , gs4 , Uns(2368359562));  
299     hh(A , B , C , D ,  5 , hs1 , Uns(4294588738)); /* Round 3 */
300     hh(D , A , B , C ,  8 , hs2 , Uns(2272392833)); 
301     hh(C , D , A , B , 11 , hs3 , Uns(1839030562)); 
302     hh(B , C , D , A , 14 , hs4 , Uns(4259657740)); 
303     hh(A , B , C , D ,  1 , hs1 , Uns(2763975236)); 
304     hh(D , A , B , C ,  4 , hs2 , Uns(1272893353)); 
305     hh(C , D , A , B ,  7 , hs3 , Uns(4139469664)); 
306     hh(B , C , D , A , 10 , hs4 , Uns(3200236656)); 
307     hh(A , B , C , D , 13 , hs1 ,  Uns(681279174)); 
308     hh(D , A , B , C ,  0 , hs2 , Uns(3936430074)); 
309     hh(C , D , A , B ,  3 , hs3 , Uns(3572445317)); 
310     hh(B , C , D , A ,  6 , hs4 ,   Uns(76029189)); 
311     hh(A , B , C , D ,  9 , hs1 , Uns(3654602809)); 
312     hh(D , A , B , C , 12 , hs2 , Uns(3873151461)); 
313     hh(C , D , A , B , 15 , hs3 ,  Uns(530742520)); 
314     hh(B , C , D , A ,  2 , hs4 , Uns(3299628645));
315     ii(A , B , C , D ,  0 , is1 , Uns(4096336452)); /* Round 4 */
316     ii(D , A , B , C ,  7 , is2 , Uns(1126891415));
317     ii(C , D , A , B , 14 , is3 , Uns(2878612391));
318     ii(B , C , D , A ,  5 , is4 , Uns(4237533241));
319     ii(A , B , C , D , 12 , is1 , Uns(1700485571));
320     ii(D , A , B , C ,  3 , is2 , Uns(2399980690));
321     ii(C , D , A , B , 10 , is3 , Uns(4293915773));
322     ii(B , C , D , A ,  1 , is4 , Uns(2240044497));
323     ii(A , B , C , D ,  8 , is1 , Uns(1873313359));
324     ii(D , A , B , C , 15 , is2 , Uns(4264355552));
325     ii(C , D , A , B ,  6 , is3 , Uns(2734768916));
326     ii(B , C , D , A , 13 , is4 , Uns(1309151649));
327     ii(A , B , C , D ,  4 , is1 , Uns(4149444226));
328     ii(D , A , B , C , 11 , is2 , Uns(3174756917));
329     ii(C , D , A , B ,  2 , is3 ,  Uns(718787259));
330     ii(B , C , D , A ,  9 , is4 , Uns(3951481745));
331     
332     MDp->buffer[0] += A; 
333     MDp->buffer[1] += B;
334     MDp->buffer[2] += C;
335     MDp->buffer[3] += D; 
336 #ifdef WORDS_BIGENDIAN
337     MDreverse(X);
338 #endif
339 }
340
341 /* MDupdate(MDp,X,count)
342 ** Input: MDp -- an MDptr
343 **        X -- a pointer to an array of unsigned characters.
344 **        count -- the number of bits of X to use.
345 **                 (if not a multiple of 8, uses high bits of last byte.)
346 ** Update MDp using the number of bits of X given by count.
347 ** This is the basic input routine for an MD5 user.
348 ** The routine completes the MD computation when count < 512, so
349 ** every MD computation should end with one call to MDupdate with a
350 ** count less than 512.  A call with count 0 will be ignored if the
351 ** MD has already been terminated (done != 0), so an extra call with count
352 ** 0 can be given as a ``courtesy close'' to force termination if desired.
353 ** Returns : 0 if processing succeeds or was already done;
354 **          -1 if processing was already done
355 **          -2 if count was too large
356 */
357 int 
358 MDupdate(MDptr MDp,
359          unsigned char *X,
360          unsigned int count)
361
362     unsigned int i, tmp, bit, byte, mask;
363     unsigned char XX[64];
364     unsigned char *p;
365     /* return with no error if this is a courtesy close with count
366   ** zero and MDp->done is true.
367   */
368     if (count == 0 && MDp->done) return 0;
369     /* check to see if MD is already done and report error */
370     if (MDp->done) { return -1; }
371 /*
372     if (MDp->done) { fprintf(stderr,"\nError: MDupdate MD already done."); return; }
373 */
374     /* Add count to MDp->count */
375     tmp = count;
376     p = MDp->count;
377     while (tmp)
378     { tmp += *p;
379     *p++ = tmp;
380     tmp = tmp >> 8;
381     }
382     /* Process data */
383     if (count == 512) 
384     { /* Full block of data to handle */
385         MDblock(MDp,(unsigned int *)X);
386     }
387     else if (count > 512) /* Check for count too large */
388     return -2;
389 /*
390     { fprintf(stderr,"\nError: MDupdate called with illegal count value %d.",count);
391     return;
392     }
393 */
394     else /* partial block -- must be last block so finish up */
395     { /* Find out how many bytes and residual bits there are */
396         int copycount;
397         byte = count >> 3;
398         bit =  count & 7;
399         copycount = byte; if (bit) copycount++;
400         /* Copy X into XX since we need to modify it */
401         memset(XX,0,sizeof(XX));
402         memcpy(XX,X,copycount);
403
404         /* Add padding '1' bit and low-order zeros in last byte */
405         mask = ((unsigned long)1) << (7 - bit);
406         XX[byte] = (XX[byte] | mask) & ~( mask - 1);
407         /* If room for bit count, finish up with this block */
408         if (byte <= 55)
409         { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
410         MDblock(MDp,(unsigned int *)XX);
411         }
412         else /* need to do two blocks to finish up */
413         { MDblock(MDp,(unsigned int *)XX);
414         for (i=0;i<56;i++) XX[i] = 0;
415         for (i=0;i<8;i++)  XX[56+i] = MDp->count[i];
416         MDblock(MDp,(unsigned int *)XX);
417         }
418         /* Set flag saying we're done with MD computation */
419         MDp->done = 1;
420     }
421     return 0;
422 }
423
424 /* MDchecksum(data, len, MD5): do a checksum on an arbirtrary amount of data */
425 int
426 MDchecksum(u_char *data, size_t len, u_char *mac, size_t maclen)
427 {
428   MDstruct md;
429   MDstruct *MD = &md;
430   int rc = 0;
431   
432   MDbegin(MD);
433   while (len >= 64) {
434     rc = MDupdate(MD, data, 64*8);
435     if (rc) goto check_end;
436     data += 64;
437     len -= 64;
438   }
439   rc = MDupdate(MD, data, len*8);
440   if (rc) goto check_end;
441
442   /* copy the checksum to the outgoing data (all of it that is requested). */
443   MDget(MD, mac, maclen);
444
445 check_end:
446   memset(&md,0,sizeof(md));
447   return rc;
448 }
449
450
451 /* MDsign(data, len, MD5): do a checksum on an arbirtrary amount
452    of data, and prepended with a secret in the standard fashion */
453 int
454 MDsign(u_char *data, size_t len, u_char *mac, size_t maclen,
455        u_char *secret, size_t secretlen)
456 {
457 #define HASHKEYLEN 64
458
459   MDstruct MD;
460   u_char   K1[HASHKEYLEN];
461   u_char   K2[HASHKEYLEN];
462   u_char   extendedAuthKey[HASHKEYLEN];
463   u_char   buf[HASHKEYLEN];
464   size_t   i;
465   u_char  *cp;
466   int      rc = 0;
467
468 /*
469   memset(K1,0,HASHKEYLEN);
470   memset(K2,0,HASHKEYLEN);
471   memset(buf,0,HASHKEYLEN);
472   memset(extendedAuthKey,0,HASHKEYLEN);
473 */
474
475   if (secretlen != 16 || secret == NULL || mac == NULL || data == NULL ||
476     len <= 0 || maclen <= 0) {
477 /*    DEBUGMSGTL(("md5","MD5 signing not properly initialized")); */
478     return -1;
479   }
480   
481   memset(extendedAuthKey, 0, HASHKEYLEN);
482   memcpy(extendedAuthKey, secret, secretlen);
483   for(i = 0; i < HASHKEYLEN; i++) {
484     K1[i] = extendedAuthKey[i] ^ 0x36;
485     K2[i] = extendedAuthKey[i] ^ 0x5c;
486   }
487
488   MDbegin(&MD);
489   rc = MDupdate(&MD, K1, HASHKEYLEN*8);
490   if (rc) goto update_end;
491
492   i = len;
493   cp = data;
494   while (i >= 64) {
495     rc = MDupdate(&MD, cp, 64*8);
496         if (rc) goto update_end;
497     cp += 64;
498     i -= 64;
499   }
500
501   rc = MDupdate(&MD, cp, i*8);
502   if (rc) goto update_end;
503
504   memset(buf,0,HASHKEYLEN);
505   MDget(&MD, buf, HASHKEYLEN);
506
507   MDbegin(&MD);
508   rc = MDupdate(&MD, K2, HASHKEYLEN*8);
509   if (rc) goto update_end;
510   rc = MDupdate(&MD, buf, 16*8);
511   if (rc) goto update_end;
512   
513   /* copy the sign checksum to the outgoing pointer */
514   MDget(&MD, mac, maclen);
515
516 update_end:
517   memset(buf, 0, HASHKEYLEN);
518   memset(K1, 0, HASHKEYLEN);
519   memset(K2, 0, HASHKEYLEN);
520   memset(extendedAuthKey, 0, HASHKEYLEN);
521   memset(&MD, 0, sizeof(MD));
522
523   return rc;
524 }
525
526 void
527 MDget(MDstruct *MD, u_char *buf, size_t buflen)
528 {
529   int i, j;
530   
531   /* copy the checksum to the outgoing data (all of it that is requested). */
532   for(i=0; i < 4 && i*4 < (int)buflen; i++)
533     for(j=0; j < 4 && i*4+j < (int)buflen; j++)
534       buf[i*4+j] = (MD->buffer[i] >> j*8) & 0xff;
535 }
536
537 /* 
538 ** End of md5.c
539 ****************************(cut)*****************************************/