1 //==========================================================================
3 // ./lib/current/src/md5.c
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.
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.
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
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.
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.
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.
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####
41 // -------------------------------------------
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.
49 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
50 // -------------------------------------------
52 //####UCDSNMPCOPYRIGHTEND####
53 //==========================================================================
54 //#####DESCRIPTIONBEGIN####
59 // Purpose: Port of UCD-SNMP distribution to eCos.
63 //####DESCRIPTIONEND####
65 //==========================================================================
66 /********************************************************************
67 Copyright 1989, 1991, 1992 by Carnegie Mellon University
70 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
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
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 *********************************************************************/
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 ** **************************************************************************
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,
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)
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.
129 /* code uses WORDS_BIGENDIAN defined by configure now -- WH 9/27/95 */
131 /* Compile-time includes
137 #include <sys/types.h>
149 /* Compile-time declarations of MD5 ``magic constants''.
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 */
159 #define gs1 5 /* round 2 shift amounts */
163 #define hs1 4 /* round 3 shift amounts */
167 #define is1 6 /* round 4 shift amounts */
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.
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
189 #define Uns(num) num##U
192 #endif /* STDC_HEADERS */
194 void MDreverse (unsigned int *);
195 static void MDblock (MDptr, unsigned int *);
197 #ifdef SNMP_TESTING_CODE
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.
210 printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
214 #endif /* SNMP_TESTING_CODE */
217 ** Initialize message digest buffer MDp.
218 ** This is a user-callable routine.
228 for (i=0;i<8;i++) MDp->count[i] = 0;
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.
237 #define revx { t = (*X << 16) | (*X >> 16); \
238 *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
240 void MDreverse(unsigned int *X)
242 register unsigned int t;
243 revx; revx; revx; revx; revx; revx; revx; revx;
244 revx; revx; revx; revx; revx; revx; revx; revx;
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.
257 register unsigned int tmp, A, B, C, D; /* hpux sysv sun */
258 #ifdef WORDS_BIGENDIAN
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));
336 #ifdef WORDS_BIGENDIAN
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
362 unsigned int i, tmp, bit, byte, mask;
363 unsigned char XX[64];
365 /* return with no error if this is a courtesy close with count
366 ** zero and MDp->done is true.
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; }
372 if (MDp->done) { fprintf(stderr,"\nError: MDupdate MD already done."); return; }
374 /* Add count to MDp->count */
384 { /* Full block of data to handle */
385 MDblock(MDp,(unsigned int *)X);
387 else if (count > 512) /* Check for count too large */
390 { fprintf(stderr,"\nError: MDupdate called with illegal count value %d.",count);
394 else /* partial block -- must be last block so finish up */
395 { /* Find out how many bytes and residual bits there are */
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);
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 */
409 { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
410 MDblock(MDp,(unsigned int *)XX);
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);
418 /* Set flag saying we're done with MD computation */
424 /* MDchecksum(data, len, MD5): do a checksum on an arbirtrary amount of data */
426 MDchecksum(u_char *data, size_t len, u_char *mac, size_t maclen)
434 rc = MDupdate(MD, data, 64*8);
435 if (rc) goto check_end;
439 rc = MDupdate(MD, data, len*8);
440 if (rc) goto check_end;
442 /* copy the checksum to the outgoing data (all of it that is requested). */
443 MDget(MD, mac, maclen);
446 memset(&md,0,sizeof(md));
451 /* MDsign(data, len, MD5): do a checksum on an arbirtrary amount
452 of data, and prepended with a secret in the standard fashion */
454 MDsign(u_char *data, size_t len, u_char *mac, size_t maclen,
455 u_char *secret, size_t secretlen)
457 #define HASHKEYLEN 64
460 u_char K1[HASHKEYLEN];
461 u_char K2[HASHKEYLEN];
462 u_char extendedAuthKey[HASHKEYLEN];
463 u_char buf[HASHKEYLEN];
469 memset(K1,0,HASHKEYLEN);
470 memset(K2,0,HASHKEYLEN);
471 memset(buf,0,HASHKEYLEN);
472 memset(extendedAuthKey,0,HASHKEYLEN);
475 if (secretlen != 16 || secret == NULL || mac == NULL || data == NULL ||
476 len <= 0 || maclen <= 0) {
477 /* DEBUGMSGTL(("md5","MD5 signing not properly initialized")); */
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;
489 rc = MDupdate(&MD, K1, HASHKEYLEN*8);
490 if (rc) goto update_end;
495 rc = MDupdate(&MD, cp, 64*8);
496 if (rc) goto update_end;
501 rc = MDupdate(&MD, cp, i*8);
502 if (rc) goto update_end;
504 memset(buf,0,HASHKEYLEN);
505 MDget(&MD, buf, HASHKEYLEN);
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;
513 /* copy the sign checksum to the outgoing pointer */
514 MDget(&MD, mac, maclen);
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));
527 MDget(MDstruct *MD, u_char *buf, size_t buflen)
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;
539 ****************************(cut)*****************************************/