net-snmp 5.7
|
00001 /* Portions of this file are subject to the following copyright(s). See 00002 * the Net-SNMP's COPYING file for more details and other copyrights 00003 * that may apply: 00004 */ 00005 /* 00006 * Portions of this file are copyrighted by: 00007 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved. 00008 * Use is subject to license terms specified in the COPYING file 00009 * distributed with the Net-SNMP package. 00010 */ 00011 00012 /* 00013 * scapi.c 00014 * 00015 */ 00016 00017 #include <net-snmp/net-snmp-config.h> 00018 #include <net-snmp/net-snmp-features.h> 00019 00020 #include <sys/types.h> 00021 #ifdef HAVE_STDLIB_H 00022 #include <stdlib.h> 00023 #endif 00024 #if HAVE_STRING_H 00025 #include <string.h> 00026 #else 00027 #include <strings.h> 00028 #endif 00029 #if TIME_WITH_SYS_TIME 00030 # include <sys/time.h> 00031 # include <time.h> 00032 #else 00033 # if HAVE_SYS_TIME_H 00034 # include <sys/time.h> 00035 # else 00036 # include <time.h> 00037 # endif 00038 #endif 00039 #ifdef HAVE_NETINET_IN_H 00040 #include <netinet/in.h> 00041 #endif 00042 00043 #if HAVE_UNISTD_H 00044 #include <unistd.h> 00045 #endif 00046 #if HAVE_DMALLOC_H 00047 #include <dmalloc.h> 00048 #endif 00049 00050 #include <net-snmp/types.h> 00051 #include <net-snmp/output_api.h> 00052 #include <net-snmp/utilities.h> 00053 00054 netsnmp_feature_child_of(usm_support, libnetsnmp) 00055 netsnmp_feature_child_of(usm_scapi, usm_support) 00056 00057 #ifndef NETSNMP_FEATURE_REMOVE_USM_SCAPI 00058 00059 #ifdef NETSNMP_USE_INTERNAL_MD5 00060 #include <net-snmp/library/md5.h> 00061 #endif 00062 #include <net-snmp/library/snmp_api.h> 00063 #include <net-snmp/library/callback.h> 00064 #include <net-snmp/library/snmp_secmod.h> 00065 #include <net-snmp/library/snmpusm.h> 00066 #include <net-snmp/library/keytools.h> 00067 #include <net-snmp/library/scapi.h> 00068 #include <net-snmp/library/mib.h> 00069 #include <net-snmp/library/transform_oids.h> 00070 00071 #ifdef NETSNMP_USE_INTERNAL_CRYPTO 00072 #include <net-snmp/library/openssl_md5.h> 00073 #include <net-snmp/library/openssl_sha.h> 00074 #include <net-snmp/library/openssl_des.h> 00075 #include <net-snmp/library/openssl_aes.h> 00076 #endif 00077 00078 #ifdef NETSNMP_USE_OPENSSL 00079 #include <openssl/hmac.h> 00080 #include <openssl/evp.h> 00081 #include <openssl/rand.h> 00082 #include <openssl/des.h> 00083 #ifdef HAVE_AES 00084 #include <openssl/aes.h> 00085 #endif 00086 00087 #ifndef NETSNMP_DISABLE_DES 00088 #ifdef HAVE_STRUCT_DES_KS_STRUCT_WEAK_KEY 00089 /* these are older names for newer structures that exist in openssl .9.7 */ 00090 #define DES_key_schedule des_key_schedule 00091 #define DES_cblock des_cblock 00092 #define DES_key_sched des_key_sched 00093 #define DES_ncbc_encrypt des_ncbc_encrypt 00094 #define DES_cbc_encrypt des_cbc_encrypt 00095 #define OLD_DES 00096 #endif 00097 #endif 00098 00099 #endif /* HAVE_OPENSSL */ 00100 00101 #ifdef NETSNMP_USE_INTERNAL_CRYPTO 00102 #endif 00103 00104 #ifdef NETSNMP_USE_PKCS11 00105 #include <security/cryptoki.h> 00106 #endif 00107 00108 #ifdef QUITFUN 00109 #undef QUITFUN 00110 #define QUITFUN(e, l) \ 00111 if (e != SNMPERR_SUCCESS) { \ 00112 rval = SNMPERR_SC_GENERAL_FAILURE; \ 00113 goto l ; \ 00114 } 00115 #endif 00116 00117 #ifdef NETSNMP_USE_INTERNAL_CRYPTO 00118 static 00119 int SHA1_hmac(u_char * data, size_t len, u_char * mac, size_t maclen, 00120 u_char * secret, size_t secretlen); 00121 00122 static 00123 int MD5_hmac(u_char * data, size_t len, u_char * mac, size_t maclen, 00124 u_char * secret, size_t secretlen); 00125 #endif 00126 00127 /* 00128 * sc_get_properlength(oid *hashtype, u_int hashtype_len): 00129 * 00130 * Given a hashing type ("hashtype" and its length hashtype_len), return 00131 * the length of the hash result. 00132 * 00133 * Returns either the length or SNMPERR_GENERR for an unknown hashing type. 00134 */ 00135 int 00136 sc_get_properlength(const oid * hashtype, u_int hashtype_len) 00137 { 00138 DEBUGTRACE; 00139 /* 00140 * Determine transform type hash length. 00141 */ 00142 #ifndef NETSNMP_DISABLE_MD5 00143 if (ISTRANSFORM(hashtype, HMACMD5Auth)) { 00144 return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5); 00145 } else 00146 #endif 00147 if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { 00148 return BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1); 00149 } 00150 return SNMPERR_GENERR; 00151 } 00152 00153 netsnmp_feature_child_of(scapi_get_proper_priv_length, netsnmp_unused) 00154 #ifndef NETSNMP_FEATURE_REMOVE_SCAPI_GET_PROPER_PRIV_LENGTH 00155 int 00156 sc_get_proper_priv_length(const oid * privtype, u_int privtype_len) 00157 { 00158 int properlength = 0; 00159 #ifndef NETSNMP_DISABLE_DES 00160 if (ISTRANSFORM(privtype, DESPriv)) { 00161 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); 00162 } 00163 #endif 00164 #ifdef HAVE_AES 00165 if (ISTRANSFORM(privtype, AESPriv)) { 00166 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES); 00167 } 00168 #endif 00169 return properlength; 00170 } 00171 #endif /* NETSNMP_FEATURE_REMOVE_SCAPI_GET_PROPER_PRIV_LENGTH */ 00172 00173 00174 /*******************************************************************-o-****** 00175 * sc_init 00176 * 00177 * Returns: 00178 * SNMPERR_SUCCESS Success. 00179 */ 00180 int 00181 sc_init(void) 00182 { 00183 int rval = SNMPERR_SUCCESS; 00184 00185 #if !defined(NETSNMP_USE_OPENSSL) 00186 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00187 struct timeval tv; 00188 00189 DEBUGTRACE; 00190 00191 gettimeofday(&tv, (struct timezone *) 0); 00192 00193 srandom((unsigned)(tv.tv_sec ^ tv.tv_usec)); 00194 #elif NETSNMP_USE_PKCS11 00195 DEBUGTRACE; 00196 rval = pkcs_init(); 00197 #else 00198 rval = SNMPERR_SC_NOT_CONFIGURED; 00199 #endif /* NETSNMP_USE_INTERNAL_MD5 */ 00200 /* 00201 * XXX ogud: The only reason to do anything here with openssl is to 00202 * * XXX ogud: seed random number generator 00203 */ 00204 #endif /* ifndef NETSNMP_USE_OPENSSL */ 00205 return rval; 00206 } /* end sc_init() */ 00207 00208 /*******************************************************************-o-****** 00209 * sc_random 00210 * 00211 * Parameters: 00212 * *buf Pre-allocated buffer. 00213 * *buflen Size of buffer. 00214 * 00215 * Returns: 00216 * SNMPERR_SUCCESS Success. 00217 */ 00218 int 00219 sc_random(u_char * buf, size_t * buflen) 00220 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00221 { 00222 int rval = SNMPERR_SUCCESS; 00223 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00224 int i; 00225 int rndval; 00226 u_char *ucp = buf; 00227 #endif 00228 00229 DEBUGTRACE; 00230 00231 #ifdef NETSNMP_USE_OPENSSL 00232 RAND_bytes(buf, *buflen); /* will never fail */ 00233 #elif NETSNMP_USE_PKCS11 /* NETSNMP_USE_PKCS11 */ 00234 pkcs_random(buf, *buflen); 00235 #else /* NETSNMP_USE_INTERNAL_MD5 */ 00236 /* 00237 * fill the buffer with random integers. Note that random() 00238 * is defined in config.h and may not be truly the random() 00239 * system call if something better existed 00240 */ 00241 rval = *buflen - *buflen % sizeof(rndval); 00242 for (i = 0; i < rval; i += sizeof(rndval)) { 00243 rndval = random(); 00244 memcpy(ucp, &rndval, sizeof(rndval)); 00245 ucp += sizeof(rndval); 00246 } 00247 00248 rndval = random(); 00249 memcpy(ucp, &rndval, *buflen % sizeof(rndval)); 00250 00251 rval = SNMPERR_SUCCESS; 00252 #endif /* NETSNMP_USE_OPENSSL */ 00253 return rval; 00254 00255 } /* end sc_random() */ 00256 00257 #else 00258 _SCAPI_NOT_CONFIGURED 00259 #endif /* */ 00260 /*******************************************************************-o-****** 00261 * sc_generate_keyed_hash 00262 * 00263 * Parameters: 00264 * authtype Type of authentication transform. 00265 * authtypelen 00266 * *key Pointer to key (Kul) to use in keyed hash. 00267 * keylen Length of key in bytes. 00268 * *message Pointer to the message to hash. 00269 * msglen Length of the message. 00270 * *MAC Will be returned with allocated bytes containg hash. 00271 * *maclen Length of the hash buffer in bytes; also indicates 00272 * whether the MAC should be truncated. 00273 * 00274 * Returns: 00275 * SNMPERR_SUCCESS Success. 00276 * SNMPERR_GENERR All errs 00277 * 00278 * 00279 * A hash of the first msglen bytes of message using a keyed hash defined 00280 * by authtype is created and stored in MAC. MAC is ASSUMED to be a buffer 00281 * of at least maclen bytes. If the length of the hash is greater than 00282 * maclen, it is truncated to fit the buffer. If the length of the hash is 00283 * less than maclen, maclen set to the number of hash bytes generated. 00284 * 00285 * ASSUMED that the number of hash bits is a multiple of 8. 00286 */ 00287 int 00288 sc_generate_keyed_hash(const oid * authtype, size_t authtypelen, 00289 const u_char * key, u_int keylen, 00290 const u_char * message, u_int msglen, 00291 u_char * MAC, size_t * maclen) 00292 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00293 { 00294 int rval = SNMPERR_SUCCESS; 00295 int iproperlength; 00296 size_t properlength; 00297 00298 u_char buf[SNMP_MAXBUF_SMALL]; 00299 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) 00300 unsigned int buf_len = sizeof(buf); 00301 #endif 00302 00303 DEBUGTRACE; 00304 00305 #ifdef NETSNMP_ENABLE_TESTING_CODE 00306 { 00307 int i; 00308 DEBUGMSG(("sc_generate_keyed_hash", 00309 "sc_generate_keyed_hash(): key=0x")); 00310 for (i = 0; i < keylen; i++) 00311 DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff)); 00312 DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen)); 00313 } 00314 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 00315 00316 /* 00317 * Sanity check. 00318 */ 00319 if (!authtype || !key || !message || !MAC || !maclen 00320 || (keylen <= 0) || (msglen <= 0) || (*maclen <= 0) 00321 || (authtypelen != USM_LENGTH_OID_TRANSFORM)) { 00322 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00323 } 00324 00325 iproperlength = sc_get_properlength(authtype, authtypelen); 00326 if (iproperlength == SNMPERR_GENERR) 00327 return SNMPERR_GENERR; 00328 properlength = (size_t)iproperlength; 00329 if (keylen < properlength) { 00330 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00331 } 00332 #ifdef NETSNMP_USE_OPENSSL 00333 /* 00334 * Determine transform type. 00335 */ 00336 #ifndef NETSNMP_DISABLE_MD5 00337 if (ISTRANSFORM(authtype, HMACMD5Auth)) 00338 HMAC(EVP_md5(), key, keylen, message, msglen, buf, &buf_len); 00339 else 00340 #endif 00341 if (ISTRANSFORM(authtype, HMACSHA1Auth)) 00342 HMAC(EVP_sha1(), key, keylen, message, msglen, buf, &buf_len); 00343 else { 00344 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00345 } 00346 if (buf_len != properlength) { 00347 QUITFUN(rval, sc_generate_keyed_hash_quit); 00348 } 00349 if (*maclen > buf_len) 00350 *maclen = buf_len; 00351 memcpy(MAC, buf, *maclen); 00352 00353 #elif NETSNMP_USE_PKCS11 /* NETSNMP_USE_PKCS11 */ 00354 00355 #ifndef NETSNMP_DISABLE_MD5 00356 if (ISTRANSFORM(authtype, HMACMD5Auth)) { 00357 if (pkcs_sign(CKM_MD5_HMAC,key, keylen, message, 00358 msglen, buf, &buf_len) != SNMPERR_SUCCESS) { 00359 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00360 } 00361 } else 00362 #endif 00363 if (ISTRANSFORM(authtype, HMACSHA1Auth)) { 00364 if (pkcs_sign(CKM_SHA_1_HMAC,key, keylen, message, 00365 msglen, buf, &buf_len) != SNMPERR_SUCCESS) { 00366 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00367 } 00368 } else { 00369 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00370 } 00371 00372 if (buf_len != properlength) { 00373 QUITFUN(rval, sc_generate_keyed_hash_quit); 00374 } 00375 if (*maclen > buf_len) 00376 *maclen = buf_len; 00377 memcpy(MAC, buf, *maclen); 00378 00379 #elif NETSNMP_USE_INTERNAL_CRYPTO 00380 if (*maclen > properlength) 00381 *maclen = properlength; 00382 #ifndef NETSNMP_DISABLE_MD5 00383 if (ISTRANSFORM(authtype, HMACMD5Auth)) 00384 rval = MD5_hmac(message, msglen, MAC, *maclen, key, keylen); 00385 else 00386 #endif 00387 if (ISTRANSFORM(authtype, HMACSHA1Auth)) 00388 rval = SHA1_hmac(message, msglen, MAC, *maclen, key, keylen); 00389 else { 00390 QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit); 00391 } 00392 if (rval != 0) { 00393 rval = SNMPERR_GENERR; 00394 goto sc_generate_keyed_hash_quit; 00395 } 00396 #else /* NETSNMP_USE_INTERNAL_MD5 */ 00397 if (*maclen > properlength) 00398 *maclen = properlength; 00399 if (MDsign(message, msglen, MAC, *maclen, key, keylen)) { 00400 rval = SNMPERR_GENERR; 00401 goto sc_generate_keyed_hash_quit; 00402 } 00403 #endif /* NETSNMP_USE_OPENSSL */ 00404 00405 #ifdef NETSNMP_ENABLE_TESTING_CODE 00406 { 00407 char *s; 00408 int len = binary_to_hex(MAC, *maclen, &s); 00409 00410 DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s)); 00411 SNMP_ZERO(s, len); 00412 SNMP_FREE(s); 00413 } 00414 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 00415 00416 sc_generate_keyed_hash_quit: 00417 memset(buf, 0, SNMP_MAXBUF_SMALL); 00418 return rval; 00419 } /* end sc_generate_keyed_hash() */ 00420 00421 #else 00422 _SCAPI_NOT_CONFIGURED 00423 #endif /* */ 00424 /* 00425 * sc_hash(): a generic wrapper around whatever hashing package we are using. 00426 * 00427 * IN: 00428 * hashtype - oid pointer to a hash type 00429 * hashtypelen - length of oid pointer 00430 * buf - u_char buffer to be hashed 00431 * buf_len - integer length of buf data 00432 * MAC_len - length of the passed MAC buffer size. 00433 * 00434 * OUT: 00435 * MAC - pre-malloced space to store hash output. 00436 * MAC_len - length of MAC output to the MAC buffer. 00437 * 00438 * Returns: 00439 * SNMPERR_SUCCESS Success. 00440 * SNMP_SC_GENERAL_FAILURE Any error. 00441 */ 00442 int 00443 sc_hash(const oid * hashtype, size_t hashtypelen, const u_char * buf, 00444 size_t buf_len, u_char * MAC, size_t * MAC_len) 00445 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00446 { 00447 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00448 int rval = SNMPERR_SUCCESS; 00449 #endif 00450 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) 00451 unsigned int tmp_len; 00452 #endif 00453 int ret; 00454 00455 #ifdef NETSNMP_USE_OPENSSL 00456 const EVP_MD *hashfn; 00457 EVP_MD_CTX ctx, *cptr; 00458 #endif 00459 #ifdef NETSNMP_USE_INTERNAL_CRYPTO 00460 MD5_CTX cmd5; 00461 SHA_CTX csha1; 00462 #endif 00463 DEBUGTRACE; 00464 00465 if (hashtype == NULL || buf == NULL || buf_len <= 0 || 00466 MAC == NULL || MAC_len == NULL ) 00467 return (SNMPERR_GENERR); 00468 ret = sc_get_properlength(hashtype, hashtypelen); 00469 if (( ret < 0 ) || (*MAC_len < (size_t)ret )) 00470 return (SNMPERR_GENERR); 00471 00472 #ifdef NETSNMP_USE_OPENSSL 00473 /* 00474 * Determine transform type. 00475 */ 00476 #ifndef NETSNMP_DISABLE_MD5 00477 if (ISTRANSFORM(hashtype, HMACMD5Auth)) { 00478 hashfn = (const EVP_MD *) EVP_md5(); 00479 } else 00480 #endif 00481 if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { 00482 hashfn = (const EVP_MD *) EVP_sha1(); 00483 } else { 00484 return (SNMPERR_GENERR); 00485 } 00486 00488 memset(&ctx, 0, sizeof(ctx)); 00489 cptr = &ctx; 00490 #if defined(OLD_DES) 00491 EVP_DigestInit(cptr, hashfn); 00492 #else /* !OLD_DES */ 00493 /* this is needed if the runtime library is different than the compiled 00494 library since the openssl versions are very different. */ 00495 if (SSLeay() < 0x907000) { 00496 /* the old version of the struct was bigger and thus more 00497 memory is needed. should be 152, but we use 256 for safety. */ 00498 cptr = (EVP_MD_CTX *)malloc(256); 00499 EVP_DigestInit(cptr, hashfn); 00500 } else { 00501 EVP_MD_CTX_init(cptr); 00502 EVP_DigestInit(cptr, hashfn); 00503 } 00504 #endif 00505 00507 EVP_DigestUpdate(cptr, buf, buf_len); 00508 00510 #if defined(OLD_DES) 00511 EVP_DigestFinal(cptr, MAC, &tmp_len); 00512 *MAC_len = tmp_len; 00513 #else /* !OLD_DES */ 00514 if (SSLeay() < 0x907000) { 00515 EVP_DigestFinal(cptr, MAC, &tmp_len); 00516 *MAC_len = tmp_len; 00517 free(cptr); 00518 } else { 00519 EVP_DigestFinal_ex(cptr, MAC, &tmp_len); 00520 *MAC_len = tmp_len; 00521 EVP_MD_CTX_cleanup(cptr); 00522 } 00523 #endif /* OLD_DES */ 00524 return (rval); 00525 00526 #elif NETSNMP_USE_INTERNAL_CRYPTO 00527 #ifndef NETSNMP_DISABLE_MD5 00528 if (ISTRANSFORM(hashtype, HMACMD5Auth)) { 00529 if (*MAC_len < MD5_DIGEST_LENGTH) 00530 return (SNMPERR_GENERR); /* the buffer isn't big enough */ 00531 MD5_Init(&cmd5); 00532 MD5_Update(&cmd5, buf, buf_len); 00533 MD5_Final(MAC, &cmd5); 00534 *MAC_len = MD5_DIGEST_LENGTH; 00535 } else 00536 #endif 00537 if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { 00538 if (*MAC_len < SHA_DIGEST_LENGTH) 00539 return (SNMPERR_GENERR); /* the buffer isn't big enough */ 00540 SHA1_Init(&csha1); 00541 SHA1_Update(&csha1, buf, buf_len); 00542 SHA1_Final(MAC, &csha1); 00543 *MAC_len = SHA_DIGEST_LENGTH; 00544 00545 } else { 00546 return (SNMPERR_GENERR); 00547 } 00548 return (rval); 00549 #elif NETSNMP_USE_PKCS11 /* NETSNMP_USE_PKCS11 */ 00550 00551 #ifndef NETSNMP_DISABLE_MD5 00552 if (ISTRANSFORM(hashtype, HMACMD5Auth)) { 00553 rval = pkcs_digest(CKM_MD5, buf, buf_len, MAC, &tmp_len); 00554 *MAC_len = tmp_len; 00555 } else 00556 #endif 00557 if (ISTRANSFORM(hashtype, HMACSHA1Auth)) { 00558 rval = pkcs_digest(CKM_SHA_1, buf, buf_len, MAC, &tmp_len); 00559 *MAC_len = tmp_len; 00560 } else { 00561 return (SNMPERR_GENERR); 00562 } 00563 00564 return (rval); 00565 00566 #else /* NETSNMP_USE_INTERNAL_MD5 */ 00567 00568 if (MDchecksum(buf, buf_len, MAC, *MAC_len)) { 00569 return SNMPERR_GENERR; 00570 } 00571 if (*MAC_len > 16) 00572 *MAC_len = 16; 00573 return SNMPERR_SUCCESS; 00574 00575 #endif /* NETSNMP_USE_OPENSSL */ 00576 } 00577 #else /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */ 00578 _SCAPI_NOT_CONFIGURED 00579 #endif /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */ 00580 /*******************************************************************-o-****** 00581 * sc_check_keyed_hash 00582 * 00583 * Parameters: 00584 * authtype Transform type of authentication hash. 00585 * *key Key bits in a string of bytes. 00586 * keylen Length of key in bytes. 00587 * *message Message for which to check the hash. 00588 * msglen Length of message. 00589 * *MAC Given hash. 00590 * maclen Length of given hash; indicates truncation if it is 00591 * shorter than the normal size of output for 00592 * given hash transform. 00593 * Returns: 00594 * SNMPERR_SUCCESS Success. 00595 * SNMP_SC_GENERAL_FAILURE Any error 00596 * 00597 * 00598 * Check the hash given in MAC against the hash of message. If the length 00599 * of MAC is less than the length of the transform hash output, only maclen 00600 * bytes are compared. The length of MAC cannot be greater than the 00601 * length of the hash transform output. 00602 */ 00603 int 00604 sc_check_keyed_hash(const oid * authtype, size_t authtypelen, 00605 const u_char * key, u_int keylen, 00606 const u_char * message, u_int msglen, 00607 const u_char * MAC, u_int maclen) 00608 #if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00609 { 00610 int rval = SNMPERR_SUCCESS; 00611 size_t buf_len = SNMP_MAXBUF_SMALL; 00612 00613 u_char buf[SNMP_MAXBUF_SMALL]; 00614 00615 DEBUGTRACE; 00616 00617 #ifdef NETSNMP_ENABLE_TESTING_CODE 00618 { 00619 int i; 00620 DEBUGMSG(("scapi", "sc_check_keyed_hash(): key=0x")); 00621 for (i = 0; i < keylen; i++) 00622 DEBUGMSG(("scapi", "%02x", key[i] & 0xff)); 00623 DEBUGMSG(("scapi", " (%d)\n", keylen)); 00624 } 00625 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 00626 00627 /* 00628 * Sanity check. 00629 */ 00630 if (!authtype || !key || !message || !MAC 00631 || (keylen <= 0) || (msglen <= 0) || (maclen <= 0) 00632 || (authtypelen != USM_LENGTH_OID_TRANSFORM)) { 00633 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); 00634 } 00635 00636 00637 if (maclen != USM_MD5_AND_SHA_AUTH_LEN) { 00638 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); 00639 } 00640 00641 /* 00642 * Generate a full hash of the message, then compare 00643 * the result with the given MAC which may shorter than 00644 * the full hash length. 00645 */ 00646 rval = sc_generate_keyed_hash(authtype, authtypelen, 00647 key, keylen, 00648 message, msglen, buf, &buf_len); 00649 QUITFUN(rval, sc_check_keyed_hash_quit); 00650 00651 if (maclen > msglen) { 00652 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); 00653 00654 } else if (memcmp(buf, MAC, maclen) != 0) { 00655 QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit); 00656 } 00657 00658 00659 sc_check_keyed_hash_quit: 00660 memset(buf, 0, SNMP_MAXBUF_SMALL); 00661 00662 return rval; 00663 00664 } /* end sc_check_keyed_hash() */ 00665 00666 #else 00667 _SCAPI_NOT_CONFIGURED 00668 #endif /* NETSNMP_USE_INTERNAL_MD5 */ 00669 /*******************************************************************-o-****** 00670 * sc_encrypt 00671 * 00672 * Parameters: 00673 * privtype Type of privacy cryptographic transform. 00674 * *key Key bits for crypting. 00675 * keylen Length of key (buffer) in bytes. 00676 * *iv IV bits for crypting. 00677 * ivlen Length of iv (buffer) in bytes. 00678 * *plaintext Plaintext to crypt. 00679 * ptlen Length of plaintext. 00680 * *ciphertext Ciphertext to crypt. 00681 * *ctlen Length of ciphertext. 00682 * 00683 * Returns: 00684 * SNMPERR_SUCCESS Success. 00685 * SNMPERR_SC_NOT_CONFIGURED Encryption is not supported. 00686 * SNMPERR_SC_GENERAL_FAILURE Any other error 00687 * 00688 * 00689 * Encrypt plaintext into ciphertext using key and iv. 00690 * 00691 * ctlen contains actual number of crypted bytes in ciphertext upon 00692 * successful return. 00693 */ 00694 int 00695 sc_encrypt(const oid * privtype, size_t privtypelen, 00696 u_char * key, u_int keylen, 00697 u_char * iv, u_int ivlen, 00698 const u_char * plaintext, u_int ptlen, 00699 u_char * ciphertext, size_t * ctlen) 00700 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00701 { 00702 int rval = SNMPERR_SUCCESS; 00703 u_int properlength = 0, properlength_iv = 0; 00704 u_char pad_block[128]; /* bigger than anything I need */ 00705 u_char my_iv[128]; /* ditto */ 00706 int pad, plast, pad_size = 0; 00707 int have_trans; 00708 #ifndef NETSNMP_DISABLE_DES 00709 #ifdef OLD_DES 00710 DES_key_schedule key_sch; 00711 #else 00712 DES_key_schedule key_sched_store; 00713 DES_key_schedule *key_sch = &key_sched_store; 00714 #endif 00715 DES_cblock key_struct; 00716 #endif 00717 #ifdef HAVE_AES 00718 AES_KEY aes_key; 00719 int new_ivlen = 0; 00720 #endif 00721 00722 DEBUGTRACE; 00723 00724 /* 00725 * Sanity check. 00726 */ 00727 #if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV) 00728 snmp_log(LOG_ERR, "Encryption support not enabled.\n"); 00729 return SNMPERR_SC_NOT_CONFIGURED; 00730 #endif 00731 00732 if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen 00733 || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0) 00734 || (privtypelen != USM_LENGTH_OID_TRANSFORM)) { 00735 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00736 } else if (ptlen > *ctlen) { 00737 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00738 } 00739 #ifdef NETSNMP_ENABLE_TESTING_CODE 00740 { 00741 size_t buf_len = 128, out_len = 0; 00742 u_char *buf = (u_char *) malloc(buf_len); 00743 00744 if (buf != NULL) { 00745 if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, 00746 iv, ivlen)) { 00747 DEBUGMSGTL(("scapi", "encrypt: IV: %s/", buf)); 00748 } else { 00749 DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]/", buf)); 00750 } 00751 out_len = 0; 00752 if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, 00753 key, keylen)) { 00754 DEBUGMSG(("scapi", "%s\n", buf)); 00755 } else { 00756 DEBUGMSG(("scapi", "%s [TRUNCATED]\n", buf)); 00757 } 00758 out_len = 0; 00759 if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, 00760 plaintext, 16)) { 00761 DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf)); 00762 } else { 00763 DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n", 00764 buf)); 00765 } 00766 free(buf); 00767 } else { 00768 DEBUGMSGTL(("scapi", 00769 "encrypt: malloc fail for debug output\n")); 00770 } 00771 } 00772 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 00773 00774 00775 /* 00776 * Determine privacy transform. 00777 */ 00778 have_trans = 0; 00779 #ifndef NETSNMP_DISABLE_DES 00780 if (ISTRANSFORM(privtype, DESPriv)) { 00781 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); 00782 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); 00783 pad_size = properlength; 00784 have_trans = 1; 00785 } 00786 #endif 00787 #ifdef HAVE_AES 00788 if (ISTRANSFORM(privtype, AESPriv)) { 00789 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES); 00790 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES_IV); 00791 have_trans = 1; 00792 } 00793 #endif 00794 if (!have_trans) { 00795 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00796 } 00797 00798 if ((keylen < properlength) || (ivlen < properlength_iv)) { 00799 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00800 } 00801 00802 memset(my_iv, 0, sizeof(my_iv)); 00803 00804 #ifndef NETSNMP_DISABLE_DES 00805 if (ISTRANSFORM(privtype, DESPriv)) { 00806 00807 /* 00808 * now calculate the padding needed 00809 */ 00810 pad = pad_size - (ptlen % pad_size); 00811 plast = (int) ptlen - (pad_size - pad); 00812 if (pad == pad_size) 00813 pad = 0; 00814 if (ptlen + pad > *ctlen) { 00815 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); /* not enough space */ 00816 } 00817 if (pad > 0) { /* copy data into pad block if needed */ 00818 memcpy(pad_block, plaintext + plast, pad_size - pad); 00819 memset(&pad_block[pad_size - pad], pad, pad); /* filling in padblock */ 00820 } 00821 00822 memcpy(key_struct, key, sizeof(key_struct)); 00823 (void) DES_key_sched(&key_struct, key_sch); 00824 00825 memcpy(my_iv, iv, ivlen); 00826 /* 00827 * encrypt the data 00828 */ 00829 DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch, 00830 (DES_cblock *) my_iv, DES_ENCRYPT); 00831 if (pad > 0) { 00832 /* 00833 * then encrypt the pad block 00834 */ 00835 DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size, 00836 key_sch, (DES_cblock *) my_iv, DES_ENCRYPT); 00837 *ctlen = plast + pad_size; 00838 } else { 00839 *ctlen = plast; 00840 } 00841 } 00842 #endif 00843 #ifdef HAVE_AES 00844 if (ISTRANSFORM(privtype, AESPriv)) { 00845 (void) AES_set_encrypt_key(key, properlength*8, &aes_key); 00846 00847 memcpy(my_iv, iv, ivlen); 00848 /* 00849 * encrypt the data 00850 */ 00851 AES_cfb128_encrypt(plaintext, ciphertext, ptlen, 00852 &aes_key, my_iv, &new_ivlen, AES_ENCRYPT); 00853 *ctlen = ptlen; 00854 } 00855 #endif 00856 sc_encrypt_quit: 00857 /* 00858 * clear memory just in case 00859 */ 00860 memset(my_iv, 0, sizeof(my_iv)); 00861 memset(pad_block, 0, sizeof(pad_block)); 00862 #ifndef NETSNMP_DISABLE_DES 00863 memset(key_struct, 0, sizeof(key_struct)); 00864 #ifdef OLD_DES 00865 memset(&key_sch, 0, sizeof(key_sch)); 00866 #else 00867 memset(&key_sched_store, 0, sizeof(key_sched_store)); 00868 #endif 00869 #endif 00870 #ifdef HAVE_AES 00871 memset(&aes_key,0,sizeof(aes_key)); 00872 #endif 00873 return rval; 00874 00875 } /* end sc_encrypt() */ 00876 #elif defined(NETSNMP_USE_PKCS11) 00877 { 00878 int rval = SNMPERR_SUCCESS; 00879 u_int properlength, properlength_iv; 00880 u_char pkcs_des_key[8]; 00881 00882 DEBUGTRACE; 00883 00884 /* 00885 * Sanity check. 00886 */ 00887 #if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV) 00888 snmp_log(LOG_ERR, "Encryption support not enabled.\n"); 00889 return SNMPERR_SC_NOT_CONFIGURED; 00890 #endif 00891 00892 if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen 00893 || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0) 00894 || (privtypelen != USM_LENGTH_OID_TRANSFORM)) { 00895 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00896 } else if (ptlen > *ctlen) { 00897 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00898 } 00899 00900 /* 00901 * Determine privacy transform. 00902 */ 00903 if (ISTRANSFORM(privtype, DESPriv)) { 00904 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); 00905 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); 00906 } else { 00907 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00908 } 00909 00910 if ((keylen < properlength) || (ivlen < properlength_iv)) { 00911 QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); 00912 } 00913 00914 if (ISTRANSFORM(privtype, DESPriv)) { 00915 memset(pkcs_des_key, 0, sizeof(pkcs_des_key)); 00916 memcpy(pkcs_des_key, key, sizeof(pkcs_des_key)); 00917 rval = pkcs_encrpyt(CKM_DES_CBC, pkcs_des_key, 00918 sizeof(pkcs_des_key), iv, ivlen, plaintext, ptlen, 00919 ciphertext, ctlen); 00920 } 00921 00922 sc_encrypt_quit: 00923 return rval; 00924 } 00925 #else 00926 { 00927 # if NETSNMP_USE_INTERNAL_MD5 00928 { 00929 snmp_log(LOG_ERR, "Encryption support not enabled.\n"); 00930 DEBUGMSGTL(("scapi", "Encrypt function not defined.\n")); 00931 return SNMPERR_SC_GENERAL_FAILURE; 00932 } 00933 00934 # else 00935 _SCAPI_NOT_CONFIGURED 00936 # endif /* NETSNMP_USE_INTERNAL_MD5 */ 00937 } 00938 #endif /* */ 00939 00940 00941 00942 /*******************************************************************-o-****** 00943 * sc_decrypt 00944 * 00945 * Parameters: 00946 * privtype 00947 * *key 00948 * keylen 00949 * *iv 00950 * ivlen 00951 * *ciphertext 00952 * ctlen 00953 * *plaintext 00954 * *ptlen 00955 * 00956 * Returns: 00957 * SNMPERR_SUCCESS Success. 00958 * SNMPERR_SC_NOT_CONFIGURED Encryption is not supported. 00959 * SNMPERR_SC_GENERAL_FAILURE Any other error 00960 * 00961 * 00962 * Decrypt ciphertext into plaintext using key and iv. 00963 * 00964 * ptlen contains actual number of plaintext bytes in plaintext upon 00965 * successful return. 00966 */ 00967 int 00968 sc_decrypt(const oid * privtype, size_t privtypelen, 00969 u_char * key, u_int keylen, 00970 u_char * iv, u_int ivlen, 00971 u_char * ciphertext, u_int ctlen, 00972 u_char * plaintext, size_t * ptlen) 00973 #if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO) 00974 { 00975 00976 int rval = SNMPERR_SUCCESS; 00977 u_char my_iv[128]; 00978 #ifndef NETSNMP_DISABLE_DES 00979 #ifdef OLD_DES 00980 DES_key_schedule key_sch; 00981 #else 00982 DES_key_schedule key_sched_store; 00983 DES_key_schedule *key_sch = &key_sched_store; 00984 #endif 00985 DES_cblock key_struct; 00986 #endif 00987 u_int properlength = 0, properlength_iv = 0; 00988 int have_transform; 00989 #ifdef HAVE_AES 00990 int new_ivlen = 0; 00991 AES_KEY aes_key; 00992 #endif 00993 00994 DEBUGTRACE; 00995 00996 if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen 00997 || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen) 00998 || (privtypelen != USM_LENGTH_OID_TRANSFORM)) { 00999 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); 01000 } 01001 #ifdef NETSNMP_ENABLE_TESTING_CODE 01002 { 01003 size_t buf_len = 128, out_len = 0; 01004 u_char *buf = (u_char *) malloc(buf_len); 01005 01006 if (buf != NULL) { 01007 if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, 01008 iv, ivlen)) { 01009 DEBUGMSGTL(("scapi", "decrypt: IV: %s/", buf)); 01010 } else { 01011 DEBUGMSGTL(("scapi", "decrypt: IV: %s [TRUNCATED]/", buf)); 01012 } 01013 out_len = 0; 01014 if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, 01015 key, keylen)) { 01016 DEBUGMSG(("scapi", "%s\n", buf)); 01017 } else { 01018 DEBUGMSG(("scapi", "%s\n", buf)); 01019 } 01020 free(buf); 01021 } else { 01022 DEBUGMSGTL(("scapi", 01023 "decrypt: malloc fail for debug output\n")); 01024 } 01025 } 01026 #endif /* NETSNMP_ENABLE_TESTING_CODE */ 01027 01028 /* 01029 * Determine privacy transform. 01030 */ 01031 have_transform = 0; 01032 #ifndef NETSNMP_DISABLE_DES 01033 if (ISTRANSFORM(privtype, DESPriv)) { 01034 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); 01035 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); 01036 have_transform = 1; 01037 } 01038 #endif 01039 #ifdef HAVE_AES 01040 if (ISTRANSFORM(privtype, AESPriv)) { 01041 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES); 01042 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES_IV); 01043 have_transform = 1; 01044 } 01045 #endif 01046 if (!have_transform) { 01047 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); 01048 } 01049 01050 if ((keylen < properlength) || (ivlen < properlength_iv)) { 01051 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); 01052 } 01053 01054 memset(my_iv, 0, sizeof(my_iv)); 01055 #ifndef NETSNMP_DISABLE_DES 01056 if (ISTRANSFORM(privtype, DESPriv)) { 01057 memcpy(key_struct, key, sizeof(key_struct)); 01058 (void) DES_key_sched(&key_struct, key_sch); 01059 01060 memcpy(my_iv, iv, ivlen); 01061 DES_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch, 01062 (DES_cblock *) my_iv, DES_DECRYPT); 01063 *ptlen = ctlen; 01064 } 01065 #endif 01066 #ifdef HAVE_AES 01067 if (ISTRANSFORM(privtype, AESPriv)) { 01068 (void) AES_set_encrypt_key(key, properlength*8, &aes_key); 01069 01070 memcpy(my_iv, iv, ivlen); 01071 /* 01072 * encrypt the data 01073 */ 01074 AES_cfb128_encrypt(ciphertext, plaintext, ctlen, 01075 &aes_key, my_iv, &new_ivlen, AES_DECRYPT); 01076 *ptlen = ctlen; 01077 } 01078 #endif 01079 01080 /* 01081 * exit cond 01082 */ 01083 sc_decrypt_quit: 01084 #ifndef NETSNMP_DISABLE_DES 01085 #ifdef OLD_DES 01086 memset(&key_sch, 0, sizeof(key_sch)); 01087 #else 01088 memset(&key_sched_store, 0, sizeof(key_sched_store)); 01089 #endif 01090 memset(key_struct, 0, sizeof(key_struct)); 01091 #endif 01092 memset(my_iv, 0, sizeof(my_iv)); 01093 return rval; 01094 } /* USE OPEN_SSL */ 01095 #elif NETSNMP_USE_PKCS11 /* USE PKCS */ 01096 { 01097 int rval = SNMPERR_SUCCESS; 01098 u_int properlength, properlength_iv; 01099 u_char pkcs_des_key[8]; 01100 01101 DEBUGTRACE; 01102 01103 if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen 01104 || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen) 01105 || (privtypelen != USM_LENGTH_OID_TRANSFORM)) { 01106 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); 01107 } 01108 01109 /* 01110 * Determine privacy transform. 01111 */ 01112 if (ISTRANSFORM(privtype, DESPriv)) { 01113 properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); 01114 properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); 01115 } else { 01116 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); 01117 } 01118 01119 if ((keylen < properlength) || (ivlen < properlength_iv)) { 01120 QUITFUN(SNMPERR_GENERR, sc_decrypt_quit); 01121 } 01122 01123 if (ISTRANSFORM(privtype, DESPriv)) { 01124 memset(pkcs_des_key, 0, sizeof(pkcs_des_key)); 01125 memcpy(pkcs_des_key, key, sizeof(pkcs_des_key)); 01126 rval = pkcs_decrpyt(CKM_DES_CBC, pkcs_des_key, 01127 sizeof(pkcs_des_key), iv, ivlen, ciphertext, 01128 ctlen, plaintext, ptlen); 01129 *ptlen = ctlen; 01130 } 01131 01132 sc_decrypt_quit: 01133 return rval; 01134 } /* USE PKCS */ 01135 #else 01136 { 01137 #if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV) 01138 snmp_log(LOG_ERR, "Encryption support not enabled.\n"); 01139 return SNMPERR_SC_NOT_CONFIGURED; 01140 #else 01141 # if NETSNMP_USE_INTERNAL_MD5 01142 { 01143 DEBUGMSGTL(("scapi", "Decryption function not defined.\n")); 01144 return SNMPERR_SC_GENERAL_FAILURE; 01145 } 01146 01147 # else 01148 _SCAPI_NOT_CONFIGURED 01149 # endif /* NETSNMP_USE_INTERNAL_MD5 */ 01150 #endif /* */ 01151 } 01152 #endif /* NETSNMP_USE_OPENSSL */ 01153 01154 #ifdef NETSNMP_USE_INTERNAL_CRYPTO 01155 01156 /* These functions are basically copies of the MDSign() routine in 01157 md5.c modified to be used with the OpenSSL hashing functions. The 01158 copyright below is from the md5.c file that these functions were 01159 taken from: */ 01160 01161 /* 01162 * ** ************************************************************************** 01163 * ** md5.c -- Implementation of MD5 Message Digest Algorithm ** 01164 * ** Updated: 2/16/90 by Ronald L. Rivest ** 01165 * ** (C) 1990 RSA Data Security, Inc. ** 01166 * ** ************************************************************************** 01167 */ 01168 01169 /* 01170 * MD5_hmac(data, len, MD5): do a checksum on an arbirtrary amount 01171 * of data, and prepended with a secret in the standard fashion 01172 */ 01173 static int 01174 MD5_hmac(u_char * data, size_t len, u_char * mac, size_t maclen, 01175 u_char * secret, size_t secretlen) 01176 { 01177 #define MD5_HASHKEYLEN 64 01178 #define MD5_SECRETKEYLEN 16 01179 01180 MD5_CTX cmd5; 01181 u_char K1[MD5_HASHKEYLEN]; 01182 u_char K2[MD5_HASHKEYLEN]; 01183 u_char extendedAuthKey[MD5_HASHKEYLEN]; 01184 u_char buf[MD5_HASHKEYLEN]; 01185 size_t i; 01186 u_char *cp, *newdata = NULL; 01187 int rc = 0; 01188 01189 /* 01190 * memset(K1,0,MD5_HASHKEYLEN); 01191 * memset(K2,0,MD5_HASHKEYLEN); 01192 * memset(buf,0,MD5_HASHKEYLEN); 01193 * memset(extendedAuthKey,0,MD5_HASHKEYLEN); 01194 */ 01195 01196 if (secretlen != MD5_SECRETKEYLEN || secret == NULL || 01197 mac == NULL || data == NULL || 01198 len <= 0 || maclen <= 0) { 01199 /* 01200 * DEBUGMSGTL(("md5","MD5 signing not properly initialized")); 01201 */ 01202 return -1; 01203 } 01204 01205 memset(extendedAuthKey, 0, MD5_HASHKEYLEN); 01206 memcpy(extendedAuthKey, secret, secretlen); 01207 for (i = 0; i < MD5_HASHKEYLEN; i++) { 01208 K1[i] = extendedAuthKey[i] ^ 0x36; 01209 K2[i] = extendedAuthKey[i] ^ 0x5c; 01210 } 01211 01212 MD5_Init(&cmd5); 01213 rc = !MD5_Update(&cmd5, K1, MD5_HASHKEYLEN); 01214 if (rc) 01215 goto update_end; 01216 01217 i = len; 01218 if (((uintptr_t) data) % sizeof(long) != 0) { 01219 /* 01220 * this relies on the ability to use integer math and thus we 01221 * must rely on data that aligns on 32-bit-word-boundries 01222 */ 01223 memdup(&newdata, data, len); 01224 cp = newdata; 01225 } else { 01226 cp = data; 01227 } 01228 01229 while (i >= 64) { 01230 rc = !MD5_Update(&cmd5, cp, 64); 01231 if (rc) 01232 goto update_end; 01233 cp += 64; 01234 i -= 64; 01235 } 01236 01237 rc = !MD5_Update(&cmd5, cp, i); 01238 if (rc) 01239 goto update_end; 01240 01241 memset(buf, 0, MD5_HASHKEYLEN); 01242 MD5_Final(buf, &cmd5); 01243 01244 MD5_Init(&cmd5); 01245 rc = !MD5_Update(&cmd5, K2, MD5_HASHKEYLEN); 01246 if (rc) 01247 goto update_end; 01248 rc = !MD5_Update(&cmd5, buf, MD5_SECRETKEYLEN); 01249 if (rc) 01250 goto update_end; 01251 01252 /* 01253 * copy the sign checksum to the outgoing pointer 01254 */ 01255 MD5_Final(buf, &cmd5); 01256 memcpy(mac, buf, maclen); 01257 01258 update_end: 01259 memset(buf, 0, MD5_HASHKEYLEN); 01260 memset(K1, 0, MD5_HASHKEYLEN); 01261 memset(K2, 0, MD5_HASHKEYLEN); 01262 memset(extendedAuthKey, 0, MD5_HASHKEYLEN); 01263 memset(&cmd5, 0, sizeof(cmd5)); 01264 01265 if (newdata) 01266 free(newdata); 01267 return rc; 01268 } 01269 01270 static int 01271 SHA1_hmac(u_char * data, size_t len, u_char * mac, size_t maclen, 01272 u_char * secret, size_t secretlen) 01273 { 01274 #define SHA1_HASHKEYLEN 64 01275 #define SHA1_SECRETKEYLEN 20 01276 01277 SHA_CTX csha1; 01278 u_char K1[SHA1_HASHKEYLEN]; 01279 u_char K2[SHA1_HASHKEYLEN]; 01280 u_char extendedAuthKey[SHA1_HASHKEYLEN]; 01281 u_char buf[SHA1_HASHKEYLEN]; 01282 size_t i; 01283 u_char *cp, *newdata = NULL; 01284 int rc = 0; 01285 01286 /* 01287 * memset(K1,0,SHA1_HASHKEYLEN); 01288 * memset(K2,0,SHA1_HASHKEYLEN); 01289 * memset(buf,0,SHA1_HASHKEYLEN); 01290 * memset(extendedAuthKey,0,SHA1_HASHKEYLEN); 01291 */ 01292 01293 if (secretlen != SHA1_SECRETKEYLEN || secret == NULL || 01294 mac == NULL || data == NULL || 01295 len <= 0 || maclen <= 0) { 01296 /* 01297 * DEBUGMSGTL(("sha1","SHA1 signing not properly initialized")); 01298 */ 01299 return -1; 01300 } 01301 01302 memset(extendedAuthKey, 0, SHA1_HASHKEYLEN); 01303 memcpy(extendedAuthKey, secret, secretlen); 01304 for (i = 0; i < SHA1_HASHKEYLEN; i++) { 01305 K1[i] = extendedAuthKey[i] ^ 0x36; 01306 K2[i] = extendedAuthKey[i] ^ 0x5c; 01307 } 01308 01309 SHA1_Init(&csha1); 01310 rc = !SHA1_Update(&csha1, K1, SHA1_HASHKEYLEN); 01311 if (rc) 01312 goto update_end; 01313 01314 i = len; 01315 if (((uintptr_t) data) % sizeof(long) != 0) { 01316 /* 01317 * this relies on the ability to use integer math and thus we 01318 * must rely on data that aligns on 32-bit-word-boundries 01319 */ 01320 memdup(&newdata, data, len); 01321 cp = newdata; 01322 } else { 01323 cp = data; 01324 } 01325 01326 while (i >= 64) { 01327 rc = !SHA1_Update(&csha1, cp, 64); 01328 if (rc) 01329 goto update_end; 01330 cp += 64; 01331 i -= 64; 01332 } 01333 01334 rc = !SHA1_Update(&csha1, cp, i); 01335 if (rc) 01336 goto update_end; 01337 01338 memset(buf, 0, SHA1_HASHKEYLEN); 01339 SHA1_Final(buf, &csha1); 01340 01341 SHA1_Init(&csha1); 01342 rc = !SHA1_Update(&csha1, K2, SHA1_HASHKEYLEN); 01343 if (rc) 01344 goto update_end; 01345 rc = !SHA1_Update(&csha1, buf, SHA1_SECRETKEYLEN); 01346 if (rc) 01347 goto update_end; 01348 01349 /* 01350 * copy the sign checksum to the outgoing pointer 01351 */ 01352 SHA1_Final(buf, &csha1); 01353 memcpy(mac, buf, maclen); 01354 01355 update_end: 01356 memset(buf, 0, SHA1_HASHKEYLEN); 01357 memset(K1, 0, SHA1_HASHKEYLEN); 01358 memset(K2, 0, SHA1_HASHKEYLEN); 01359 memset(extendedAuthKey, 0, SHA1_HASHKEYLEN); 01360 memset(&csha1, 0, sizeof(csha1)); 01361 01362 if (newdata) 01363 free(newdata); 01364 return rc; 01365 } 01366 #endif /* NETSNMP_USE_INTERNAL_CRYPTO */ 01367 #endif /* NETSNMP_FEATURE_REMOVE_USM_SCAPI */