Blame snmplib/scapi.c

Packit fcad23
/* Portions of this file are subject to the following copyright(s).  See
Packit fcad23
 * the Net-SNMP's COPYING file for more details and other copyrights
Packit fcad23
 * that may apply:
Packit fcad23
 */
Packit fcad23
/*
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 *
Packit fcad23
 * Portions of this file are copyrighted by:
Packit fcad23
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
Packit fcad23
 * Use is subject to license terms specified in the COPYING file
Packit fcad23
 * distributed with the Net-SNMP package.
Packit fcad23
 */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * scapi.c
Packit fcad23
 *
Packit fcad23
 */
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-features.h>
Packit fcad23
Packit fcad23
#include <sys/types.h>
Packit fcad23
#ifdef HAVE_STDLIB_H
Packit fcad23
#include <stdlib.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_STRING_H
Packit fcad23
#include <string.h>
Packit fcad23
#else
Packit fcad23
#include <strings.h>
Packit fcad23
#endif
Packit fcad23
#if TIME_WITH_SYS_TIME
Packit fcad23
# include <sys/time.h>
Packit fcad23
# include <time.h>
Packit fcad23
#else
Packit fcad23
# if HAVE_SYS_TIME_H
Packit fcad23
#  include <sys/time.h>
Packit fcad23
# else
Packit fcad23
#  include <time.h>
Packit fcad23
# endif
Packit fcad23
#endif
Packit fcad23
#ifdef HAVE_NETINET_IN_H
Packit fcad23
#include <netinet/in.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#if HAVE_UNISTD_H
Packit fcad23
#include <unistd.h>
Packit fcad23
#endif
Packit fcad23
#if HAVE_DMALLOC_H
Packit fcad23
#include <dmalloc.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#include <net-snmp/types.h>
Packit fcad23
#include <net-snmp/output_api.h>
Packit fcad23
#include <net-snmp/utilities.h>
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(usm_support, libnetsnmp)
Packit fcad23
netsnmp_feature_child_of(usm_scapi, usm_support)
Packit fcad23
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_USM_SCAPI
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_INTERNAL_MD5
Packit fcad23
#include <net-snmp/library/md5.h>
Packit fcad23
#endif
Packit fcad23
#include <net-snmp/library/snmp_api.h>
Packit fcad23
#include <net-snmp/library/callback.h>
Packit fcad23
#include <net-snmp/library/snmp_secmod.h>
Packit fcad23
#include <net-snmp/library/snmpusm.h>
Packit fcad23
#include <net-snmp/library/keytools.h>
Packit fcad23
#include <net-snmp/library/scapi.h>
Packit fcad23
#include <net-snmp/library/mib.h>
Packit fcad23
#include <net-snmp/library/transform_oids.h>
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
#include <net-snmp/library/openssl_md5.h>
Packit fcad23
#include <net-snmp/library/openssl_sha.h>
Packit fcad23
#include <net-snmp/library/openssl_des.h>
Packit fcad23
#include <net-snmp/library/openssl_aes.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
#include <openssl/hmac.h>
Packit fcad23
#include <openssl/evp.h>
Packit fcad23
#include <openssl/rand.h>
Packit fcad23
#include <openssl/des.h>
Packit fcad23
#ifdef HAVE_AES
Packit fcad23
#include <openssl/aes.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
#ifdef HAVE_STRUCT_DES_KS_STRUCT_WEAK_KEY
Packit fcad23
/* these are older names for newer structures that exist in openssl .9.7 */
Packit fcad23
#define DES_key_schedule    des_key_schedule 
Packit fcad23
#define DES_cblock          des_cblock 
Packit fcad23
#define DES_key_sched       des_key_sched 
Packit fcad23
#define DES_ncbc_encrypt    des_ncbc_encrypt
Packit fcad23
#define DES_cbc_encrypt    des_cbc_encrypt
Packit fcad23
#define OLD_DES
Packit fcad23
#endif
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#endif /* HAVE_OPENSSL */
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_PKCS11
Packit fcad23
#include <security/cryptoki.h>
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef QUITFUN
Packit fcad23
#undef QUITFUN
Packit fcad23
#define QUITFUN(e, l)					\
Packit fcad23
	if (e != SNMPERR_SUCCESS) {			\
Packit fcad23
		rval = SNMPERR_SC_GENERAL_FAILURE;	\
Packit fcad23
		goto l ;				\
Packit fcad23
	}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
static
Packit fcad23
int SHA1_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
Packit fcad23
              const u_char * secret, size_t secretlen);
Packit fcad23
Packit fcad23
static
Packit fcad23
int MD5_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
Packit fcad23
             const u_char * secret, size_t secretlen);
Packit fcad23
#endif
Packit fcad23
Packit fcad23
static netsnmp_auth_alg_info _auth_alg_info[] = {
Packit fcad23
    { NETSNMP_USMAUTH_NOAUTH, "usmNoAuthProtocol", usmNoAuthProtocol,
Packit fcad23
      OID_LENGTH(usmNoAuthProtocol), 0, 0 },
Packit fcad23
    { NETSNMP_USMAUTH_HMACSHA1, "usmHMACSHA1AuthProtocol",
Packit fcad23
      usmHMACSHA1AuthProtocol, OID_LENGTH(usmHMACSHA1AuthProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_AUTHLEN_HMACSHA1), USM_MD5_AND_SHA_AUTH_LEN },
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
    { NETSNMP_USMAUTH_HMACMD5, "usmHMACMD5AuthProtocol",
Packit fcad23
      usmHMACMD5AuthProtocol, OID_LENGTH(usmHMACMD5AuthProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_AUTHLEN_HMACMD5), USM_MD5_AND_SHA_AUTH_LEN },
Packit fcad23
#endif
Packit fcad23
#ifdef HAVE_EVP_SHA224
Packit fcad23
    { NETSNMP_USMAUTH_HMAC128SHA224, "usmHMAC128SHA224AuthProtocol",
Packit fcad23
      usmHMAC128SHA224AuthProtocol, OID_LENGTH(usmHMAC128SHA224AuthProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC128SHA224), USM_HMAC128SHA224_AUTH_LEN },
Packit fcad23
    { NETSNMP_USMAUTH_HMAC192SHA256, "usmHMAC192SHA256AuthProtocol",
Packit fcad23
      usmHMAC192SHA256AuthProtocol, OID_LENGTH(usmHMAC192SHA256AuthProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC192SHA256), USM_HMAC192SHA256_AUTH_LEN },
Packit fcad23
#endif
Packit fcad23
#ifdef HAVE_EVP_SHA384
Packit fcad23
    { NETSNMP_USMAUTH_HMAC256SHA384, "usmHMAC256SHA384AuthProtocol",
Packit fcad23
      usmHMAC256SHA384AuthProtocol, OID_LENGTH(usmHMAC256SHA384AuthProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC256SHA384), USM_HMAC256SHA384_AUTH_LEN },
Packit fcad23
    { NETSNMP_USMAUTH_HMAC384SHA512, "usmHMAC384SHA512AuthProtocol",
Packit fcad23
      usmHMAC384SHA512AuthProtocol, OID_LENGTH(usmHMAC384SHA512AuthProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_AUTHLEN_HMAC384SHA512), USM_HMAC384SHA512_AUTH_LEN },
Packit fcad23
#endif
Packit fcad23
    { -1, "unknown", NULL, 0, 0, 0 }
Packit fcad23
};
Packit fcad23
Packit fcad23
static netsnmp_priv_alg_info _priv_alg_info[] = {
Packit fcad23
    { USM_CREATE_USER_PRIV_NONE, "usmNoPrivProtocol",
Packit fcad23
      usmNoPrivProtocol, OID_LENGTH(usmNoPrivProtocol), 0, 0, 0 },
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
    { USM_CREATE_USER_PRIV_DES, "usmDESPrivProtocol",
Packit fcad23
      usmDESPrivProtocol, OID_LENGTH(usmDESPrivProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_1DES),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_1DES) },
Packit fcad23
#endif
Packit fcad23
#ifdef HAVE_AES
Packit fcad23
    { USM_CREATE_USER_PRIV_AES, "usmAESPrivProtocol",
Packit fcad23
      usmAESPrivProtocol, OID_LENGTH(usmAESPrivProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES_IV),
Packit fcad23
      0 },
Packit fcad23
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
Packit fcad23
    { USM_CREATE_USER_PRIV_AES192, "usmAES192PrivProtocol",
Packit fcad23
      usmAES192PrivProtocol, OID_LENGTH(usmAES192PrivProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES192),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV),
Packit fcad23
      0 },
Packit fcad23
    { USM_CREATE_USER_PRIV_AES192_CISCO, "usmAES192CiscoPrivProtocol",
Packit fcad23
      usmAES192CiscoPrivProtocol, OID_LENGTH(usmAES192CiscoPrivProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES192),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES192_IV),
Packit fcad23
      0 },
Packit fcad23
    { USM_CREATE_USER_PRIV_AES256, "usmAES256PrivProtocol",
Packit fcad23
      usmAES256PrivProtocol, OID_LENGTH(usmAES256PrivProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES256),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV),
Packit fcad23
      0 },
Packit fcad23
    { USM_CREATE_USER_PRIV_AES256_CISCO, "usmAES256CiscoPrivProtocol",
Packit fcad23
      usmAES256CiscoPrivProtocol, OID_LENGTH(usmAES256CiscoPrivProtocol),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES256),
Packit fcad23
      BYTESIZE(SNMP_TRANS_PRIVLEN_AES256_IV),
Packit fcad23
      0 },
