comparison packages/net/snmp/lib/current/src/md5.c @ 103:95f3e12a6327 ecos-sw-2000-06-23

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