Mercurial > ecos
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)*****************************************/ |