Packit fcad23
#endif
Packit fcad23
#endif
Packit fcad23
    { -1, NULL, NULL, 0 , 0, 0, 0 },
Packit fcad23
};
Packit fcad23
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_priv_alg(oid *privoid, u_int len)
Packit fcad23
 *
Packit fcad23
 * returns a pointer to a netsnmp_priv_alg_info struct
Packit fcad23
 */
Packit fcad23
netsnmp_priv_alg_info *
Packit fcad23
sc_get_priv_alg_byoid(const oid *privoid, u_int len)
Packit fcad23
{
Packit fcad23
    int i = 0;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if ((NULL == privoid) || (0 == len))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    for( ; _priv_alg_info[i].type != -1; ++i) {
Packit fcad23
        if (len != _priv_alg_info[i].oid_len)
Packit fcad23
            continue;
Packit fcad23
        if (snmp_oid_compare(_priv_alg_info[i].alg_oid,
Packit fcad23
                             _priv_alg_info[i].oid_len,
Packit fcad23
                             privoid, len) == 0 )
Packit fcad23
            return(&_priv_alg_info[i]);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    DEBUGMSGTL(("scapi", "no match for OID "));
Packit fcad23
    DEBUGMSGOID(("scapi", privoid, len));
Packit fcad23
    DEBUGMSG(("scapi", "\n"));
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_priv_alg_bytype(u_int type)
Packit fcad23
 *
Packit fcad23
 * returns a pointer to a netsnmp_priv_alg_info struct
Packit fcad23
 */
Packit fcad23
netsnmp_priv_alg_info *
Packit fcad23
sc_get_priv_alg_bytype(u_int type)
Packit fcad23
{
Packit fcad23
    int i = 0;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    for( ; _priv_alg_info[i].type != -1; ++i) {
Packit fcad23
        if (type != _priv_alg_info[i].type)
Packit fcad23
            continue;
Packit fcad23
        return(&_priv_alg_info[i]);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_find_auth_alg(oid *authoid, u_int len)
Packit fcad23
 *
Packit fcad23
 * returns a pointer to a netsnmp_auth_alg_info struct
Packit fcad23
 */
Packit fcad23
netsnmp_auth_alg_info *
Packit fcad23
sc_find_auth_alg_byoid(const oid *authoid, u_int len)
Packit fcad23
{
Packit fcad23
    int i = 0;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if ((NULL == authoid) || (0 == len))
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    for( ; _auth_alg_info[i].type != -1; ++i) {
Packit fcad23
        if (len != _auth_alg_info[i].oid_len)
Packit fcad23
            continue;
Packit fcad23
        if (snmp_oid_compare(_auth_alg_info[i].alg_oid,
Packit fcad23
                             _auth_alg_info[i].oid_len,
Packit fcad23
                             authoid, len) == 0 )
Packit fcad23
            return(&_auth_alg_info[i]);
Packit fcad23
    }
Packit fcad23
Packit fcad23
/*    DEBUGMSGTL(("scapi", "No auth alg found for"));
Packit fcad23
      DEBUGMSGOID(("scapi", authoid, len ));*/
Packit fcad23
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_auth_alg_byindex(u_int index)
Packit fcad23
 *
Packit fcad23
 * returns a pointer to a netsnmp_auth_alg_info struct
Packit fcad23
 */
Packit fcad23
netsnmp_auth_alg_info *
Packit fcad23
sc_get_auth_alg_byindex(u_int index)
Packit fcad23
{
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if (index >= (sizeof(_auth_alg_info)) / (sizeof(_auth_alg_info[0])) ||
Packit fcad23
        -1 == _auth_alg_info[index].type)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return(&_auth_alg_info[index]);
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_find_auth_alg_bytype(u_int type)
Packit fcad23
 *
Packit fcad23
 * returns a pointer to a netsnmp_auth_alg_info struct
Packit fcad23
 */
Packit fcad23
netsnmp_auth_alg_info *
Packit fcad23
sc_find_auth_alg_bytype(u_int type)
Packit fcad23
{
Packit fcad23
    int i = 0;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    for( ; _auth_alg_info[i].type != -1; ++i) {
Packit fcad23
        if (type != _auth_alg_info[i].type)
Packit fcad23
            continue;
Packit fcad23
        return(&_auth_alg_info[i]);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_authtype(oid *hashtype, u_int hashtype_len):
Packit fcad23
 * 
Packit fcad23
 * Given a hashing type ("hashtype" and its length hashtype_len), return
Packit fcad23
 * its type (the last suboid). NETSNMP_USMAUTH_* constants are defined in
Packit fcad23
 * transform_oids.h.
Packit fcad23
 * 
Packit fcad23
 * Returns SNMPERR_GENERR for an unknown hashing type.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_get_authtype(const oid * hashtype, u_int hashtype_len)
Packit fcad23
{
Packit fcad23
    netsnmp_auth_alg_info *aai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    aai = sc_find_auth_alg_byoid(hashtype, hashtype_len);
Packit fcad23
    if (NULL == aai)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
Packit fcad23
    return aai->type;
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
sc_get_privtype(const oid * privtype, u_int privtype_len)
Packit fcad23
{
Packit fcad23
    netsnmp_priv_alg_info *pai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    pai = sc_get_priv_alg_byoid(privtype, privtype_len);
Packit fcad23
    if (NULL == pai)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
Packit fcad23
    return pai->type;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_auth_maclen(int hashtype):
Packit fcad23
 *
Packit fcad23
 * Given a hash type, return its MAC length, which may be shorter than
Packit fcad23
 * the full hash length.
Packit fcad23
 *
Packit fcad23
 * Returns 0 for an unknown hash type.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_get_auth_maclen(int hashtype)
Packit fcad23
{
Packit fcad23
    netsnmp_auth_alg_info *aai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    aai = sc_find_auth_alg_bytype(hashtype);
Packit fcad23
    if (NULL == aai)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    return aai->mac_length;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_proper_auth_length_bytype(int hashtype):
Packit fcad23
 * 
Packit fcad23
 * Given a hashing type, return the length of the hash result.
Packit fcad23
 * 
Packit fcad23
 * Returns either the length or SNMPERR_GENERR for an unknown hashing type.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_get_proper_auth_length_bytype(int hashtype)
Packit fcad23
{
Packit fcad23
    netsnmp_auth_alg_info *aai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    aai = sc_find_auth_alg_bytype(hashtype);
Packit fcad23
    if (NULL == aai)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
Packit fcad23
    return aai->proper_length;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_auth_oid(int hashtype, int *oid_len):
Packit fcad23
 * 
Packit fcad23
 * Given a type, return the OID and optionally set OID length.
Packit fcad23
 */
Packit fcad23
oid *
Packit fcad23
sc_get_auth_oid(int type, size_t *oid_len)
Packit fcad23
{
Packit fcad23
    netsnmp_auth_alg_info *ai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    ai = sc_find_auth_alg_bytype(type);
Packit fcad23
    if (NULL == ai)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    if (NULL != oid_len)
Packit fcad23
        *oid_len = ai->oid_len;
Packit fcad23
Packit fcad23
    return ai->alg_oid;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_auth_name(int hashtype):
Packit fcad23
 * 
Packit fcad23
 * Given a type, return the name string
Packit fcad23
 */
Packit fcad23
const char*
Packit fcad23
sc_get_auth_name(int type)
Packit fcad23
{
Packit fcad23
    netsnmp_auth_alg_info *ai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    ai = sc_find_auth_alg_bytype(type);
Packit fcad23
    if (NULL == ai)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return ai->name;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_priv_oid(int type, int *oid_len):
Packit fcad23
 * 
Packit fcad23
 * Given a type, return the OID and optionally set OID length.
Packit fcad23
 */
Packit fcad23
oid *
Packit fcad23
sc_get_priv_oid(int type, size_t *oid_len)
Packit fcad23
{
Packit fcad23
    netsnmp_priv_alg_info *ai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    ai = sc_get_priv_alg_bytype(type);
Packit fcad23
    if (NULL == ai)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    if (NULL != oid_len)
Packit fcad23
        *oid_len = ai->oid_len;
Packit fcad23
Packit fcad23
    return ai->alg_oid;
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_properlength(oid *hashtype, u_int hashtype_len):
Packit fcad23
 * 
Packit fcad23
 * Given a hashing type ("hashtype" and its length hashtype_len), return
Packit fcad23
 * the length of the hash result.
Packit fcad23
 * 
Packit fcad23
 * Returns either the length or SNMPERR_GENERR for an unknown hashing type.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_get_properlength(const oid * hashtype, u_int hashtype_len)
Packit fcad23
{
Packit fcad23
    DEBUGTRACE;
Packit fcad23
    /*
Packit fcad23
     * Determine transform type hash length.
Packit fcad23
     */
Packit fcad23
    return sc_get_proper_auth_length_bytype(
Packit fcad23
        sc_get_authtype(hashtype, hashtype_len));
Packit fcad23
}
Packit fcad23
Packit fcad23
netsnmp_feature_child_of(scapi_get_proper_priv_length, netsnmp_unused)
Packit fcad23
#ifndef NETSNMP_FEATURE_REMOVE_SCAPI_GET_PROPER_PRIV_LENGTH
Packit fcad23
int
Packit fcad23
sc_get_proper_priv_length(const oid * privtype, u_int privtype_len)
Packit fcad23
{
Packit fcad23
    netsnmp_priv_alg_info *pai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    pai = sc_get_priv_alg_byoid(privtype, privtype_len);
Packit fcad23
    if (NULL == pai)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    return pai->proper_length;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_FEATURE_REMOVE_SCAPI_GET_PROPER_PRIV_LENGTH */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * sc_get_priv_alg_byindex(u_int index)
Packit fcad23
 *
Packit fcad23
 * returns a pointer to a netsnmp_priv_alg_info struct
Packit fcad23
 */
Packit fcad23
netsnmp_priv_alg_info *
Packit fcad23
sc_get_priv_alg_byindex(u_int index)
Packit fcad23
{
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if (index >= (sizeof(_priv_alg_info)) / (sizeof(_priv_alg_info[0])) ||
Packit fcad23
        -1 == _priv_alg_info[index].type)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    return(&_priv_alg_info[index]);
Packit fcad23
}
Packit fcad23
Packit fcad23
int
Packit fcad23
sc_get_proper_priv_length_bytype(int privtype)
Packit fcad23
{
Packit fcad23
    netsnmp_priv_alg_info *pai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    pai = sc_get_priv_alg_bytype(privtype);
Packit fcad23
    if (NULL == pai)
Packit fcad23
        return 0;
Packit fcad23
Packit fcad23
    return pai->proper_length;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_init
Packit fcad23
 *
Packit fcad23
 * Returns:
Packit fcad23
 *	SNMPERR_SUCCESS			Success.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_init(void)
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS;
Packit fcad23
Packit fcad23
#if !defined(NETSNMP_USE_OPENSSL)
Packit fcad23
#if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
    struct timeval  tv;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    gettimeofday(&tv, (struct timezone *) 0);
Packit fcad23
Packit fcad23
    netsnmp_srandom((unsigned)(tv.tv_sec ^ tv.tv_usec));
Packit fcad23
#elif NETSNMP_USE_PKCS11
Packit fcad23
    DEBUGTRACE;
Packit fcad23
    rval = pkcs_init();
Packit fcad23
#else
Packit fcad23
    rval = SNMPERR_SC_NOT_CONFIGURED;
Packit fcad23
#endif                           /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
    /*
Packit fcad23
     * XXX ogud: The only reason to do anything here with openssl is to 
Packit fcad23
     * * XXX ogud: seed random number generator 
Packit fcad23
     */
Packit fcad23
#endif                          /* ifndef NETSNMP_USE_OPENSSL */
Packit fcad23
Packit fcad23
    return rval;
Packit fcad23
}                               /* end sc_init() */
Packit fcad23
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_random
Packit fcad23
 *
Packit fcad23
 * Parameters:
Packit fcad23
 *	*buf		Pre-allocated buffer.
Packit fcad23
 *	*buflen 	Size of buffer.
Packit fcad23
 *      
Packit fcad23
 * Returns:
Packit fcad23
 *	SNMPERR_SUCCESS			Success.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_random(u_char * buf, size_t * buflen)
Packit fcad23
#if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS;
Packit fcad23
#if !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_PKCS11)
Packit fcad23
    int             i;
Packit fcad23
    int             rndval;
Packit fcad23
    u_char         *ucp = buf;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
    RAND_bytes(buf, *buflen);   /* will never fail */
Packit fcad23
#elif NETSNMP_USE_PKCS11			/* NETSNMP_USE_PKCS11 */
Packit fcad23
    pkcs_random(buf, *buflen);
Packit fcad23
#else                           /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
    /*
Packit fcad23
     * fill the buffer with random integers.  Note that random()
Packit fcad23
     * is defined in config.h and may not be truly the random()
Packit fcad23
     * system call if something better existed 
Packit fcad23
     */
Packit fcad23
    rval = *buflen - *buflen % sizeof(rndval);
Packit fcad23
    for (i = 0; i < rval; i += sizeof(rndval)) {
Packit fcad23
        rndval = netsnmp_random();
Packit fcad23
        memcpy(ucp, &rndval, sizeof(rndval));
Packit fcad23
        ucp += sizeof(rndval);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    rndval = netsnmp_random();
Packit fcad23
    memcpy(ucp, &rndval, *buflen % sizeof(rndval));
Packit fcad23
Packit fcad23
    rval = SNMPERR_SUCCESS;
Packit fcad23
#endif                          /* NETSNMP_USE_OPENSSL */
Packit fcad23
    return rval;
Packit fcad23
Packit fcad23
}                               /* end sc_random() */
Packit fcad23
Packit fcad23
#else
Packit fcad23
_SCAPI_NOT_CONFIGURED
Packit fcad23
#endif                          /*  */
Packit fcad23
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
const EVP_MD   *
Packit fcad23
sc_get_openssl_hashfn(int auth_type)
Packit fcad23
{
Packit fcad23
    const EVP_MD   *hashfn = NULL;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    switch (auth_type) {
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
        case NETSNMP_USMAUTH_HMACMD5:
Packit fcad23
            hashfn = (const EVP_MD *) EVP_md5();
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
        case NETSNMP_USMAUTH_HMACSHA1:
Packit fcad23
            hashfn = (const EVP_MD *) EVP_sha1();
Packit fcad23
            break;
Packit fcad23
Packit fcad23
#ifdef HAVE_EVP_SHA224
Packit fcad23
        case NETSNMP_USMAUTH_HMAC128SHA224:
Packit fcad23
            hashfn = (const EVP_MD *) EVP_sha224();
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case NETSNMP_USMAUTH_HMAC192SHA256:
Packit fcad23
            hashfn = (const EVP_MD *) EVP_sha256();
Packit fcad23
            break;
Packit fcad23
#endif /* HAVE_EVP_SHA224 */
Packit fcad23
Packit fcad23
#ifdef HAVE_EVP_SHA384
Packit fcad23
        case NETSNMP_USMAUTH_HMAC256SHA384:
Packit fcad23
            hashfn = (const EVP_MD *) EVP_sha384();
Packit fcad23
            break;
Packit fcad23
Packit fcad23
        case NETSNMP_USMAUTH_HMAC384SHA512:
Packit fcad23
            hashfn = (const EVP_MD *) EVP_sha512();
Packit fcad23
            break;
Packit fcad23
#endif /* HAVE_EVP_SHA384 */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return hashfn;
Packit fcad23
}
Packit fcad23
Packit fcad23
const EVP_CIPHER *
Packit fcad23
sc_get_openssl_privfn(int priv_type)
Packit fcad23
{
Packit fcad23
    const EVP_CIPHER *fn = NULL;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    switch(priv_type & (USM_PRIV_MASK_ALG | USM_PRIV_MASK_VARIANT)) {
Packit fcad23
#ifdef HAVE_AES
Packit fcad23
        case USM_CREATE_USER_PRIV_AES:
Packit fcad23
            fn = (const EVP_CIPHER *)EVP_aes_128_cfb();
Packit fcad23
            break;
Packit fcad23
#ifdef NETSNMP_DRAFT_BLUMENTHAL_AES_04
Packit fcad23
        case USM_CREATE_USER_PRIV_AES192:
Packit fcad23
            fn = (const void*)EVP_aes_192_cfb();
Packit fcad23
            break;
Packit fcad23
        case USM_CREATE_USER_PRIV_AES256:
Packit fcad23
            fn = (const void*)EVP_aes_256_cfb();
Packit fcad23
            break;
Packit fcad23
#endif
Packit fcad23
#endif /* HAVE_AES */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return fn;
Packit fcad23
}
Packit fcad23
#endif /* openssl */
Packit fcad23
Packit fcad23
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_generate_keyed_hash
Packit fcad23
 *
Packit fcad23
 * Parameters:
Packit fcad23
 *	 authtype	Type of authentication transform.
Packit fcad23
 *	 authtypelen
Packit fcad23
 *	*key		Pointer to key (Kul) to use in keyed hash.
Packit fcad23
 *	 keylen		Length of key in bytes.
Packit fcad23
 *	*message	Pointer to the message to hash.
Packit fcad23
 *	 msglen		Length of the message.
Packit fcad23
 *	*MAC		Will be returned with allocated bytes containg hash.
Packit fcad23
 *	*maclen		Length of the hash buffer in bytes; also indicates
Packit fcad23
 *				whether the MAC should be truncated.
Packit fcad23
 *      
Packit fcad23
 * Returns:
Packit fcad23
 *	SNMPERR_SUCCESS			Success.
Packit fcad23
 *	SNMPERR_GENERR			All errs
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * A hash of the first msglen bytes of message using a keyed hash defined
Packit fcad23
 * by authtype is created and stored in MAC.  MAC is ASSUMED to be a buffer
Packit fcad23
 * of at least maclen bytes.  If the length of the hash is greater than
Packit fcad23
 * maclen, it is truncated to fit the buffer.  If the length of the hash is
Packit fcad23
 * less than maclen, maclen set to the number of hash bytes generated.
Packit fcad23
 *
Packit fcad23
 * ASSUMED that the number of hash bits is a multiple of 8.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_generate_keyed_hash(const oid * authtypeOID, size_t authtypeOIDlen,
Packit fcad23
                       const u_char * key, u_int keylen,
Packit fcad23
                       const u_char * message, u_int msglen,
Packit fcad23
                       u_char * MAC, size_t * maclen)
Packit fcad23
#if  defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS, auth_type;
Packit fcad23
    int             iproperlength;
Packit fcad23
    size_t          properlength;
Packit fcad23
    u_char          buf[SNMP_MAXBUF_SMALL];
Packit fcad23
#if  defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11)
Packit fcad23
    unsigned int    buf_len = sizeof(buf);
Packit fcad23
#endif
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
    const EVP_MD   *hashfn;
Packit fcad23
#elif defined(NETSNMP_USE_PKCS11)
Packit fcad23
    u_long          ck_type;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    {
Packit fcad23
        int             i;
Packit fcad23
        DEBUGMSG(("sc_generate_keyed_hash",
Packit fcad23
                  "sc_generate_keyed_hash(): key=0x"));
Packit fcad23
        for (i = 0; i < keylen; i++)
Packit fcad23
            DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff));
Packit fcad23
        DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen));
Packit fcad23
    }
Packit fcad23
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Sanity check.
Packit fcad23
     */
Packit fcad23
    if (!authtypeOID || !key || !message || !MAC || !maclen
Packit fcad23
        || (keylen <= 0) || (msglen <= 0) || (*maclen <= 0)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    auth_type = sc_get_authtype(authtypeOID, authtypeOIDlen);
Packit fcad23
    iproperlength = sc_get_auth_maclen(auth_type);
Packit fcad23
    if (iproperlength == SNMPERR_GENERR)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    properlength = (size_t)iproperlength;
Packit fcad23
    if (keylen < properlength) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    DEBUGMSGTL(("scapi", "iproperlength: %d, maclen:%" NETSNMP_PRIz "d\n", iproperlength,
Packit fcad23
                *maclen));
Packit fcad23
#endif
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
    /** get hash function */
Packit fcad23
    hashfn = sc_get_openssl_hashfn(auth_type);
Packit fcad23
    if (NULL == hashfn) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    HMAC(hashfn, key, keylen, message, msglen, buf, &buf_len);
Packit fcad23
    if (buf_len != properlength) {
Packit fcad23
        QUITFUN(rval, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
    if (*maclen > buf_len)
Packit fcad23
        *maclen = buf_len;
Packit fcad23
    memcpy(MAC, buf, *maclen);
Packit fcad23
Packit fcad23
#elif NETSNMP_USE_PKCS11                    /* NETSNMP_USE_PKCS11 */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
    if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
Packit fcad23
	if (pkcs_sign(CKM_MD5_HMAC,key, keylen, message,
Packit fcad23
			msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
        }
Packit fcad23
    } else
Packit fcad23
#endif
Packit fcad23
        if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
Packit fcad23
	if (pkcs_sign(CKM_SHA_1_HMAC,key, keylen, message,
Packit fcad23
			msglen, buf, &buf_len) != SNMPERR_SUCCESS) {
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
        }
Packit fcad23
    } else {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    if (buf_len != properlength) {
Packit fcad23
        QUITFUN(rval, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
    if (*maclen > buf_len)
Packit fcad23
        *maclen = buf_len;
Packit fcad23
    memcpy(MAC, buf, *maclen);
Packit fcad23
Packit fcad23
#elif NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
    if (*maclen > properlength)
Packit fcad23
        *maclen = properlength;
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
    if (NETSNMP_USMAUTH_HMACMD5 == auth_type)
Packit fcad23
        rval = MD5_hmac(message, msglen, MAC, *maclen, key, keylen);
Packit fcad23
    else
Packit fcad23
#endif
Packit fcad23
         if (NETSNMP_USMAUTH_HMACSHA1 == auth_type)
Packit fcad23
        rval = SHA1_hmac(message, msglen, MAC, *maclen, key, keylen);
Packit fcad23
    else {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
    if (rval != 0) {
Packit fcad23
        rval = SNMPERR_GENERR;
Packit fcad23
        goto sc_generate_keyed_hash_quit;
Packit fcad23
    }    
Packit fcad23
#else                            /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
    if (*maclen > properlength)
Packit fcad23
        *maclen = properlength;
Packit fcad23
    if (MDsign(message, msglen, MAC, *maclen, key, keylen)) {
Packit fcad23
        rval = SNMPERR_GENERR;
Packit fcad23
        goto sc_generate_keyed_hash_quit;
Packit fcad23
    }
Packit fcad23
#endif                          /* NETSNMP_USE_OPENSSL */
Packit fcad23
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    {
Packit fcad23
        char           *s;
Packit fcad23
        int             len = binary_to_hex(MAC, *maclen, &s);
Packit fcad23
Packit fcad23
        DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s));
Packit fcad23
        SNMP_ZERO(s, len);
Packit fcad23
        SNMP_FREE(s);
Packit fcad23
    }
Packit fcad23
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
Packit fcad23
Packit fcad23
  sc_generate_keyed_hash_quit:
Packit fcad23
    memset(buf, 0, SNMP_MAXBUF_SMALL);
Packit fcad23
    return rval;
Packit fcad23
}                               /* end sc_generate_keyed_hash() */
Packit fcad23
Packit fcad23
#else
Packit fcad23
                _SCAPI_NOT_CONFIGURED
Packit fcad23
#endif                          /* */
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_hash(): a generic wrapper around whatever hashing package we are using.
Packit fcad23
 * 
Packit fcad23
 * IN:
Packit fcad23
 * hashtype    - oid pointer to a hash type
Packit fcad23
 * hashtypelen - length of oid pointer
Packit fcad23
 * buf         - u_char buffer to be hashed
Packit fcad23
 * buf_len     - integer length of buf data
Packit fcad23
 * MAC_len     - length of the passed MAC buffer size.
Packit fcad23
 * 
Packit fcad23
 * OUT:    
Packit fcad23
 * MAC         - pre-malloced space to store hash output.
Packit fcad23
 * MAC_len     - length of MAC output to the MAC buffer.
Packit fcad23
 * 
Packit fcad23
 * Returns:
Packit fcad23
 * SNMPERR_SUCCESS              Success.
Packit fcad23
 * SNMP_SC_GENERAL_FAILURE      Any error.
Packit fcad23
 * SNMPERR_SC_NOT_CONFIGURED    Hash type not supported.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_hash(const oid * hashtype, size_t hashtypelen, const u_char * buf,
Packit fcad23
        size_t buf_len, u_char * MAC, size_t * MAC_len)
Packit fcad23
{
Packit fcad23
    int auth_type;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if (hashtype == NULL)
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    auth_type = sc_get_authtype(hashtype, hashtypelen);
Packit fcad23
    if (auth_type < 0 )
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    return sc_hash_type(auth_type, buf, buf_len, MAC, MAC_len);
Packit fcad23
}
Packit fcad23
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_hash_type():
Packit fcad23
 *    a generic wrapper around whatever hashing package we are using.
Packit fcad23
 *
Packit fcad23
 * IN:
Packit fcad23
 * hashtype    - oid pointer to a hash type
Packit fcad23
 * hashtypelen - length of oid pointer
Packit fcad23
 * buf         - u_char buffer to be hashed
Packit fcad23
 * buf_len     - integer length of buf data
Packit fcad23
 * MAC_len     - length of the passed MAC buffer size.
Packit fcad23
 *
Packit fcad23
 * OUT:
Packit fcad23
 * MAC         - pre-malloced space to store hash output.
Packit fcad23
 * MAC_len     - length of MAC output to the MAC buffer.
Packit fcad23
 *
Packit fcad23
 * Returns:
Packit fcad23
 * SNMPERR_SUCCESS              Success.
Packit fcad23
 * SNMP_SC_GENERAL_FAILURE      Any error.
Packit fcad23
 * SNMPERR_SC_NOT_CONFIGURED    Hash type not supported.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_hash_type(int auth_type, const u_char * buf, size_t buf_len, u_char * MAC,
Packit fcad23
             size_t * MAC_len)
Packit fcad23
#if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
{
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
    int            rval = SNMPERR_SUCCESS;
Packit fcad23
#endif
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11)
Packit fcad23
    unsigned int   tmp_len;
Packit fcad23
#endif
Packit fcad23
    int            ret;
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
    const EVP_MD   *hashfn;
Packit fcad23
    EVP_MD_CTX     *cptr;
Packit fcad23
#endif
Packit fcad23
#ifdef NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
    MD5_CTX        cmd5;
Packit fcad23
    SHA_CTX        csha1;
Packit fcad23
#endif
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if (buf == NULL || buf_len <= 0 || MAC == NULL || MAC_len == NULL )
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    ret = sc_get_proper_auth_length_bytype(auth_type);
Packit fcad23
    if (( ret < 0 ) || (*MAC_len < (size_t)ret ))
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_OPENSSL
Packit fcad23
    /*
Packit fcad23
     * Determine transform type.
Packit fcad23
     */
Packit fcad23
    hashfn = sc_get_openssl_hashfn(auth_type);
Packit fcad23
    if (NULL == hashfn)
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
Packit fcad23
/** initialize the pointer */
Packit fcad23
#if defined(HAVE_EVP_MD_CTX_NEW)
Packit fcad23
    cptr = EVP_MD_CTX_new();
Packit fcad23
#elif defined(HAVE_EVP_MD_CTX_CREATE)
Packit fcad23
    cptr = EVP_MD_CTX_create();
Packit fcad23
#else
Packit fcad23
    cptr = malloc(sizeof(*cptr));
Packit fcad23
#if defined(OLD_DES)
Packit fcad23
    memset(cptr, 0, sizeof(*cptr));
Packit fcad23
#else
Packit fcad23
    EVP_MD_CTX_init(cptr);
Packit fcad23
#endif
Packit fcad23
#endif
Packit fcad23
    if (!EVP_DigestInit(cptr, hashfn)) {
Packit fcad23
        /* requested hash function is not available */
Packit fcad23
        return SNMPERR_SC_NOT_CONFIGURED;
Packit fcad23
    }
Packit fcad23
Packit fcad23
/** pass the data */
Packit fcad23
    EVP_DigestUpdate(cptr, buf, buf_len);
Packit fcad23
Packit fcad23
/** do the final pass */
Packit fcad23
    EVP_DigestFinal(cptr, MAC, &tmp_len);
Packit fcad23
    *MAC_len = tmp_len;
Packit fcad23
#if defined(HAVE_EVP_MD_CTX_FREE)
Packit fcad23
    EVP_MD_CTX_free(cptr);
Packit fcad23
#elif defined(HAVE_EVP_MD_CTX_DESTROY)
Packit fcad23
    EVP_MD_CTX_destroy(cptr);
Packit fcad23
#else
Packit fcad23
#if !defined(OLD_DES)
Packit fcad23
    EVP_MD_CTX_cleanup(cptr);
Packit fcad23
#endif
Packit fcad23
    free(cptr);
Packit fcad23
#endif
Packit fcad23
    return (rval);
Packit fcad23
Packit fcad23
#elif NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
    if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
Packit fcad23
        if (*MAC_len < MD5_DIGEST_LENGTH)
Packit fcad23
            return (SNMPERR_GENERR);      /* the buffer isn't big enough */
Packit fcad23
        MD5_Init(&cmd5);
Packit fcad23
        MD5_Update(&cmd5, buf, buf_len);
Packit fcad23
        MD5_Final(MAC, &cmd5);
Packit fcad23
        *MAC_len = MD5_DIGEST_LENGTH;
Packit fcad23
    } else 
Packit fcad23
#endif
Packit fcad23
    if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
Packit fcad23
        if (*MAC_len < SHA_DIGEST_LENGTH)
Packit fcad23
            return (SNMPERR_GENERR);      /* the buffer isn't big enough */
Packit fcad23
        SHA1_Init(&csha1);
Packit fcad23
        SHA1_Update(&csha1, buf, buf_len);
Packit fcad23
        SHA1_Final(MAC, &csha1);
Packit fcad23
        *MAC_len = SHA_DIGEST_LENGTH;
Packit fcad23
            
Packit fcad23
    } else {
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
    }
Packit fcad23
    return (rval);
Packit fcad23
#elif NETSNMP_USE_PKCS11                  /* NETSNMP_USE_PKCS11 */
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_MD5
Packit fcad23
    if (NETSNMP_USMAUTH_HMACMD5 == auth_type) {
Packit fcad23
        rval = pkcs_digest(CKM_MD5, buf, buf_len, MAC, &tmp_len);
Packit fcad23
        *MAC_len = tmp_len;
Packit fcad23
    } else
Packit fcad23
#endif
Packit fcad23
    if (NETSNMP_USMAUTH_HMACSHA1 == auth_type) {
Packit fcad23
       rval = pkcs_digest(CKM_SHA_1, buf, buf_len, MAC, &tmp_len);
Packit fcad23
        *MAC_len = tmp_len;
Packit fcad23
    } else {
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
    }
Packit fcad23
Packit fcad23
     return (rval);
Packit fcad23
Packit fcad23
#else                           /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
Packit fcad23
    if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
Packit fcad23
        return SNMPERR_GENERR;
Packit fcad23
    }
Packit fcad23
    if (*MAC_len > 16)
Packit fcad23
        *MAC_len = 16;
Packit fcad23
    return SNMPERR_SUCCESS;
Packit fcad23
Packit fcad23
#endif                          /* NETSNMP_USE_OPENSSL */
Packit fcad23
}
Packit fcad23
#else                           /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */
Packit fcad23
_SCAPI_NOT_CONFIGURED
Packit fcad23
#endif                          /* !defined(NETSNMP_USE_OPENSSL) && !defined(NETSNMP_USE_INTERNAL_MD5) */
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_check_keyed_hash
Packit fcad23
 *
Packit fcad23
 * Parameters:
Packit fcad23
 *	 authtype	Transform type of authentication hash.
Packit fcad23
 *	*key		Key bits in a string of bytes.
Packit fcad23
 *	 keylen		Length of key in bytes.
Packit fcad23
 *	*message	Message for which to check the hash.
Packit fcad23
 *	 msglen		Length of message.
Packit fcad23
 *	*MAC		Given hash.
Packit fcad23
 *	 maclen		Length of given hash; indicates truncation if it is
Packit fcad23
 *				shorter than the normal size of output for
Packit fcad23
 *				given hash transform.
Packit fcad23
 * Returns:
Packit fcad23
 *	SNMPERR_SUCCESS		Success.
Packit fcad23
 *	SNMP_SC_GENERAL_FAILURE	Any error
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * Check the hash given in MAC against the hash of message.  If the length
Packit fcad23
 * of MAC is less than the length of the transform hash output, only maclen
Packit fcad23
 * bytes are compared.  The length of MAC cannot be greater than the
Packit fcad23
 * length of the hash transform output.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_check_keyed_hash(const oid * authtypeOID, size_t authtypeOIDlen,
Packit fcad23
                    const u_char * key, u_int keylen,
Packit fcad23
                    const u_char * message, u_int msglen,
Packit fcad23
                    const u_char * MAC, u_int maclen)
Packit fcad23
#if defined(NETSNMP_USE_INTERNAL_MD5) || defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_PKCS11) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS, auth_type, auth_size;
Packit fcad23
    size_t          buf_len = SNMP_MAXBUF_SMALL;
Packit fcad23
Packit fcad23
    u_char          buf[SNMP_MAXBUF_SMALL];
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    {
Packit fcad23
        int             i;
Packit fcad23
        DEBUGMSG(("scapi", "sc_check_keyed_hash():    key=0x"));
Packit fcad23
        for (i = 0; i < keylen; i++)
Packit fcad23
            DEBUGMSG(("scapi", "%02x", key[i] & 0xff));
Packit fcad23
        DEBUGMSG(("scapi", " (%d)\n", keylen));
Packit fcad23
    }
Packit fcad23
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Sanity check.
Packit fcad23
     */
Packit fcad23
    if (!authtypeOID || !key || !message || !MAC
Packit fcad23
        || (keylen <= 0) || (msglen <= 0) || (maclen <= 0)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    auth_type = sc_get_authtype(authtypeOID, authtypeOIDlen);
Packit fcad23
    if (auth_type < 0 )
Packit fcad23
        return (SNMPERR_GENERR);
Packit fcad23
Packit fcad23
    auth_size = sc_get_auth_maclen(auth_type);
Packit fcad23
    if (0 == auth_size || maclen != auth_size) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Generate a full hash of the message, then compare
Packit fcad23
     * the result with the given MAC which may be shorter than
Packit fcad23
     * the full hash length.
Packit fcad23
     */
Packit fcad23
    rval = sc_generate_keyed_hash(authtypeOID, authtypeOIDlen, key, keylen,
Packit fcad23
                                  message, msglen, buf, &buf_len);
Packit fcad23
    QUITFUN(rval, sc_check_keyed_hash_quit);
Packit fcad23
Packit fcad23
    if (maclen > msglen) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
Packit fcad23
Packit fcad23
    } else if (memcmp(buf, MAC, maclen) != 0) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_check_keyed_hash_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
Packit fcad23
  sc_check_keyed_hash_quit:
Packit fcad23
    memset(buf, 0, SNMP_MAXBUF_SMALL);
Packit fcad23
Packit fcad23
    return rval;
Packit fcad23
Packit fcad23
}                               /* end sc_check_keyed_hash() */
Packit fcad23
Packit fcad23
#else
Packit fcad23
_SCAPI_NOT_CONFIGURED
Packit fcad23
#endif                          /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_encrypt
Packit fcad23
 *
Packit fcad23
 * Parameters:
Packit fcad23
 *	 privtype	Type of privacy cryptographic transform.
Packit fcad23
 *	*key		Key bits for crypting.
Packit fcad23
 *	 keylen		Length of key (buffer) in bytes.
Packit fcad23
 *	*iv		IV bits for crypting.
Packit fcad23
 *	 ivlen		Length of iv (buffer) in bytes.
Packit fcad23
 *	*plaintext	Plaintext to crypt.
Packit fcad23
 *	 ptlen		Length of plaintext.
Packit fcad23
 *	*ciphertext	Ciphertext to crypt.
Packit fcad23
 *	*ctlen		Length of ciphertext.
Packit fcad23
 *      
Packit fcad23
 * Returns:
Packit fcad23
 *	SNMPERR_SUCCESS			Success.
Packit fcad23
 *	SNMPERR_SC_NOT_CONFIGURED	Encryption is not supported.
Packit fcad23
 *	SNMPERR_SC_GENERAL_FAILURE	Any other error
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * Encrypt plaintext into ciphertext using key and iv.
Packit fcad23
 *
Packit fcad23
 * ctlen contains actual number of crypted bytes in ciphertext upon
Packit fcad23
 * successful return.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_encrypt(const oid * privtype, size_t privtypelen,
Packit fcad23
           u_char * key, u_int keylen,
Packit fcad23
           u_char * iv, u_int ivlen,
Packit fcad23
           const u_char * plaintext, u_int ptlen,
Packit fcad23
           u_char * ciphertext, size_t * ctlen)
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS;
Packit fcad23
    u_char          pad_block[128];      /* bigger than anything I need */
Packit fcad23
    u_char          my_iv[128];  /* ditto */
Packit fcad23
    netsnmp_priv_alg_info *pai = NULL;
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
    int             pad, plast, pad_size = 0;
Packit fcad23
#ifdef OLD_DES
Packit fcad23
    DES_key_schedule key_sch;
Packit fcad23
#else
Packit fcad23
    DES_key_schedule key_sched_store;
Packit fcad23
    DES_key_schedule *key_sch = &key_sched_store;
Packit fcad23
#endif /* OLD_DES */
Packit fcad23
    DES_cblock       key_struct;
Packit fcad23
#endif /* NETSNMP_DISABLE_DES */
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Sanity check.
Packit fcad23
     */
Packit fcad23
#if	!defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
Packit fcad23
    snmp_log(LOG_ERR, "Encryption support not enabled.(2)\n");
Packit fcad23
    return SNMPERR_SC_NOT_CONFIGURED;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
Packit fcad23
        || (keylen <= 0) || (ivlen <= 0) || (ivlen > sizeof(my_iv))
Packit fcad23
        || (ptlen <= 0) || (*ctlen <= 0)) {
Packit fcad23
        DEBUGMSGTL(("scapi:encrypt", "bad arguments 1\n"));
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
    } else if (ptlen > *ctlen) {
Packit fcad23
        DEBUGMSGTL(("scapi:encrypt", "bad arguments 2\n"));
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
    }
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    {
Packit fcad23
        size_t          buf_len = 128, out_len = 0;
Packit fcad23
        u_char         *buf = (u_char *) malloc(buf_len);
Packit fcad23
Packit fcad23
        if (buf != NULL) {
Packit fcad23
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         iv, ivlen)) {
Packit fcad23
                DEBUGMSGTL(("scapi", "encrypt: IV: %s\n", buf));
Packit fcad23
            } else {
Packit fcad23
                DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]\n", buf));
Packit fcad23
            }
Packit fcad23
            out_len = 0;
Packit fcad23
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         key, keylen)) {
Packit fcad23
                DEBUGMSG(("scapi", "key: %s\n", buf));
Packit fcad23
            } else {
Packit fcad23
                DEBUGMSG(("scapi", "key: %s [TRUNCATED]\n", buf));
Packit fcad23
            }
Packit fcad23
            out_len = 0;
Packit fcad23
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         plaintext, 16)) {
Packit fcad23
                DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf));
Packit fcad23
            } else {
Packit fcad23
                DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n",
Packit fcad23
                            buf));
Packit fcad23
            }
Packit fcad23
            free(buf);
Packit fcad23
        } else {
Packit fcad23
            DEBUGMSGTL(("scapi",
Packit fcad23
                        "encrypt: malloc fail for debug output\n"));
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
Packit fcad23
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Determine privacy transform.
Packit fcad23
     */
Packit fcad23
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
Packit fcad23
    if (NULL == pai ||
Packit fcad23
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
Packit fcad23
        DEBUGMSGTL(("scapi:encrypt",
Packit fcad23
                    "bad arguments 3 pai %p, keylen %d ivlen %d\n",
Packit fcad23
                    pai, keylen, ivlen));
Packit fcad23
        if (pai)
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", " pai: properlen %d, ivlen %d\n",
Packit fcad23
                        pai->proper_length, pai->iv_length));
Packit fcad23
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
    }
