00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <net-snmp/net-snmp-config.h>
00048
00049 #ifndef DISABLE_MD5
00050
00051 #include <stdio.h>
00052 #include <sys/types.h>
00053 #if HAVE_STRING_H
00054 #include <string.h>
00055 #else
00056 #include <strings.h>
00057 #endif
00058 #if HAVE_WINSOCK_H
00059 #include <winsock.h>
00060 #endif
00061
00062 #if HAVE_STDLIB_H
00063 #include <stdlib.h>
00064 #endif
00065
00066 #include <net-snmp/utilities.h>
00067 #include <net-snmp/library/md5.h>
00068
00069
00070
00071
00072 #define I0 0x67452301
00073 #define I1 0xefcdab89
00074 #define I2 0x98badcfe
00075 #define I3 0x10325476
00076 #define fs1 7
00077 #define fs2 12
00078 #define fs3 17
00079 #define fs4 22
00080 #define gs1 5
00081 #define gs2 9
00082 #define gs3 14
00083 #define gs4 20
00084 #define hs1 4
00085 #define hs2 11
00086 #define hs3 16
00087 #define hs4 23
00088 #define is1 6
00089 #define is2 10
00090 #define is3 15
00091 #define is4 21
00092
00093
00094
00095
00096
00097
00098
00099
00100 #define f(X,Y,Z) ((X&Y) | ((~X)&Z))
00101 #define g(X,Y,Z) ((X&Z) | (Y&(~Z)))
00102 #define h(X,Y,Z) (X^Y^Z)
00103 #define i_(X,Y,Z) (Y ^ ((X) | (~Z)))
00104 #define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
00105 #define ff(A,B,C,D,i,s,lp) A = rot((A + f(B,C,D) + X[i] + lp),s) + B
00106 #define gg(A,B,C,D,i,s,lp) A = rot((A + g(B,C,D) + X[i] + lp),s) + B
00107 #define hh(A,B,C,D,i,s,lp) A = rot((A + h(B,C,D) + X[i] + lp),s) + B
00108 #define ii(A,B,C,D,i,s,lp) A = rot((A + i_(B,C,D) + X[i] + lp),s) + B
00109
00110 #ifdef STDC_HEADERS
00111 #define Uns(num) num##U
00112 #else
00113 #define Uns(num) num
00114 #endif
00115
00116 void MDreverse(unsigned int *);
00117 static void MDblock(MDptr, unsigned int *);
00118
00119 #ifdef SNMP_TESTING_CODE
00120
00121
00122
00123
00124
00125
00126
00127 void
00128 MDprint(MDptr MDp)
00129 {
00130 int i, j;
00131 for (i = 0; i < 4; i++)
00132 for (j = 0; j < 32; j = j + 8)
00133 printf("%02x", (MDp->buffer[i] >> j) & 0xFF);
00134 printf("\n");
00135 fflush(stdout);
00136 }
00137 #endif
00138
00139
00140
00141
00142
00143
00144 void
00145 MDbegin(MDptr MDp)
00146 {
00147 int i;
00148 MDp->buffer[0] = I0;
00149 MDp->buffer[1] = I1;
00150 MDp->buffer[2] = I2;
00151 MDp->buffer[3] = I3;
00152 for (i = 0; i < 8; i++)
00153 MDp->count[i] = 0;
00154 MDp->done = 0;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 #define revx { t = (*X << 16) | (*X >> 16); \
00164 *X++ = ((t & 0xFF00FF00) >> 8) | ((t & 0x00FF00FF) << 8); }
00165
00166 void
00167 MDreverse(unsigned int *X)
00168 {
00169 register unsigned int t;
00170 revx;
00171 revx;
00172 revx;
00173 revx;
00174 revx;
00175 revx;
00176 revx;
00177 revx;
00178 revx;
00179 revx;
00180 revx;
00181 revx;
00182 revx;
00183 revx;
00184 revx;
00185 revx;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195 static void
00196 MDblock(MDptr MDp, unsigned int *X)
00197 {
00198 register unsigned int tmp, A, B, C, D;
00199 #ifdef WORDS_BIGENDIAN
00200 MDreverse(X);
00201 #endif
00202 A = MDp->buffer[0];
00203 B = MDp->buffer[1];
00204 C = MDp->buffer[2];
00205 D = MDp->buffer[3];
00206
00207
00208
00209
00210 ff(A, B, C, D, 0, fs1, Uns(3614090360));
00211 ff(D, A, B, C, 1, fs2, Uns(3905402710));
00212 ff(C, D, A, B, 2, fs3, Uns(606105819));
00213 ff(B, C, D, A, 3, fs4, Uns(3250441966));
00214 ff(A, B, C, D, 4, fs1, Uns(4118548399));
00215 ff(D, A, B, C, 5, fs2, Uns(1200080426));
00216 ff(C, D, A, B, 6, fs3, Uns(2821735955));
00217 ff(B, C, D, A, 7, fs4, Uns(4249261313));
00218 ff(A, B, C, D, 8, fs1, Uns(1770035416));
00219 ff(D, A, B, C, 9, fs2, Uns(2336552879));
00220 ff(C, D, A, B, 10, fs3, Uns(4294925233));
00221 ff(B, C, D, A, 11, fs4, Uns(2304563134));
00222 ff(A, B, C, D, 12, fs1, Uns(1804603682));
00223 ff(D, A, B, C, 13, fs2, Uns(4254626195));
00224 ff(C, D, A, B, 14, fs3, Uns(2792965006));
00225 ff(B, C, D, A, 15, fs4, Uns(1236535329));
00226 gg(A, B, C, D, 1, gs1, Uns(4129170786));
00227 gg(D, A, B, C, 6, gs2, Uns(3225465664));
00228 gg(C, D, A, B, 11, gs3, Uns(643717713));
00229 gg(B, C, D, A, 0, gs4, Uns(3921069994));
00230 gg(A, B, C, D, 5, gs1, Uns(3593408605));
00231 gg(D, A, B, C, 10, gs2, Uns(38016083));
00232 gg(C, D, A, B, 15, gs3, Uns(3634488961));
00233 gg(B, C, D, A, 4, gs4, Uns(3889429448));
00234 gg(A, B, C, D, 9, gs1, Uns(568446438));
00235 gg(D, A, B, C, 14, gs2, Uns(3275163606));
00236 gg(C, D, A, B, 3, gs3, Uns(4107603335));
00237 gg(B, C, D, A, 8, gs4, Uns(1163531501));
00238 gg(A, B, C, D, 13, gs1, Uns(2850285829));
00239 gg(D, A, B, C, 2, gs2, Uns(4243563512));
00240 gg(C, D, A, B, 7, gs3, Uns(1735328473));
00241 gg(B, C, D, A, 12, gs4, Uns(2368359562));
00242 hh(A, B, C, D, 5, hs1, Uns(4294588738));
00243 hh(D, A, B, C, 8, hs2, Uns(2272392833));
00244 hh(C, D, A, B, 11, hs3, Uns(1839030562));
00245 hh(B, C, D, A, 14, hs4, Uns(4259657740));
00246 hh(A, B, C, D, 1, hs1, Uns(2763975236));
00247 hh(D, A, B, C, 4, hs2, Uns(1272893353));
00248 hh(C, D, A, B, 7, hs3, Uns(4139469664));
00249 hh(B, C, D, A, 10, hs4, Uns(3200236656));
00250 hh(A, B, C, D, 13, hs1, Uns(681279174));
00251 hh(D, A, B, C, 0, hs2, Uns(3936430074));
00252 hh(C, D, A, B, 3, hs3, Uns(3572445317));
00253 hh(B, C, D, A, 6, hs4, Uns(76029189));
00254 hh(A, B, C, D, 9, hs1, Uns(3654602809));
00255 hh(D, A, B, C, 12, hs2, Uns(3873151461));
00256 hh(C, D, A, B, 15, hs3, Uns(530742520));
00257 hh(B, C, D, A, 2, hs4, Uns(3299628645));
00258 ii(A, B, C, D, 0, is1, Uns(4096336452));
00259 ii(D, A, B, C, 7, is2, Uns(1126891415));
00260 ii(C, D, A, B, 14, is3, Uns(2878612391));
00261 ii(B, C, D, A, 5, is4, Uns(4237533241));
00262 ii(A, B, C, D, 12, is1, Uns(1700485571));
00263 ii(D, A, B, C, 3, is2, Uns(2399980690));
00264 ii(C, D, A, B, 10, is3, Uns(4293915773));
00265 ii(B, C, D, A, 1, is4, Uns(2240044497));
00266 ii(A, B, C, D, 8, is1, Uns(1873313359));
00267 ii(D, A, B, C, 15, is2, Uns(4264355552));
00268 ii(C, D, A, B, 6, is3, Uns(2734768916));
00269 ii(B, C, D, A, 13, is4, Uns(1309151649));
00270 ii(A, B, C, D, 4, is1, Uns(4149444226));
00271 ii(D, A, B, C, 11, is2, Uns(3174756917));
00272 ii(C, D, A, B, 2, is3, Uns(718787259));
00273 ii(B, C, D, A, 9, is4, Uns(3951481745));
00274
00275 MDp->buffer[0] += A;
00276 MDp->buffer[1] += B;
00277 MDp->buffer[2] += C;
00278 MDp->buffer[3] += D;
00279 #ifdef WORDS_BIGENDIAN
00280 MDreverse(X);
00281 #endif
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 int
00302 MDupdate(MDptr MDp, unsigned char *X, unsigned int count)
00303 {
00304 unsigned int i, tmp, bit, byte, mask;
00305 unsigned char XX[64];
00306 unsigned char *p;
00307
00308
00309
00310
00311 if (count == 0 && MDp->done)
00312 return 0;
00313
00314
00315
00316 if (MDp->done) {
00317 return -1;
00318 }
00319
00320
00321
00322
00323
00324
00325 tmp = count;
00326 p = MDp->count;
00327 while (tmp) {
00328 tmp += *p;
00329 *p++ = tmp;
00330 tmp = tmp >> 8;
00331 }
00332
00333
00334
00335 if (count == 512) {
00336 MDblock(MDp, (unsigned int *) X);
00337 } else if (count > 512)
00338 return -2;
00339
00340
00341
00342
00343
00344 else {
00345
00346
00347
00348 int copycount;
00349 byte = count >> 3;
00350 bit = count & 7;
00351 copycount = byte;
00352 if (bit)
00353 copycount++;
00354
00355
00356
00357 memset(XX, 0, sizeof(XX));
00358 memcpy(XX, X, copycount);
00359
00360
00361
00362
00363 mask = ((unsigned long) 1) << (7 - bit);
00364 XX[byte] = (XX[byte] | mask) & ~(mask - 1);
00365
00366
00367
00368 if (byte <= 55) {
00369 for (i = 0; i < 8; i++)
00370 XX[56 + i] = MDp->count[i];
00371 MDblock(MDp, (unsigned int *) XX);
00372 } else {
00373 MDblock(MDp, (unsigned int *) XX);
00374 for (i = 0; i < 56; i++)
00375 XX[i] = 0;
00376 for (i = 0; i < 8; i++)
00377 XX[56 + i] = MDp->count[i];
00378 MDblock(MDp, (unsigned int *) XX);
00379 }
00380
00381
00382
00383 MDp->done = 1;
00384 }
00385 return 0;
00386 }
00387
00388
00389
00390
00391 int
00392 MDchecksum(u_char * data, size_t len, u_char * mac, size_t maclen)
00393 {
00394 MDstruct md;
00395 MDstruct *MD = &md;
00396 int rc = 0;
00397
00398 MDbegin(MD);
00399 while (len >= 64) {
00400 rc = MDupdate(MD, data, 64 * 8);
00401 if (rc)
00402 goto check_end;
00403 data += 64;
00404 len -= 64;
00405 }
00406 rc = MDupdate(MD, data, len * 8);
00407 if (rc)
00408 goto check_end;
00409
00410
00411
00412
00413 MDget(MD, mac, maclen);
00414
00415 check_end:
00416 memset(&md, 0, sizeof(md));
00417 return rc;
00418 }
00419
00420
00421
00422
00423
00424
00425 int
00426 MDsign(u_char * data, size_t len, u_char * mac, size_t maclen,
00427 u_char * secret, size_t secretlen)
00428 {
00429 #define HASHKEYLEN 64
00430
00431 MDstruct MD;
00432 u_char K1[HASHKEYLEN];
00433 u_char K2[HASHKEYLEN];
00434 u_char extendedAuthKey[HASHKEYLEN];
00435 u_char buf[HASHKEYLEN];
00436 size_t i;
00437 u_char *cp, *newdata = 0;
00438 int rc = 0;
00439
00440
00441
00442
00443
00444
00445
00446
00447 if (secretlen != 16 || secret == NULL || mac == NULL || data == NULL ||
00448 len <= 0 || maclen <= 0) {
00449
00450
00451
00452 return -1;
00453 }
00454
00455 memset(extendedAuthKey, 0, HASHKEYLEN);
00456 memcpy(extendedAuthKey, secret, secretlen);
00457 for (i = 0; i < HASHKEYLEN; i++) {
00458 K1[i] = extendedAuthKey[i] ^ 0x36;
00459 K2[i] = extendedAuthKey[i] ^ 0x5c;
00460 }
00461
00462 MDbegin(&MD);
00463 rc = MDupdate(&MD, K1, HASHKEYLEN * 8);
00464 if (rc)
00465 goto update_end;
00466
00467 i = len;
00468 if (((unsigned int) data) % sizeof(long) != 0) {
00469
00470
00471
00472
00473 memdup(&newdata, data, len);
00474 cp = newdata;
00475 } else {
00476 cp = data;
00477 }
00478
00479 while (i >= 64) {
00480 rc = MDupdate(&MD, cp, 64 * 8);
00481 if (rc)
00482 goto update_end;
00483 cp += 64;
00484 i -= 64;
00485 }
00486
00487 rc = MDupdate(&MD, cp, i * 8);
00488 if (rc)
00489 goto update_end;
00490
00491 memset(buf, 0, HASHKEYLEN);
00492 MDget(&MD, buf, HASHKEYLEN);
00493
00494 MDbegin(&MD);
00495 rc = MDupdate(&MD, K2, HASHKEYLEN * 8);
00496 if (rc)
00497 goto update_end;
00498 rc = MDupdate(&MD, buf, 16 * 8);
00499 if (rc)
00500 goto update_end;
00501
00502
00503
00504
00505 MDget(&MD, mac, maclen);
00506
00507 update_end:
00508 memset(buf, 0, HASHKEYLEN);
00509 memset(K1, 0, HASHKEYLEN);
00510 memset(K2, 0, HASHKEYLEN);
00511 memset(extendedAuthKey, 0, HASHKEYLEN);
00512 memset(&MD, 0, sizeof(MD));
00513
00514 if (newdata)
00515 free(newdata);
00516 return rc;
00517 }
00518
00519 void
00520 MDget(MDstruct * MD, u_char * buf, size_t buflen)
00521 {
00522 int i, j;
00523
00524
00525
00526
00527 for (i = 0; i < 4 && i * 4 < (int) buflen; i++)
00528 for (j = 0; j < 4 && i * 4 + j < (int) buflen; j++)
00529 buf[i * 4 + j] = (MD->buffer[i] >> j * 8) & 0xff;
00530 }
00531
00532
00533
00534
00535
00536
00537 #endif