00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <net-snmp/net-snmp-config.h>
00017
00018 #include <stdio.h>
00019 #include <sys/types.h>
00020 #if HAVE_WINSOCK_H
00021 #include <winsock.h>
00022 #endif
00023 #ifdef HAVE_NETINET_IN_H
00024 #include <netinet/in.h>
00025 #endif
00026 #ifdef HAVE_STDLIB_H
00027 #include <stdlib.h>
00028 #endif
00029 #if HAVE_STRING_H
00030 #include <string.h>
00031 #else
00032 #include <strings.h>
00033 #endif
00034
00035 #if HAVE_DMALLOC_H
00036 #include <dmalloc.h>
00037 #endif
00038
00039 #include <net-snmp/types.h>
00040 #include <net-snmp/output_api.h>
00041 #include <net-snmp/utilities.h>
00042
00043 #include <net-snmp/library/snmp_api.h>
00044 #ifdef NETSNMP_USE_OPENSSL
00045 # include <openssl/hmac.h>
00046 #else
00047 #ifdef NETSNMP_USE_INTERNAL_MD5
00048 #include <net-snmp/library/md5.h>
00049 #endif
00050 #endif
00051
00052 #ifdef NETSNMP_USE_PKCS11
00053 #include <security/cryptoki.h>
00054 #endif
00055
00056 #include <net-snmp/library/scapi.h>
00057 #include <net-snmp/library/keytools.h>
00058
00059 #include <net-snmp/library/transform_oids.h>
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 int
00095 generate_Ku(const oid * hashtype, u_int hashtype_len,
00096 u_char * P, size_t pplen, u_char * Ku, size_t * kulen)
00097 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL)
00098 {
00099 int rval = SNMPERR_SUCCESS,
00100 nbytes = USM_LENGTH_EXPANDED_PASSPHRASE;
00101
00102 u_int i, pindex = 0;
00103
00104 u_char buf[USM_LENGTH_KU_HASHBLOCK], *bufp;
00105
00106 #ifdef NETSNMP_USE_OPENSSL
00107 EVP_MD_CTX *ctx = (EVP_MD_CTX *)malloc(sizeof(EVP_MD_CTX));
00108 unsigned int tmp_len;
00109 #else
00110 MDstruct MD;
00111 #endif
00112
00113
00114
00115 if (!hashtype || !P || !Ku || !kulen || (*kulen <= 0)
00116 || (hashtype_len != USM_LENGTH_OID_TRANSFORM)) {
00117 QUITFUN(SNMPERR_GENERR, generate_Ku_quit);
00118 }
00119
00120 if (pplen < USM_LENGTH_P_MIN) {
00121 snmp_log(LOG_ERR, "Error: passphrase chosen is below the length "
00122 "requirements of the USM (min=%d).\n",USM_LENGTH_P_MIN);
00123 snmp_set_detail("The supplied password length is too short.");
00124 QUITFUN(SNMPERR_GENERR, generate_Ku_quit);
00125 }
00126
00127
00128
00129
00130
00131 #ifdef NETSNMP_USE_OPENSSL
00132
00133 #ifndef NETSNMP_DISABLE_MD5
00134 if (ISTRANSFORM(hashtype, HMACMD5Auth))
00135 EVP_DigestInit(ctx, EVP_md5());
00136 else
00137 #endif
00138 if (ISTRANSFORM(hashtype, HMACSHA1Auth))
00139 EVP_DigestInit(ctx, EVP_sha1());
00140 else {
00141 free(ctx);
00142 return (SNMPERR_GENERR);
00143 }
00144 #else
00145 MDbegin(&MD);
00146 #endif
00147
00148 while (nbytes > 0) {
00149 bufp = buf;
00150 for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) {
00151 *bufp++ = P[pindex++ % pplen];
00152 }
00153 #ifdef NETSNMP_USE_OPENSSL
00154 EVP_DigestUpdate(ctx, buf, USM_LENGTH_KU_HASHBLOCK);
00155 #elif NETSNMP_USE_INTERNAL_MD5
00156 if (MDupdate(&MD, buf, USM_LENGTH_KU_HASHBLOCK * 8)) {
00157 rval = SNMPERR_USM_ENCRYPTIONERROR;
00158 goto md5_fin;
00159 }
00160 #endif
00161
00162 nbytes -= USM_LENGTH_KU_HASHBLOCK;
00163 }
00164
00165 #ifdef NETSNMP_USE_OPENSSL
00166 tmp_len = *kulen;
00167 EVP_DigestFinal(ctx, (unsigned char *) Ku, &tmp_len);
00168 *kulen = tmp_len;
00169
00170
00171
00172 #elif NETSNMP_USE_INTERNAL_MD5
00173 if (MDupdate(&MD, buf, 0)) {
00174 rval = SNMPERR_USM_ENCRYPTIONERROR;
00175 goto md5_fin;
00176 }
00177 *kulen = sc_get_properlength(hashtype, hashtype_len);
00178 MDget(&MD, Ku, *kulen);
00179 md5_fin:
00180 memset(&MD, 0, sizeof(MD));
00181 #endif
00182
00183
00184 #ifdef NETSNMP_ENABLE_TESTING_CODE
00185 DEBUGMSGTL(("generate_Ku", "generating Ku (from %s): ", P));
00186 for (i = 0; i < *kulen; i++)
00187 DEBUGMSG(("generate_Ku", "%02x", Ku[i]));
00188 DEBUGMSG(("generate_Ku", "\n"));
00189 #endif
00190
00191
00192 generate_Ku_quit:
00193 memset(buf, 0, sizeof(buf));
00194 #ifdef NETSNMP_USE_OPENSSL
00195 free(ctx);
00196 #endif
00197 return rval;
00198
00199 }
00200 #elif NETSNMP_USE_PKCS11
00201 {
00202 int rval = SNMPERR_SUCCESS;
00203
00204
00205
00206
00207 if (!hashtype || !P || !Ku || !kulen || (*kulen <= 0)
00208 || (hashtype_len != USM_LENGTH_OID_TRANSFORM)) {
00209 QUITFUN(SNMPERR_GENERR, generate_Ku_quit);
00210 }
00211
00212 if (pplen < USM_LENGTH_P_MIN) {
00213 snmp_log(LOG_ERR, "Error: passphrase chosen is below the length "
00214 "requirements of the USM (min=%d).\n",USM_LENGTH_P_MIN);
00215 snmp_set_detail("The supplied password length is too short.");
00216 QUITFUN(SNMPERR_GENERR, generate_Ku_quit);
00217 }
00218
00219
00220
00221
00222
00223 #ifndef NETSNMP_DISABLE_MD5
00224 if (ISTRANSFORM(hashtype, HMACMD5Auth))
00225 return pkcs_generate_Ku(CKM_MD5, P, pplen, Ku, kulen);
00226 else
00227 #endif
00228 if (ISTRANSFORM(hashtype, HMACSHA1Auth))
00229 return pkcs_generate_Ku(CKM_SHA_1, P, pplen, Ku, kulen);
00230 else {
00231 return (SNMPERR_GENERR);
00232 }
00233
00234 generate_Ku_quit:
00235
00236 return rval;
00237 }
00238 #else
00239 _KEYTOOLS_NOT_AVAILABLE
00240 #endif
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 int
00280 generate_kul(const oid * hashtype, u_int hashtype_len,
00281 u_char * engineID, size_t engineID_len,
00282 u_char * Ku, size_t ku_len,
00283 u_char * Kul, size_t * kul_len)
00284 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_PKCS11)
00285 {
00286 int rval = SNMPERR_SUCCESS;
00287 u_int nbytes = 0;
00288 size_t properlength;
00289 int iproperlength;
00290
00291 u_char buf[SNMP_MAXBUF];
00292 #ifdef NETSNMP_ENABLE_TESTING_CODE
00293 int i;
00294 #endif
00295
00296
00297
00298
00299
00300 if (!hashtype || !engineID || !Ku || !Kul || !kul_len
00301 || (engineID_len <= 0) || (ku_len <= 0) || (*kul_len <= 0)
00302 || (hashtype_len != USM_LENGTH_OID_TRANSFORM)) {
00303 QUITFUN(SNMPERR_GENERR, generate_kul_quit);
00304 }
00305
00306
00307 iproperlength = sc_get_properlength(hashtype, hashtype_len);
00308 if (iproperlength == SNMPERR_GENERR)
00309 QUITFUN(SNMPERR_GENERR, generate_kul_quit);
00310
00311 properlength = (size_t) iproperlength;
00312
00313 if (((int) *kul_len < properlength) || ((int) ku_len < properlength)) {
00314 QUITFUN(SNMPERR_GENERR, generate_kul_quit);
00315 }
00316
00317
00318
00319
00320
00321 nbytes = 0;
00322 memcpy(buf, Ku, properlength);
00323 nbytes += properlength;
00324 memcpy(buf + nbytes, engineID, engineID_len);
00325 nbytes += engineID_len;
00326 memcpy(buf + nbytes, Ku, properlength);
00327 nbytes += properlength;
00328
00329 rval = sc_hash(hashtype, hashtype_len, buf, nbytes, Kul, kul_len);
00330
00331 #ifdef NETSNMP_ENABLE_TESTING_CODE
00332 DEBUGMSGTL(("generate_kul", "generating Kul (from Ku): "));
00333 for (i = 0; i < *kul_len; i++)
00334 DEBUGMSG(("generate_kul", "%02x", Kul[i]));
00335 DEBUGMSG(("generate_kul", "keytools\n"));
00336 #endif
00337
00338 QUITFUN(rval, generate_kul_quit);
00339
00340
00341 generate_kul_quit:
00342 return rval;
00343
00344 }
00345
00346 #else
00347 _KEYTOOLS_NOT_AVAILABLE
00348 #endif
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 int
00388 encode_keychange(const oid * hashtype, u_int hashtype_len,
00389 u_char * oldkey, size_t oldkey_len,
00390 u_char * newkey, size_t newkey_len,
00391 u_char * kcstring, size_t * kcstring_len)
00392 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_PKCS11)
00393 {
00394 int rval = SNMPERR_SUCCESS;
00395 size_t properlength;
00396 size_t nbytes = 0;
00397
00398 u_char *tmpbuf = NULL;
00399
00400
00401
00402
00403
00404 if (!hashtype || !oldkey || !newkey || !kcstring || !kcstring_len
00405 || (oldkey_len <= 0) || (newkey_len <= 0) || (*kcstring_len <= 0)
00406 || (hashtype_len != USM_LENGTH_OID_TRANSFORM)) {
00407 QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
00408 }
00409
00410
00411
00412
00413 properlength = sc_get_properlength(hashtype, hashtype_len);
00414 if (properlength == SNMPERR_GENERR)
00415 QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
00416
00417 if ((oldkey_len != newkey_len) || (*kcstring_len < (2 * oldkey_len))) {
00418 QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
00419 }
00420
00421 properlength = SNMP_MIN((int) oldkey_len, properlength);
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 nbytes = properlength;
00433
00434 #if defined(NETSNMP_ENABLE_TESTING_CODE) && defined(RANDOMZEROS)
00435 memset(kcstring, 0, nbytes);
00436 DEBUGMSG(("encode_keychange",
00437 "** Using all zero bits for \"random\" delta of )"
00438 "the keychange string! **\n"));
00439 #else
00440 rval = sc_random(kcstring, &nbytes);
00441 QUITFUN(rval, encode_keychange_quit);
00442 if ((int) nbytes != properlength) {
00443 QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
00444 }
00445 #endif
00446
00447 tmpbuf = (u_char *) malloc(properlength * 2);
00448 if (tmpbuf) {
00449 memcpy(tmpbuf, oldkey, properlength);
00450 memcpy(tmpbuf + properlength, kcstring, properlength);
00451
00452 *kcstring_len -= properlength;
00453 rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength * 2,
00454 kcstring + properlength, kcstring_len);
00455
00456 QUITFUN(rval, encode_keychange_quit);
00457
00458 *kcstring_len = (properlength * 2);
00459
00460 kcstring += properlength;
00461 nbytes = 0;
00462 while ((int) (nbytes++) < properlength) {
00463 *kcstring++ ^= *newkey++;
00464 }
00465 }
00466
00467 encode_keychange_quit:
00468 if (rval != SNMPERR_SUCCESS)
00469 memset(kcstring, 0, *kcstring_len);
00470 SNMP_FREE(tmpbuf);
00471
00472 return rval;
00473
00474 }
00475
00476 #else
00477 _KEYTOOLS_NOT_AVAILABLE
00478 #endif
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 int
00513 decode_keychange(const oid * hashtype, u_int hashtype_len,
00514 u_char * oldkey, size_t oldkey_len,
00515 u_char * kcstring, size_t kcstring_len,
00516 u_char * newkey, size_t * newkey_len)
00517 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_PKCS11)
00518 {
00519 int rval = SNMPERR_SUCCESS;
00520 size_t properlength = 0;
00521 int iproperlength = 0;
00522 u_int nbytes = 0;
00523
00524 u_char *bufp, tmp_buf[SNMP_MAXBUF];
00525 size_t tmp_buf_len = SNMP_MAXBUF;
00526 u_char *tmpbuf = NULL;
00527
00528
00529
00530
00531
00532
00533 if (!hashtype || !oldkey || !kcstring || !newkey || !newkey_len
00534 || (oldkey_len <= 0) || (kcstring_len <= 0) || (*newkey_len <= 0)
00535 || (hashtype_len != USM_LENGTH_OID_TRANSFORM)) {
00536 QUITFUN(SNMPERR_GENERR, decode_keychange_quit);
00537 }
00538
00539
00540
00541
00542
00543 iproperlength = sc_get_properlength(hashtype, hashtype_len);
00544 if (iproperlength == SNMPERR_GENERR)
00545 QUITFUN(SNMPERR_GENERR, decode_keychange_quit);
00546
00547 properlength = (size_t) iproperlength;
00548
00549 if (((oldkey_len * 2) != kcstring_len) || (*newkey_len < oldkey_len)) {
00550 QUITFUN(SNMPERR_GENERR, decode_keychange_quit);
00551 }
00552
00553 properlength = oldkey_len;
00554 *newkey_len = properlength;
00555
00556
00557
00558
00559
00560
00561
00562 tmpbuf = (u_char *) malloc(properlength * 2);
00563 if (tmpbuf) {
00564 memcpy(tmpbuf, oldkey, properlength);
00565 memcpy(tmpbuf + properlength, kcstring, properlength);
00566
00567 rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength * 2,
00568 tmp_buf, &tmp_buf_len);
00569 QUITFUN(rval, decode_keychange_quit);
00570
00571 memcpy(newkey, tmp_buf, properlength);
00572 bufp = kcstring + properlength;
00573 nbytes = 0;
00574 while ((int) (nbytes++) < properlength) {
00575 *newkey++ ^= *bufp++;
00576 }
00577 }
00578
00579 decode_keychange_quit:
00580 if (rval != SNMPERR_SUCCESS) {
00581 memset(newkey, 0, properlength);
00582 }
00583 memset(tmp_buf, 0, SNMP_MAXBUF);
00584 if (tmpbuf != NULL)
00585 SNMP_FREE(tmpbuf);
00586
00587 return rval;
00588
00589 }
00590
00591 #else
00592 _KEYTOOLS_NOT_AVAILABLE
00593 #endif