Packit fcad23
    pad_size = pai->pad_size;
Packit fcad23
Packit fcad23
    memset(my_iv, 0, sizeof(my_iv));
Packit fcad23
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
    if (USM_CREATE_USER_PRIV_DES == (pai->type & USM_PRIV_MASK_ALG)) {
Packit fcad23
Packit fcad23
        /*
Packit fcad23
         * now calculate the padding needed 
Packit fcad23
         */
Packit fcad23
        pad = pad_size - (ptlen % pad_size);
Packit fcad23
        plast = (int) ptlen - (pad_size - pad);
Packit fcad23
        if (pad == pad_size)
Packit fcad23
            pad = 0;
Packit fcad23
        if (ptlen + pad > *ctlen) {
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", "not enough space\n"));
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);    /* not enough space */
Packit fcad23
        }
Packit fcad23
        if (pad > 0) {              /* copy data into pad block if needed */
Packit fcad23
            memcpy(pad_block, plaintext + plast, pad_size - pad);
Packit fcad23
            memset(&pad_block[pad_size - pad], pad, pad);   /* filling in padblock */
Packit fcad23
        }
Packit fcad23
Packit fcad23
        memcpy(key_struct, key, sizeof(key_struct));
Packit fcad23
        (void) DES_key_sched(&key_struct, key_sch);
