Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
keytools.c
Package: snmp.src.rar [view]
Upload User: cxs890
Upload Date: 2021-05-22
Package Size: 347k
Code Size: 17k
Category:
SNMP
Development Platform:
C/C++
- /*
- * keytools.c
- */
- #include <config.h>
- #include <stdio.h>
- #include <sys/types.h>
- #if HAVE_WINSOCK_H
- #include <ip/socket.h>
- #endif
- #ifdef HAVE_NETINET_IN_H
- #include <netinet/in.h>
- #endif
- #ifdef HAVE_STDLIB_H
- #include <stdlib.h>
- #endif
- #if HAVE_STRING_H
- #include <string.h>
- #else
- #include <strings.h>
- #endif
- #if HAVE_DMALLOC_H
- #include <dmalloc.h>
- #endif
- #include "asn1.h"
- #include "snmp_api.h"
- #ifdef USE_OPENSSL
- # include <openssl/hmac.h>
- #else
- #ifdef USE_INTERNAL_MD5
- /*#include "md5.h"*/
- #include <libsys/md5.h>
- #ifdef SWITCH
- #include <libsys/sha.h>
- #endif
- #endif
- #endif
- #include "scapi.h"
- #include "keytools.h"
- #include "tools.h"
- #include "snmp_debug.h"
- #include "snmp_logging.h"
- #include "transform_oids.h"
- typedef (*HASH_INIT_FUNC)(void *ctx);
- typedef (*HASH_UPDATE_FUNC)(void *ctx, unsigned char *dataIn, int len);
- typedef (*HASH_FINAL_FUNC)(unsigned char *hashout, void *ctx);
- /*******************************************************************-o-******
- * generate_Ku
- *
- * Parameters:
- * *hashtype MIB OID for the transform type for hashing.
- * hashtype_len Length of OID value.
- * *P Pre-allocated bytes of passpharase.
- * pplen Length of passphrase.
- * *Ku Buffer to contain Ku.
- * *kulen Length of Ku buffer.
- *
- * Returns:
- * SNMPERR_SUCCESS Success.
- * SNMPERR_GENERR All errors.
- *
- *
- * Convert a passphrase into a master user key, Ku, according to the
- * algorithm given in RFC 2274 concerning the SNMPv3 User Security Model (USM)
- * as follows:
- *
- * Expand the passphrase to fill the passphrase buffer space, if necessary,
- * concatenation as many duplicates as possible of P to itself. If P is
- * larger than the buffer space, truncate it to fit.
- *
- * Then hash the result with the given hashtype transform. Return
- * the result as Ku.
- *
- * If successful, kulen contains the size of the hash written to Ku.
- *
- * NOTE Passphrases less than USM_LENGTH_P_MIN characters in length
- * cause an error to be returned.
- * (Punt this check to the cmdline apps? XXX)
- */
- int
- generate_Ku( oid *hashtype, u_int hashtype_len,
- u_char *P, size_t pplen,
- u_char *Ku, size_t *kulen)
- #ifdef INCLUDE_SNMPV3
- {
- int rval = SNMPERR_SUCCESS,
- nbytes = USM_LENGTH_EXPANDED_PASSPHRASE;
- u_int i, pindex = 0;
- u_char buf[USM_LENGTH_KU_HASHBLOCK],
- *bufp;
- HASH_INIT_FUNC hash_init_func;
- HASH_UPDATE_FUNC hash_update_func;
- HASH_FINAL_FUNC hash_final_func;
- #ifdef USE_OPENSSL
- EVP_MD_CTX *ctx = malloc(sizeof(EVP_MD_CTX));
- #else
- MD5_CTX MD;
- SHA_CTX SHA;
- void *ctx;
- #endif
- /*
- * Sanity check.
- */
- if ( !hashtype || !P || !Ku || !kulen
- || (*kulen<=0)
- || (hashtype_len != USM_LENGTH_OID_TRANSFORM) )
- {
- QUITFUN(SNMPERR_GENERR, generate_Ku_quit);
- }
- if (pplen < USM_LENGTH_P_MIN) {
- #ifdef SNMP_TESTING_CODE
- snmp_log(LOG_WARNING, "Warning: passphrase chosen is below the length requiremnts of the USM.n");
- #else
- snmp_set_detail("Password length too short.");
- QUITFUN(SNMPERR_GENERR, generate_Ku_quit);
- #endif
- }
- /*
- * Setup for the transform type.
- */
- if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
- hash_init_func = (HASH_INIT_FUNC)MD5Init;
- hash_update_func = (HASH_UPDATE_FUNC)MD5Update;
- hash_final_func = (HASH_FINAL_FUNC)MD5Final;
- ctx = (void*)&MD;
- }
- else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
- hash_init_func = (HASH_INIT_FUNC)SHAInit;
- hash_update_func = (HASH_UPDATE_FUNC)SHAUpdate;
- hash_final_func = (HASH_FINAL_FUNC)SHAFinal;
- ctx = (void*)&SHA;
- }
- else {
- return (SNMPERR_GENERR);
- }
- #ifdef USE_OPENSSL
- if (ISTRANSFORM(hashtype, HMACMD5Auth))
- EVP_DigestInit(ctx, EVP_md5());
- else if (ISTRANSFORM(hashtype, HMACSHA1Auth))
- EVP_DigestInit(ctx, EVP_sha1());
- else {
- free(ctx);
- return (SNMPERR_GENERR);
- }
- #else
- hash_init_func(ctx);
- #endif /* USE_OPENSSL */
- while (nbytes > 0) {
- bufp = buf;
- for (i = 0; i < USM_LENGTH_KU_HASHBLOCK; i++) {
- *bufp++ = P[pindex++ % pplen];
- }
- #ifdef USE_OPENSSL
- EVP_DigestUpdate(ctx, buf, USM_LENGTH_KU_HASHBLOCK);
- #else
- /* MD5Update(&MD, buf, USM_LENGTH_KU_HASHBLOCK);*/
- hash_update_func(ctx, buf, USM_LENGTH_KU_HASHBLOCK);
- #endif /* USE_OPENSSL */
- nbytes -= USM_LENGTH_KU_HASHBLOCK;
- }
- #ifdef USE_OPENSSL
- EVP_DigestFinal(ctx, (unsigned char *) Ku, (unsigned int *) kulen);
- /* what about free() */
- #else
- /* MD5Final(Ku, &MD);*/
- hash_final_func(Ku, ctx);
- *kulen = sc_get_properlength(hashtype, hashtype_len);
- /* md5_fin:
- memset(&MD, 0, sizeof(MD)); */
- #endif /* USE_OPENSSL */
- #ifdef SNMP_TESTING_CODE
- DEBUGMSGTL(("generate_Ku", "generating Ku (from %s): ", P));
- for(i=0; i < *kulen; i++)
- DEBUGMSG(("generate_Ku", "%02x",Ku[i]));
- DEBUGMSG(("generate_Ku","n"));
- #endif /* SNMP_TESTING_CODE */
- generate_Ku_quit:
- memset(buf, 0, sizeof(buf));
- #ifdef USE_OPENSSL
- free(ctx);
- #endif
- return rval;
- } /* end generate_Ku() */
- #else
- {
- return -1;
- }
- #endif /* internal or openssl */
- /*******************************************************************-o-******
- * generate_kul
- *
- * Parameters:
- * *hashtype
- * hashtype_len
- * *engineID
- * engineID_len
- * *Ku Master key for a given user.
- * ku_len Length of Ku in bytes.
- * *Kul Localized key for a given user at engineID.
- * *kul_len Length of Kul buffer (IN); Length of Kul key (OUT).
- *
- * Returns:
- * SNMPERR_SUCCESS Success.
- * SNMPERR_GENERR All errors.
- *
- *
- * Ku MUST be the proper length (currently fixed) for the given hashtype.
- *
- * Upon successful return, Kul contains the localized form of Ku at
- * engineID, and the length of the key is stored in kul_len.
- *
- * The localized key method is defined in RFC2274, Sections 2.6 and A.2, and
- * originally documented in:
- * U. Blumenthal, N. C. Hien, B. Wijnen,
- * "Key Derivation for Network Management Applications",
- * IEEE Network Magazine, April/May issue, 1997.
- *
- *
- * ASSUMES SNMP_MAXBUF >= sizeof(Ku + engineID + Ku).
- *
- * NOTE Localized keys for privacy transforms are generated via
- * the authentication transform held by the same usmUser.
- *
- * XXX An engineID of any length is accepted, even if larger than
- * what is spec'ed for the textual convention.
- */
- int
- generate_kul( oid *hashtype, u_int hashtype_len,
- u_char *engineID, size_t engineID_len,
- u_char *Ku, size_t ku_len,
- u_char *Kul, size_t *kul_len)
- #ifdef INCLUDE_SNMPV3
- {
- int rval = SNMPERR_SUCCESS;
- u_int nbytes = 0;
- size_t properlength;
- u_char buf[SNMP_MAXBUF];
- void *context = NULL;
- #ifdef SNMP_TESTING_CODE
- int i;
- #endif
- MD5_CTX MD;
- SHA_CTX SHA;
- /*
- * Sanity check.
- */
- if ( !hashtype || !engineID || !Ku || !Kul || !kul_len
- || (engineID_len<=0) || (ku_len<=0) || (*kul_len<=0)
- || (hashtype_len != USM_LENGTH_OID_TRANSFORM) )
- {
- QUITFUN(SNMPERR_GENERR, generate_kul_quit);
- }
- properlength = sc_get_properlength(hashtype, hashtype_len);
- if (properlength == (size_t)SNMPERR_GENERR)
- QUITFUN(SNMPERR_GENERR, generate_kul_quit);
- if (((int)*kul_len < properlength) || ((int)ku_len < properlength) ) {
- QUITFUN(SNMPERR_GENERR, generate_kul_quit);
- }
- /*
- * Concatenate Ku and engineID properly, then hash the result.
- * Store it in Kul.
- */
- nbytes = 0;
- memcpy(buf, Ku, properlength); nbytes += properlength;
- memcpy(buf+nbytes, engineID, engineID_len); nbytes += engineID_len;
- memcpy(buf+nbytes, Ku, properlength); nbytes += properlength;
- if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
- MD5Init(&MD);
- MD5Update(&MD, buf, 32+engineID_len);
- MD5Final(Kul, &MD);
- *kul_len = properlength;
- }
- else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
- SHAInit(&SHA);
- SHAUpdate(&SHA, buf, 40+engineID_len);
- SHAFinal(Kul, &SHA);
- *kul_len = properlength;
- }
- else {
- return (SNMPERR_GENERR);
- }
- #ifdef SNMP_TESTING_CODE
- DEBUGMSGTL(("generate_kul", "generating Kul (from Ku): "));
- for(i=0; i < *kul_len; i++)
- DEBUGMSG(("generate_kul", "%02x",Kul[i]));
- DEBUGMSG(("generate_kul", "keytoolsn"));
- #endif /* SNMP_TESTING_CODE */
- QUITFUN(rval, generate_kul_quit);
- generate_kul_quit:
- SNMP_FREE(context);
- return rval;
- } /* end generate_kul() */
- #else
- {
- return -1;
- }
- #endif /* internal or openssl */
- /*******************************************************************-o-******
- * encode_keychange
- *
- * Parameters:
- * *hashtype MIB OID for the hash transform type.
- * hashtype_len Length of the MIB OID hash transform type.
- * *oldkey Old key that is used to encodes the new key.
- * oldkey_len Length of oldkey in bytes.
- * *newkey New key that is encoded using the old key.
- * newkey_len Length of new key in bytes.
- * *kcstring Buffer to contain the KeyChange TC string.
- * *kcstring_len Length of kcstring buffer.
- *
- * Returns:
- * SNMPERR_SUCCESS Success.
- * SNMPERR_GENERR All errors.
- *
- *
- * Uses oldkey and acquired random bytes to encode newkey into kcstring
- * according to the rules of the KeyChange TC described in RFC 2274, Section 5.
- *
- * Upon successful return, *kcstring_len contains the length of the
- * encoded string.
- *
- * ASSUMES Old and new key are always equal to each other, although
- * this may be less than the transform type hash output
- * output length (eg, using KeyChange for a DESPriv key when
- * the user also uses SHA1Auth). This also implies that the
- * hash placed in the second 1/2 of the key change string
- * will be truncated before the XOR'ing when the hash output is
- * larger than that 1/2 of the key change string.
- *
- * *kcstring_len will be returned as exactly twice that same
- * length though the input buffer may be larger.
- *
- * XXX FIX: Does not handle varibable length keys.
- * XXX FIX: Does not handle keys larger than the hash algorithm used.
- */
- int
- encode_keychange( oid *hashtype, u_int hashtype_len,
- u_char *oldkey, size_t oldkey_len,
- u_char *newkey, size_t newkey_len,
- u_char *kcstring, size_t *kcstring_len)
- #ifdef INCLUDE_SNMPV3
- {
- int rval = SNMPERR_SUCCESS;
- size_t properlength;
- size_t nbytes = 0;
- u_char *tmpbuf = NULL;
- void *context = NULL;
- /*
- * Sanity check.
- */
- if ( !hashtype || !oldkey || !newkey || !kcstring || !kcstring_len
- || (oldkey_len<=0) || (newkey_len<=0) || (*kcstring_len<=0)
- || (hashtype_len != USM_LENGTH_OID_TRANSFORM) )
- {
- QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
- }
- /*
- * Setup for the transform type.
- */
- properlength = sc_get_properlength(hashtype, hashtype_len);
- if (properlength == (size_t)SNMPERR_GENERR)
- QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
- if ( (oldkey_len != newkey_len) || (*kcstring_len < (2*oldkey_len)) )
- {
- QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
- }
- properlength = SNMP_MIN((int)oldkey_len, properlength);
- /*
- * Use the old key and some random bytes to encode the new key
- * in the KeyChange TC format:
- * . Get random bytes (store in first half of kcstring),
- * . Hash (oldkey | random_bytes) (into second half of kcstring),
- * . XOR hash and newkey (into second half of kcstring).
- *
- * Getting the wrong number of random bytes is considered an error.
- */
- nbytes = properlength;
- #if defined(SNMP_TESTING_CODE) && defined(RANDOMZEROS)
- memset(kcstring, 0, nbytes);
- DEBUGMSG(("encode_keychange",
- "** Using all zero bits for "random" delta of )"
- "the keychange string! **n"));
- #else /* !SNMP_TESTING_CODE */
- rval = sc_random(kcstring, &nbytes);
- QUITFUN(rval, encode_keychange_quit);
- if ((int)nbytes != properlength) {
- QUITFUN(SNMPERR_GENERR, encode_keychange_quit);
- }
- #endif /* !SNMP_TESTING_CODE */
- tmpbuf = (u_char *)malloc(properlength*2);
- if (tmpbuf) {
- memcpy(tmpbuf, oldkey, properlength);
- memcpy(tmpbuf+properlength, kcstring, properlength);
- *kcstring_len -= properlength;
- rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2,
- kcstring+properlength, kcstring_len);
- QUITFUN(rval, encode_keychange_quit);
- *kcstring_len = (properlength*2);
- kcstring += properlength;
- nbytes = 0;
- while ((int)(nbytes++) < properlength) {
- *kcstring++ = *kcstring ^ *newkey++;
- }
- }
- encode_keychange_quit:
- if (rval != SNMPERR_SUCCESS) memset(kcstring, 0, *kcstring_len);
- SNMP_FREE(tmpbuf);
- SNMP_FREE(context);
- return rval;
- } /* end encode_keychange() */
- #else
- {
- return -1;
- }
- #endif /* internal or openssl */
- /*******************************************************************-o-******
- * decode_keychange
- *
- * Parameters:
- * *hashtype MIB OID of the hash transform to use.
- * hashtype_len Length of the hash transform MIB OID.
- * *oldkey Old key that is used to encode the new key.
- * oldkey_len Length of oldkey in bytes.
- * *kcstring Encoded KeyString buffer containing the new key.
- * kcstring_len Length of kcstring in bytes.
- * *newkey Buffer to hold the extracted new key.
- * *newkey_len Length of newkey in bytes.
- *
- * Returns:
- * SNMPERR_SUCCESS Success.
- * SNMPERR_GENERR All errors.
- *
- *
- * Decodes a string of bits encoded according to the KeyChange TC described
- * in RFC 2274, Section 5. The new key is extracted from *kcstring with
- * the aid of the old key.
- *
- * Upon successful return, *newkey_len contains the length of the new key.
- *
- *
- * ASSUMES Old key is exactly 1/2 the length of the KeyChange buffer,
- * although this length may be less than the hash transform
- * output. Thus the new key length will be equal to the old
- * key length.
- */
- /* XXX: if the newkey is not long enough, it should be freed and remalloced */
- int
- decode_keychange( oid *hashtype, u_int hashtype_len,
- u_char *oldkey, size_t oldkey_len,
- u_char *kcstring, size_t kcstring_len,
- u_char *newkey, size_t *newkey_len)
- #ifdef INCLUDEV3
- {
- int rval = SNMPERR_SUCCESS;
- size_t properlength = 0;
- u_int nbytes = 0;
- u_char *bufp,
- tmp_buf[SNMP_MAXBUF];
- size_t tmp_buf_len = SNMP_MAXBUF;
- void *context = NULL;
- u_char *tmpbuf = NULL;
- /*
- * Sanity check.
- */
- if ( !hashtype || !oldkey || !kcstring || !newkey || !newkey_len
- || (oldkey_len<=0) || (kcstring_len<=0) || (*newkey_len<=0)
- || (hashtype_len != USM_LENGTH_OID_TRANSFORM) )
- {
- QUITFUN(SNMPERR_GENERR, decode_keychange_quit);
- }
- /*
- * Setup for the transform type.
- */
- properlength = sc_get_properlength(hashtype, hashtype_len);
- if (properlength == (size_t)SNMPERR_GENERR)
- QUITFUN(SNMPERR_GENERR, decode_keychange_quit);
- if ( ((oldkey_len*2) != kcstring_len) || (*newkey_len < oldkey_len) )
- {
- QUITFUN(SNMPERR_GENERR, decode_keychange_quit);
- }
- properlength = oldkey_len;
- *newkey_len = properlength;
- /*
- * Use the old key and the given KeyChange TC string to recover
- * the new key:
- * . Hash (oldkey | random_bytes) (into newkey),
- * . XOR hash and encoded (second) half of kcstring (into newkey).
- */
- tmpbuf = (u_char *)malloc(properlength*2);
- if (tmpbuf) {
- memcpy(tmpbuf, oldkey, properlength);
- memcpy(tmpbuf+properlength, kcstring, properlength);
- rval = sc_hash(hashtype, hashtype_len, tmpbuf, properlength*2,
- tmp_buf, &tmp_buf_len);
- QUITFUN(rval, decode_keychange_quit);
- memcpy(newkey, tmp_buf, properlength);
- bufp = kcstring+properlength;
- nbytes = 0;
- while ((int)(nbytes++) < properlength) {
- *newkey++ = *newkey ^ *bufp++;
- }
- }
- decode_keychange_quit:
- if (rval != SNMPERR_SUCCESS) {
- memset(newkey, 0, properlength);
- }
- memset(tmp_buf, 0, SNMP_MAXBUF);
- SNMP_FREE(context);
- if (tmpbuf != NULL) SNMP_FREE(tmpbuf);
- return rval;
- } /* end decode_keychange() */
- #else
- {
- return -1;
- }
- #endif /* internal or openssl */