Packit fcad23
Packit fcad23
        memcpy(my_iv, iv, ivlen);
Packit fcad23
        /*
Packit fcad23
         * encrypt the data 
Packit fcad23
         */
Packit fcad23
        DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch,
Packit fcad23
                         (DES_cblock *) my_iv, DES_ENCRYPT);
Packit fcad23
        if (pad > 0) {
Packit fcad23
            /*
Packit fcad23
             * then encrypt the pad block 
Packit fcad23
             */
Packit fcad23
            DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size,
Packit fcad23
                             key_sch, (DES_cblock *) my_iv, DES_ENCRYPT);
Packit fcad23
            *ctlen = plast + pad_size;
Packit fcad23
        } else {
Packit fcad23
            *ctlen = plast;
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_AES)
Packit fcad23
    if (USM_CREATE_USER_PRIV_AES == (pai->type & USM_PRIV_MASK_ALG)) {
Packit fcad23
        EVP_CIPHER_CTX *ctx;
Packit fcad23
        const EVP_CIPHER *cipher;
Packit fcad23
        int len, rc, enclen;
Packit fcad23
Packit fcad23
        cipher = sc_get_openssl_privfn(pai->type);
Packit fcad23
        if (NULL == cipher) {
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", "cipher not found\n"));
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
        }
Packit fcad23
Packit fcad23
        memcpy(my_iv, iv, ivlen);
Packit fcad23
        /*
Packit fcad23
         * encrypt the data 
Packit fcad23
         */
Packit fcad23
        ctx = EVP_CIPHER_CTX_new();
Packit fcad23
        if (!ctx) {
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", "openssl error: ctx_new\n"));
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
        }
Packit fcad23
        rc = EVP_EncryptInit(ctx, cipher, key, my_iv);
Packit fcad23
        if (rc != 1) {
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", "openssl error: init\n"));
Packit fcad23
            EVP_CIPHER_CTX_free(ctx);
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
        }
Packit fcad23
        rc = EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, ptlen);
Packit fcad23
        if (rc != 1) {
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", "openssl error: update\n"));
Packit fcad23
            EVP_CIPHER_CTX_free(ctx);
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
        }
Packit fcad23
        enclen = len;
Packit fcad23
        rc = EVP_EncryptFinal(ctx, ciphertext + len, &len;;
Packit fcad23
        if (rc != 1) {
Packit fcad23
            DEBUGMSGTL(("scapi:encrypt", "openssl error: final\n"));
Packit fcad23
            EVP_CIPHER_CTX_free(ctx);
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
        }
Packit fcad23
        enclen += len;
Packit fcad23
        ptlen = enclen;
Packit fcad23
        /* Clean up */
Packit fcad23
        EVP_CIPHER_CTX_free(ctx);
Packit fcad23
        *ctlen = ptlen;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
  sc_encrypt_quit:
Packit fcad23
    /*
Packit fcad23
     * clear memory just in case 
Packit fcad23
     */
Packit fcad23
    memset(my_iv, 0, sizeof(my_iv));
Packit fcad23
    memset(pad_block, 0, sizeof(pad_block));
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
    memset(key_struct, 0, sizeof(key_struct));
Packit fcad23
#ifdef OLD_DES
Packit fcad23
    memset(&key_sch, 0, sizeof(key_sch));
Packit fcad23
#else
Packit fcad23
    memset(&key_sched_store, 0, sizeof(key_sched_store));
Packit fcad23
#endif
Packit fcad23
#endif
Packit fcad23
    return rval;
Packit fcad23
Packit fcad23
}                               /* end sc_encrypt() */
Packit fcad23
#elif defined(NETSNMP_USE_PKCS11)
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS, priv_type
Packit fcad23
    u_char	    pkcs_des_key[8];
Packit fcad23
    netsnmp_priv_alg_info *pai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Sanity check.
Packit fcad23
     */
Packit fcad23
#if	!defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
Packit fcad23
    snmp_log(LOG_ERR, "Encryption support not enabled.(1)\n");
Packit fcad23
    return SNMPERR_SC_NOT_CONFIGURED;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen
Packit fcad23
        || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
    } else if (ptlen > *ctlen) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Determine privacy transform.
Packit fcad23
     */
Packit fcad23
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
Packit fcad23
    if (NULL == pai || USM_CREATE_USER_PRIV_DES != priv_type ||
Packit fcad23
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_encrypt_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
Packit fcad23
    memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
Packit fcad23
    rval = pkcs_encrpyt(CKM_DES_CBC, pkcs_des_key,
Packit fcad23
                        sizeof(pkcs_des_key), iv, ivlen, plaintext, ptlen,
Packit fcad23
                        ciphertext, ctlen);
Packit fcad23
Packit fcad23
  sc_encrypt_quit:
Packit fcad23
    return rval;
Packit fcad23
}
Packit fcad23
#else
Packit fcad23
{
Packit fcad23
#	if NETSNMP_USE_INTERNAL_MD5
Packit fcad23
    {
Packit fcad23
        snmp_log(LOG_ERR, "Encryption support not enabled.(3)\n");
Packit fcad23
        DEBUGMSGTL(("scapi", "Encrypt function not defined.\n"));
Packit fcad23
        return SNMPERR_SC_GENERAL_FAILURE;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#	else
Packit fcad23
    _SCAPI_NOT_CONFIGURED
Packit fcad23
#	endif                   /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
}
Packit fcad23
#endif                          /* */
Packit fcad23
Packit fcad23
Packit fcad23
Packit fcad23
/*******************************************************************-o-******
Packit fcad23
 * sc_decrypt
Packit fcad23
 *
Packit fcad23
 * Parameters:
Packit fcad23
 *	 privtype
Packit fcad23
 *	*key
Packit fcad23
 *	 keylen
Packit fcad23
 *	*iv
Packit fcad23
 *	 ivlen
Packit fcad23
 *	*ciphertext
Packit fcad23
 *	 ctlen
Packit fcad23
 *	*plaintext
Packit fcad23
 *	*ptlen
Packit fcad23
 *      
Packit fcad23
 * Returns:
Packit fcad23
 *	SNMPERR_SUCCESS			Success.
Packit fcad23
 *	SNMPERR_SC_NOT_CONFIGURED	Encryption is not supported.
Packit fcad23
 *      SNMPERR_SC_GENERAL_FAILURE      Any other error
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * Decrypt ciphertext into plaintext using key and iv.
Packit fcad23
 *
Packit fcad23
 * ptlen contains actual number of plaintext bytes in plaintext upon
Packit fcad23
 * successful return.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
sc_decrypt(const oid * privtype, size_t privtypelen,
Packit fcad23
           u_char * key, u_int keylen,
Packit fcad23
           u_char * iv, u_int ivlen,
Packit fcad23
           u_char * ciphertext, u_int ctlen,
Packit fcad23
           u_char * plaintext, size_t * ptlen)
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) || defined(NETSNMP_USE_INTERNAL_CRYPTO)
Packit fcad23
{
Packit fcad23
Packit fcad23
    int             rval = SNMPERR_SUCCESS;
Packit fcad23
    u_char          my_iv[128];
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
#ifdef OLD_DES
Packit fcad23
    DES_key_schedule key_sch;
Packit fcad23
#else
Packit fcad23
    DES_key_schedule key_sched_store;
Packit fcad23
    DES_key_schedule *key_sch = &key_sched_store;
Packit fcad23
#endif
Packit fcad23
    DES_cblock      key_struct;
Packit fcad23
#endif
Packit fcad23
    netsnmp_priv_alg_info *pai = NULL;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
Packit fcad23
        || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)) {
Packit fcad23
        DEBUGMSGTL(("scapi", "decrypt: arg sanity checks failed\n"));
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
    }
Packit fcad23
#ifdef NETSNMP_ENABLE_TESTING_CODE
Packit fcad23
    {
Packit fcad23
        size_t          buf_len = 128, out_len = 0;
Packit fcad23
        u_char         *buf = (u_char *) malloc(buf_len);
Packit fcad23
Packit fcad23
        if (buf != NULL) {
Packit fcad23
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         iv, ivlen)) {
Packit fcad23
                DEBUGMSGTL(("scapi", "decrypt: IV: %s\n", buf));
Packit fcad23
            } else {
Packit fcad23
                DEBUGMSGTL(("scapi", "decrypt: IV: %s [TRUNCATED]\n", buf));
Packit fcad23
            }
Packit fcad23
            out_len = 0;
Packit fcad23
            if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1,
Packit fcad23
                                         key, keylen)) {
Packit fcad23
                DEBUGMSG(("scapi", "key: %s\n", buf));
Packit fcad23
            } else {
Packit fcad23
                DEBUGMSG(("scapi", "key: %s [TRUNCATED]\n", buf));
Packit fcad23
            }
Packit fcad23
            free(buf);
Packit fcad23
        } else {
Packit fcad23
            DEBUGMSGTL(("scapi",
Packit fcad23
                        "decrypt: malloc fail for debug output\n"));
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
#endif                          /* NETSNMP_ENABLE_TESTING_CODE */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Determine privacy transform.
Packit fcad23
     */
Packit fcad23
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
Packit fcad23
    if (NULL == pai ||
Packit fcad23
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(my_iv, 0, sizeof(my_iv));
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
    if (USM_CREATE_USER_PRIV_DES == (pai->type & USM_PRIV_MASK_ALG)) {
Packit fcad23
        memcpy(key_struct, key, sizeof(key_struct));
Packit fcad23
        (void) DES_key_sched(&key_struct, key_sch);
Packit fcad23
Packit fcad23
        memcpy(my_iv, iv, ivlen);
Packit fcad23
        DES_cbc_encrypt(ciphertext, plaintext, ctlen, key_sch,
Packit fcad23
                        (DES_cblock *) my_iv, DES_DECRYPT);
Packit fcad23
        *ptlen = ctlen;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
#if defined(NETSNMP_USE_OPENSSL) && defined(HAVE_AES)
Packit fcad23
    if (USM_CREATE_USER_PRIV_AES == (pai->type & USM_PRIV_MASK_ALG)) {
Packit fcad23
        EVP_CIPHER_CTX *ctx;
Packit fcad23
        const EVP_CIPHER *cipher;
Packit fcad23
        int len, rc;
Packit fcad23
Packit fcad23
        cipher = sc_get_openssl_privfn(pai->type);
Packit fcad23
        if (NULL == cipher)
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
Packit fcad23
        memcpy(my_iv, iv, ivlen);
Packit fcad23
        /*
Packit fcad23
         * decrypt the data
Packit fcad23
         */
Packit fcad23
        ctx = EVP_CIPHER_CTX_new();
Packit fcad23
        if (!ctx) {
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
        }
Packit fcad23
        rc = EVP_DecryptInit(ctx, cipher, key, my_iv);
Packit fcad23
        if (rc != 1) {
Packit fcad23
            EVP_CIPHER_CTX_free(ctx);
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
        }
Packit fcad23
        rc = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ctlen);
Packit fcad23
        if (rc != 1) {
Packit fcad23
            EVP_CIPHER_CTX_free(ctx);
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
        }
Packit fcad23
        rc = EVP_DecryptFinal(ctx, plaintext + len, &len;;
Packit fcad23
        if (rc != 1) {
Packit fcad23
            EVP_CIPHER_CTX_free(ctx);
Packit fcad23
            QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
        }
Packit fcad23
        /* Clean up */
Packit fcad23
        EVP_CIPHER_CTX_free(ctx);
Packit fcad23
        *ptlen = ctlen;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * exit cond 
Packit fcad23
     */
Packit fcad23
  sc_decrypt_quit:
Packit fcad23
#ifndef NETSNMP_DISABLE_DES
Packit fcad23
#ifdef OLD_DES
Packit fcad23
    memset(&key_sch, 0, sizeof(key_sch));
Packit fcad23
#else
Packit fcad23
    memset(&key_sched_store, 0, sizeof(key_sched_store));
Packit fcad23
#endif
Packit fcad23
    memset(key_struct, 0, sizeof(key_struct));
Packit fcad23
#endif
Packit fcad23
    memset(my_iv, 0, sizeof(my_iv));
Packit fcad23
    return rval;
Packit fcad23
}				/* USE OPEN_SSL */
Packit fcad23
#elif NETSNMP_USE_PKCS11                  /* USE PKCS */
Packit fcad23
{
Packit fcad23
    int             rval = SNMPERR_SUCCESS;
Packit fcad23
    u_char	    pkcs_des_key[8];
Packit fcad23
    netsnmp_priv_alg_info *pai;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    if (!privtype || !key || !iv || !plaintext || !ciphertext || !ptlen
Packit fcad23
        || (ctlen <= 0) || (*ptlen <= 0) || (*ptlen < ctlen)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * Determine privacy transform.
Packit fcad23
     */
Packit fcad23
    pai = sc_get_priv_alg_byoid(privtype, privtypelen);
Packit fcad23
    if (NULL == pai || USM_CREATE_USER_PRIV_DES != priv_type ||
Packit fcad23
        (keylen < pai->proper_length) || (ivlen < pai->iv_length)) {
Packit fcad23
        QUITFUN(SNMPERR_GENERR, sc_decrypt_quit);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(pkcs_des_key, 0, sizeof(pkcs_des_key));
Packit fcad23
    memcpy(pkcs_des_key, key, sizeof(pkcs_des_key));
Packit fcad23
    rval = pkcs_decrpyt(CKM_DES_CBC, pkcs_des_key, 
Packit fcad23
                        sizeof(pkcs_des_key), iv, ivlen, ciphertext,
Packit fcad23
                        ctlen, plaintext, ptlen);
Packit fcad23
    *ptlen = ctlen;
Packit fcad23
Packit fcad23
  sc_decrypt_quit:
Packit fcad23
    return rval;
Packit fcad23
}				/* USE PKCS */
Packit fcad23
#else
Packit fcad23
{
Packit fcad23
#if	!defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV)
Packit fcad23
    snmp_log(LOG_ERR, "Encryption support not enabled.(4)\n");
Packit fcad23
    return SNMPERR_SC_NOT_CONFIGURED;
Packit fcad23
#else
Packit fcad23
#	if NETSNMP_USE_INTERNAL_MD5
Packit fcad23
    {
Packit fcad23
        DEBUGMSGTL(("scapi", "Decryption function not defined.\n"));
Packit fcad23
        return SNMPERR_SC_GENERAL_FAILURE;
Packit fcad23
    }
Packit fcad23
Packit fcad23
#	else
Packit fcad23
    _SCAPI_NOT_CONFIGURED
Packit fcad23
#	endif                   /* NETSNMP_USE_INTERNAL_MD5 */
Packit fcad23
#endif                          /*  */
Packit fcad23
}
Packit fcad23
#endif                          /* NETSNMP_USE_OPENSSL */
Packit fcad23
Packit fcad23
#ifdef NETSNMP_USE_INTERNAL_CRYPTO
Packit fcad23
Packit fcad23
/* These functions are basically copies of the MDSign() routine in
Packit fcad23
   md5.c modified to be used with the OpenSSL hashing functions.  The
Packit fcad23
   copyright below is from the md5.c file that these functions were
Packit fcad23
   taken from: */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * ** **************************************************************************
Packit fcad23
 * ** md5.c -- Implementation of MD5 Message Digest Algorithm                 **
Packit fcad23
 * ** Updated: 2/16/90 by Ronald L. Rivest                                    **
Packit fcad23
 * ** (C) 1990 RSA Data Security, Inc.                                        **
Packit fcad23
 * ** **************************************************************************
Packit fcad23
 */
Packit fcad23
Packit fcad23
/*
Packit fcad23
 * MD5_hmac(data, len, MD5): do a checksum on an arbirtrary amount
Packit fcad23
 * of data, and prepended with a secret in the standard fashion 
Packit fcad23
 */
Packit fcad23
static int
Packit fcad23
MD5_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
Packit fcad23
         const u_char * secret, size_t secretlen)
Packit fcad23
{
Packit fcad23
#define MD5_HASHKEYLEN 64
Packit fcad23
#define MD5_SECRETKEYLEN 16
Packit fcad23
Packit fcad23
    MD5_CTX         cmd5;
Packit fcad23
    u_char          K1[MD5_HASHKEYLEN];
Packit fcad23
    u_char          K2[MD5_HASHKEYLEN];
Packit fcad23
    u_char          extendedAuthKey[MD5_HASHKEYLEN];
Packit fcad23
    u_char          buf[MD5_HASHKEYLEN];
Packit fcad23
    size_t          i;
Packit fcad23
    const u_char   *cp;
Packit fcad23
    u_char         *newdata = NULL;
Packit fcad23
    int             rc = 0;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * memset(K1,0,MD5_HASHKEYLEN);
Packit fcad23
     * memset(K2,0,MD5_HASHKEYLEN);
Packit fcad23
     * memset(buf,0,MD5_HASHKEYLEN);
Packit fcad23
     * memset(extendedAuthKey,0,MD5_HASHKEYLEN);
Packit fcad23
     */
Packit fcad23
Packit fcad23
    if (secretlen != MD5_SECRETKEYLEN || secret == NULL ||
Packit fcad23
        mac == NULL || data == NULL ||
Packit fcad23
        len <= 0 || maclen <= 0) {
Packit fcad23
        /*
Packit fcad23
         * DEBUGMSGTL(("md5","MD5 signing not properly initialized")); 
Packit fcad23
         */
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(extendedAuthKey, 0, MD5_HASHKEYLEN);
Packit fcad23
    memcpy(extendedAuthKey, secret, secretlen);
Packit fcad23
    for (i = 0; i < MD5_HASHKEYLEN; i++) {
Packit fcad23
        K1[i] = extendedAuthKey[i] ^ 0x36;
Packit fcad23
        K2[i] = extendedAuthKey[i] ^ 0x5c;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    MD5_Init(&cmd5);
Packit fcad23
    rc = !MD5_Update(&cmd5, K1, MD5_HASHKEYLEN);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
Packit fcad23
    i = len;
Packit fcad23
    if (((uintptr_t) data) % sizeof(long) != 0) {
Packit fcad23
        /*
Packit fcad23
         * this relies on the ability to use integer math and thus we
Packit fcad23
         * must rely on data that aligns on 32-bit-word-boundries 
Packit fcad23
         */
Packit fcad23
        newdata = netsnmp_memdup(data, len);
Packit fcad23
        cp = newdata;
Packit fcad23
    } else {
Packit fcad23
        cp = data;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    while (i >= 64) {
Packit fcad23
        rc = !MD5_Update(&cmd5, cp, 64);
Packit fcad23
        if (rc)
Packit fcad23
            goto update_end;
Packit fcad23
        cp += 64;
Packit fcad23
        i -= 64;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    rc = !MD5_Update(&cmd5, cp, i);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
Packit fcad23
    memset(buf, 0, MD5_HASHKEYLEN);
Packit fcad23
    MD5_Final(buf, &cmd5);
Packit fcad23
Packit fcad23
    MD5_Init(&cmd5);
Packit fcad23
    rc = !MD5_Update(&cmd5, K2, MD5_HASHKEYLEN);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
    rc = !MD5_Update(&cmd5, buf, MD5_SECRETKEYLEN);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * copy the sign checksum to the outgoing pointer 
Packit fcad23
     */
Packit fcad23
    MD5_Final(buf, &cmd5);
Packit fcad23
    memcpy(mac, buf, maclen);
Packit fcad23
Packit fcad23
  update_end:
Packit fcad23
    memset(buf, 0, MD5_HASHKEYLEN);
Packit fcad23
    memset(K1, 0, MD5_HASHKEYLEN);
Packit fcad23
    memset(K2, 0, MD5_HASHKEYLEN);
Packit fcad23
    memset(extendedAuthKey, 0, MD5_HASHKEYLEN);
Packit fcad23
    memset(&cmd5, 0, sizeof(cmd5));
Packit fcad23
Packit fcad23
    if (newdata)
Packit fcad23
        free(newdata);
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int
Packit fcad23
SHA1_hmac(const u_char * data, size_t len, u_char * mac, size_t maclen,
Packit fcad23
          const u_char * secret, size_t secretlen)
Packit fcad23
{
Packit fcad23
#define SHA1_HASHKEYLEN   64
Packit fcad23
#define SHA1_SECRETKEYLEN 20
Packit fcad23
Packit fcad23
    SHA_CTX         csha1;
Packit fcad23
    u_char          K1[SHA1_HASHKEYLEN];
Packit fcad23
    u_char          K2[SHA1_HASHKEYLEN];
Packit fcad23
    u_char          extendedAuthKey[SHA1_HASHKEYLEN];
Packit fcad23
    u_char          buf[SHA1_HASHKEYLEN];
Packit fcad23
    size_t          i;
Packit fcad23
    const u_char   *cp;
Packit fcad23
    u_char         *newdata = NULL;
Packit fcad23
    int             rc = 0;
Packit fcad23
Packit fcad23
    DEBUGTRACE;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * memset(K1,0,SHA1_HASHKEYLEN);
Packit fcad23
     * memset(K2,0,SHA1_HASHKEYLEN);
Packit fcad23
     * memset(buf,0,SHA1_HASHKEYLEN);
Packit fcad23
     * memset(extendedAuthKey,0,SHA1_HASHKEYLEN);
Packit fcad23
     */
Packit fcad23
Packit fcad23
    if (secretlen != SHA1_SECRETKEYLEN || secret == NULL ||
Packit fcad23
        mac == NULL || data == NULL ||
Packit fcad23
        len <= 0 || maclen <= 0) {
Packit fcad23
        /*
Packit fcad23
         * DEBUGMSGTL(("sha1","SHA1 signing not properly initialized")); 
Packit fcad23
         */
Packit fcad23
        return -1;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(extendedAuthKey, 0, SHA1_HASHKEYLEN);
Packit fcad23
    memcpy(extendedAuthKey, secret, secretlen);
Packit fcad23
    for (i = 0; i < SHA1_HASHKEYLEN; i++) {
Packit fcad23
        K1[i] = extendedAuthKey[i] ^ 0x36;
Packit fcad23
        K2[i] = extendedAuthKey[i] ^ 0x5c;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    SHA1_Init(&csha1);
Packit fcad23
    rc = !SHA1_Update(&csha1, K1, SHA1_HASHKEYLEN);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
Packit fcad23
    i = len;
Packit fcad23
    if (((uintptr_t) data) % sizeof(long) != 0) {
Packit fcad23
        /*
Packit fcad23
         * this relies on the ability to use integer math and thus we
Packit fcad23
         * must rely on data that aligns on 32-bit-word-boundries 
Packit fcad23
         */
Packit fcad23
        newdata = netsnmp_memdup(data, len);
Packit fcad23
        cp = newdata;
Packit fcad23
    } else {
Packit fcad23
        cp = data;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    while (i >= 64) {
Packit fcad23
        rc = !SHA1_Update(&csha1, cp, 64);
Packit fcad23
        if (rc)
Packit fcad23
            goto update_end;
Packit fcad23
        cp += 64;
Packit fcad23
        i -= 64;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    rc = !SHA1_Update(&csha1, cp, i);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
Packit fcad23
    memset(buf, 0, SHA1_HASHKEYLEN);
Packit fcad23
    SHA1_Final(buf, &csha1);
Packit fcad23
Packit fcad23
    SHA1_Init(&csha1);
Packit fcad23
    rc = !SHA1_Update(&csha1, K2, SHA1_HASHKEYLEN);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
    rc = !SHA1_Update(&csha1, buf, SHA1_SECRETKEYLEN);
Packit fcad23
    if (rc)
Packit fcad23
        goto update_end;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * copy the sign checksum to the outgoing pointer 
Packit fcad23
     */
Packit fcad23
    SHA1_Final(buf, &csha1);
Packit fcad23
    memcpy(mac, buf, maclen);
Packit fcad23
Packit fcad23
  update_end:
Packit fcad23
    memset(buf, 0, SHA1_HASHKEYLEN);
Packit fcad23
    memset(K1, 0, SHA1_HASHKEYLEN);
Packit fcad23
    memset(K2, 0, SHA1_HASHKEYLEN);
Packit fcad23
    memset(extendedAuthKey, 0, SHA1_HASHKEYLEN);
Packit fcad23
    memset(&csha1, 0, sizeof(csha1));
Packit fcad23
Packit fcad23
    if (newdata)
Packit fcad23
        free(newdata);
Packit fcad23
    return rc;
Packit fcad23
}
Packit fcad23
#endif /* NETSNMP_USE_INTERNAL_CRYPTO */
Packit fcad23
#endif /*  NETSNMP_FEATURE_REMOVE_USM_SCAPI  */