auth_priv.cpp
上传用户:ets1996
上传日期:2014-09-30
资源大小:353k
文件大小:61k
源码类别:

SNMP编程

开发平台:

Visual C++

  1. /*_############################################################################
  2.   _## 
  3.   _##  auth_priv.cpp  
  4.   _##
  5.   _##  SNMP++v3.2.22
  6.   _##  -----------------------------------------------
  7.   _##  Copyright (c) 2001-2007 Jochen Katz, Frank Fock
  8.   _##
  9.   _##  This software is based on SNMP++2.6 from Hewlett Packard:
  10.   _##  
  11.   _##    Copyright (c) 1996
  12.   _##    Hewlett-Packard Company
  13.   _##  
  14.   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
  15.   _##  Permission to use, copy, modify, distribute and/or sell this software 
  16.   _##  and/or its documentation is hereby granted without fee. User agrees 
  17.   _##  to display the above copyright notice and this license notice in all 
  18.   _##  copies of the software and any documentation of the software. User 
  19.   _##  agrees to assume all liability for the use of the software; 
  20.   _##  Hewlett-Packard and Jochen Katz make no representations about the 
  21.   _##  suitability of this software for any purpose. It is provided 
  22.   _##  "AS-IS" without warranty of any kind, either express or implied. User 
  23.   _##  hereby grants a royalty-free license to any and all derivatives based
  24.   _##  upon this software code base. 
  25.   _##  
  26.   _##  Stuttgart, Germany, Wed May  2 23:22:30 CEST 2007 
  27.   _##  
  28.   _##########################################################################*/
  29. char auth_priv_version[]="@(#) SNMP++ $Id: auth_priv.cpp 256 2006-06-03 20:16:00Z katz $";
  30. #include "snmp_pp/config_snmp_pp.h"
  31. #ifdef _SNMPv3
  32. #include <string.h>
  33. #include <stdlib.h>
  34. #include <time.h>
  35. // Only use DES, AES, SHA1 and MD5 from libtomcrypt if openssl is not used
  36. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  37. #include <tomcrypt.h>
  38. #endif
  39. // Use DES, AES, SHA and MD5 from openssl
  40. #ifdef _USE_OPENSSL
  41. #include <openssl/des.h>
  42. #include <openssl/aes.h>
  43. #include <openssl/sha.h>
  44. #include <openssl/md5.h>
  45. #endif
  46. // Use internal functions for SHA and MD5 and libdes only
  47. // if not using libtomcrypt and openssl
  48. #if !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  49. #include "snmp_pp/sha.h"
  50. #ifdef RSAEURO
  51. #include <rsaeuro.h>
  52. #else
  53. #include <des.h>
  54. #include "snmp_pp/md5.h"
  55. #endif
  56. #endif // !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  57. // IDEA can only be used with a valid license
  58. #ifdef _USE_IDEA
  59. #include "snmp_pp/idea.h"
  60. #endif
  61. #include "snmp_pp/auth_priv.h"
  62. #include "snmp_pp/v3.h"
  63. #include "snmp_pp/snmperrs.h"
  64. #include "snmp_pp/address.h"
  65. #include "snmp_pp/log.h"
  66. #ifdef SNMP_PP_NAMESPACE
  67. namespace Snmp_pp {
  68. #endif
  69. /*-----------------[ defines for crypto libraries ]------------------*/
  70. #ifdef _USE_OPENSSL
  71. /* -- START: Defines for OpenSSL -- */
  72. typedef SHA_CTX               SHAHashStateType;
  73. #define SHA1_INIT(s)          SHA1_Init(s)
  74. #define SHA1_PROCESS(s, p, l) SHA1_Update(s, p, l)
  75. #define SHA1_DONE(s, k)       SHA1_Final(k, s)
  76. typedef MD5_CTX               MD5HashStateType;
  77. #define MD5_INIT(s)           MD5_Init(s)
  78. #define MD5_PROCESS(s, p, l)  MD5_Update(s, p, l)
  79. #define MD5_DONE(s, k)        MD5_Final(k, s)
  80. typedef des_key_schedule      DESCBCType;
  81. #define DES_CBC_START_ENCRYPT(c, iv, k, kl, r, s) 
  82.                  if (des_key_sched((C_Block*)(k), s) < 0) 
  83.                  { 
  84.    debugprintf(0, "Starting DES encryption failed."); 
  85.    return SNMPv3_USM_ERROR; 
  86.                  }
  87. #define DES_CBC_START_DECRYPT(c, iv, k, kl, r, s) 
  88.                  if (des_key_sched((C_Block*)(k), s) < 0) 
  89.                  { 
  90.    debugprintf(0, "Starting DES decryption failed."); 
  91.    return SNMPv3_USM_ERROR; 
  92.                  }
  93. #define DES_CBC_ENCRYPT(pt, ct, s, iv, l) 
  94.                         des_ncbc_encrypt(pt, ct, l, 
  95.                                          s, (C_Block*)(iv), DES_ENCRYPT)
  96. #define DES_CBC_DECRYPT(ct, pt, s, iv, l) 
  97.                         des_ncbc_encrypt(ct, pt, l, 
  98.                                          s, (C_Block*)(iv), DES_DECRYPT)
  99. #define DES_EDE3_CBC_ENCRYPT(pt, ct, l, k1, k2, k3, iv) 
  100.                des_ede3_cbc_encrypt(pt, ct, l, 
  101.                                     k1, k2, k3, (C_Block*)(iv), DES_ENCRYPT)
  102. #define DES_EDE3_CBC_DECRYPT(ct, pt, l, k1, k2, k3, iv) 
  103.                des_ede3_cbc_encrypt(ct, pt, l, 
  104.                                     k1, k2, k3, (C_Block*)(iv), DES_DECRYPT)
  105. #define DES_MEMSET(s, c, l)   memset(&(s), c, l)
  106. /* -- END: Defines for OpenSSL -- */
  107. #else
  108. #ifdef _USE_LIBTOMCRYPT
  109. /* -- START: Defines for LibTomCrypt -- */
  110. typedef hash_state            SHAHashStateType;
  111. #define SHA1_INIT(s)          sha1_init(s)
  112. #define SHA1_PROCESS(s, p, l) sha1_process(s, p, l)
  113. #define SHA1_DONE(s, k)       sha1_done(s, k)
  114. typedef hash_state            MD5HashStateType;
  115. #define MD5_INIT(s)           md5_init(s)
  116. #define MD5_PROCESS(s, p, l)  md5_process(s, p, l)
  117. #define MD5_DONE(s, k)        md5_done(s, k)
  118. typedef symmetric_CBC         DESCBCType;
  119. #define DES_CBC_START_ENCRYPT(c, iv, k, kl, r, s) 
  120.                  if (cbc_start(c, iv, k, kl, r, &(s)) != CRYPT_OK) 
  121.                  { 
  122.    debugprintf(0, "Starting DES encryption failed."); 
  123.    return SNMPv3_USM_ERROR; 
  124.                  }
  125. #define DES_CBC_START_DECRYPT(c, iv, k, kl, r, s) 
  126.                  if (cbc_start(c, iv, k, kl, r, &(s)) != CRYPT_OK) 
  127.                  { 
  128.    debugprintf(0, "Starting DES decryption failed."); 
  129.    return SNMPv3_USM_ERROR; 
  130.                  }
  131. #define DES_CBC_ENCRYPT(pt, ct, s, iv, l) 
  132.                  if (cbc_encrypt(pt, ct, l, &(s)) != CRYPT_OK) 
  133.                  { 
  134.    debugprintf(0, "Error during DES encryption."); 
  135.    return SNMPv3_USM_ERROR; 
  136.                  }
  137. #define DES_CBC_DECRYPT(ct, pt, s, iv, l) 
  138.                  if (cbc_decrypt(ct, pt, l, &(s)) != CRYPT_OK) 
  139.                  { 
  140.    debugprintf(0, "Error during DES decryption."); 
  141.    return SNMPv3_USM_ERROR; 
  142.                  }
  143. #define DES_MEMSET(s, c, l)   memset(&(s), c, l)
  144. /* -- END: Defines for LibTomCrypt -- */
  145. #else // _USE_LIBTOMCRYPT  --> libdes
  146. /* -- START: Defines for libdes -- */
  147. typedef SHA_CTX               SHAHashStateType;
  148. #define SHA1_INIT(s)          SHAInit(s)
  149. #define SHA1_PROCESS(s, p, l) SHAUpdate(s, p, l)
  150. #define SHA1_DONE(s, k)       SHAFinal(k, s)
  151. typedef MD5_CTX               MD5HashStateType;
  152. #define MD5_INIT(s)           MD5Init(s)
  153. #define MD5_PROCESS(s, p, l)  MD5Update(s, p, l)
  154. #define MD5_DONE(s, k)        MD5Final(k, s)
  155. #define DES_EDE3_CBC_ENCRYPT(pt, ct, l, k1, k2, k3, iv) 
  156.                des_ede3_cbc_encrypt((C_Block*)(pt), (C_Block*)(ct), l, 
  157.                                     k1, k2, k3, (C_Block*)(iv), DES_ENCRYPT)
  158. #define DES_EDE3_CBC_DECRYPT(ct, pt, l, k1, k2, k3, iv) 
  159.                des_ede3_cbc_encrypt((C_Block*)(ct), (C_Block*)(pt), l, 
  160.                                     k1, k2, k3, (C_Block*)(iv), DES_DECRYPT)
  161. #ifdef RSAEURO
  162. #undef  MD5_PROCESS
  163. #define MD5_PROCESS(s, p, l)  MD5Update(s, (unsigned char*)(p), l)
  164. typedef DES_CBC_CTX           DESCBCType;
  165. #define DES_CBC_START_ENCRYPT(c, iv, k, kl, r, s) 
  166.                               DES_CBCInit(&(s), (unsigned char*)(k), iv, 1)
  167. #define DES_CBC_START_DECRYPT(c, iv, k, kl, r, s) 
  168.                               DES_CBCInit(&(s),(unsigned char*)(k), iv, 0)
  169. #define DES_CBC_ENCRYPT(pt, ct, s, iv, l) DES_CBCUpdate(&(s), pt, ct, l)
  170. #define DES_CBC_DECRYPT(ct, pt, s, iv, l) DES_CBCUpdate(&(s), (unsigned char*)(ct), pt, l)
  171. #define DES_MEMSET(s, c, l)   R_memset((POINTER)&(s), c, l)
  172. #else // RSAEURO
  173. typedef des_key_schedule      DESCBCType;
  174. #define DES_CBC_START_ENCRYPT(c, iv, k, kl, r, s) 
  175.                  if (des_key_sched((C_Block*)(k), s) < 0) 
  176.                  { 
  177.    debugprintf(0, "Starting DES encryption failed."); 
  178.    return SNMPv3_USM_ERROR; 
  179.                  }
  180. #define DES_CBC_START_DECRYPT(c, iv, k, kl, r, s) 
  181.                  if (des_key_sched((C_Block*)(k), s) < 0) 
  182.                  { 
  183.    debugprintf(0, "Starting DES decryption failed."); 
  184.    return SNMPv3_USM_ERROR; 
  185.                  }
  186. #define DES_CBC_ENCRYPT(pt, ct, s, iv, l) 
  187.                         des_ncbc_encrypt((C_Block*)(pt), (C_Block*)(ct), l, 
  188.                                          s, (C_Block*)(iv), DES_ENCRYPT)
  189. #define DES_CBC_DECRYPT(ct, pt, s, iv, l) 
  190.                         des_ncbc_encrypt((C_Block*)(ct), (C_Block*)(pt), l, 
  191.                                          s, (C_Block*)(iv), DES_DECRYPT)
  192. #define DES_MEMSET(s, c, l)   memset(&(s), c, l)
  193. /* -- END: Defines for libdes -- */
  194. #endif // RSAEURO
  195. #endif // _USE_LIBTOMCRYPT
  196. #endif // _USE_OPENSSL
  197. AuthPriv::AuthPriv(int &construct_state)
  198. {
  199.   auth = new AuthPtr[10];
  200.   priv = new PrivPtr[10];
  201.   if (auth)
  202.     auth_size = 10;
  203.   else
  204.   {
  205.     auth_size = 0;
  206.     LOG_BEGIN(ERROR_LOG | 1);
  207.     LOG("AuthPriv: Error allocating array for authentication.");
  208.     LOG_END;
  209.   }
  210.   if (priv)
  211.     priv_size = 10;
  212.   else
  213.   {
  214.     priv_size = 0;
  215.     LOG_BEGIN(ERROR_LOG | 1);
  216.     LOG("AuthPriv: Error allocating array for privacy.");
  217.     LOG_END;
  218.   }
  219.   for (int i = 0; i < auth_size; i++)
  220.     auth[i] = 0;
  221.   for (int j = 0; j < priv_size; j++)
  222.     priv[j] = 0;
  223.   /* Check size of salt, has to be 64 bits */
  224.   if (sizeof(salt) != 8)
  225.   {
  226.     LOG_BEGIN(ERROR_LOG | 1);
  227.     LOG("AuthPriv: *BUG* sizeof(pp_uint64) is not 8 bytes. snmp++ has to be patched for this system.");
  228.     LOG_END;
  229.     construct_state = SNMPv3_USM_ERROR;
  230.     return;
  231.   }
  232.   /* Initialize salt. srand() has been already done in Snmp::init() */
  233.   unsigned int *rnd = (unsigned int*)&salt;
  234.   *rnd = rand() << 1;
  235.   if (rand() < (RAND_MAX / 2))
  236.     *rnd += 1;
  237.   rnd++;
  238.   *rnd = rand() << 1;
  239.   if (rand() < (RAND_MAX / 2))
  240.     *rnd += 1;
  241.   construct_state = SNMPv3_USM_OK;
  242. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  243.   /* register needed hashes and ciphers in libtomcrypt */
  244.   if (register_cipher(&rijndael_desc) < 0)
  245.   {
  246.     LOG_BEGIN(ERROR_LOG | 1);
  247.     LOG("AuthPriv: Error registering Rijndael.");
  248.     LOG_END;
  249.     construct_state = SNMPv3_USM_ERROR;
  250.   }
  251.   if (register_cipher(&des_desc) < 0)
  252.   {
  253.     LOG_BEGIN(ERROR_LOG | 1);
  254.     LOG("AuthPriv: Error registering DES.");
  255.     LOG_END;
  256.     construct_state = SNMPv3_USM_ERROR;
  257.   }
  258.   if (register_cipher(&des3_desc) < 0)
  259.   {
  260.     LOG_BEGIN(ERROR_LOG | 1);
  261.     LOG("AuthPriv: Error registering 3DES.");
  262.     LOG_END;
  263.     construct_state = SNMPv3_USM_ERROR;
  264.   }
  265.   if (register_hash(&sha1_desc) < 0)
  266.   {
  267.     LOG_BEGIN(ERROR_LOG | 1);
  268.     LOG("AuthPriv: Error registering SHA1.");
  269.     LOG_END;
  270.     construct_state = SNMPv3_USM_ERROR;
  271.   }
  272.   if (register_hash(&md5_desc) < 0)
  273.   {
  274.     LOG_BEGIN(ERROR_LOG | 1);
  275.     LOG("AuthPriv: Error registering MD5.");
  276.     LOG_END;
  277.     construct_state = SNMPv3_USM_ERROR;
  278.   }
  279. #endif // defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  280. }
  281. AuthPriv::~AuthPriv()
  282. {
  283.   for (int i = 0; i < auth_size; i++)
  284.     if (auth[i])
  285.     {
  286.       delete auth[i];
  287.       auth[i] = 0;
  288.     }
  289.   for (int j = 0; j < priv_size; j++)
  290.     if (priv[j])
  291.     {
  292.       delete priv[j];
  293.       priv[j] = 0;
  294.     }
  295.   delete [] auth;
  296.   delete [] priv;
  297. }
  298. int AuthPriv::add_auth(Auth *new_auth)
  299. {
  300.   if (!new_auth)
  301.   {
  302.     return SNMP_CLASS_ERROR;
  303.   }
  304.   int id = new_auth->get_id();
  305.   if (id < 0)
  306.   {
  307.     return SNMP_CLASS_ERROR;
  308.   }
  309.   if (id >= auth_size)
  310.   {
  311.     AuthPtr *new_array = new AuthPtr[id + 5];
  312.     if (!new_array)
  313.     {
  314.       LOG_BEGIN(ERROR_LOG | 1);
  315.       LOG("AuthPriv: Could not allocate new auth array.");
  316.       LOG_END;
  317.       return SNMP_CLASS_ERROR;
  318.     }
  319.     for (int i=0 ; i<auth_size; i++)
  320.       new_array[i] = auth[i];
  321.     for (int j=auth_size ; j<id + 5; j++)
  322.       new_array[j] = 0;
  323.     AuthPtr *victim = auth;
  324.     auth = new_array;
  325.     delete [] victim;
  326.     auth_size = id + 5;
  327.   }
  328.   new_auth->set_salt(&salt);
  329.   if (auth[id])
  330.   {
  331.     LOG_BEGIN(WARNING_LOG | 4);
  332.     LOG("AuthPriv: deleting old auth object before adding new one (id)");
  333.     LOG(id);
  334.     LOG_END;
  335.     delete auth[id];
  336.   }
  337.   auth[id] = new_auth;
  338.   LOG_BEGIN(INFO_LOG | 6);
  339.   LOG("AuthPriv: Added auth protocol (id)");
  340.   LOG(id);
  341.   LOG_END;
  342.   return SNMP_CLASS_SUCCESS;
  343. }
  344. int AuthPriv::del_auth(const int auth_id)
  345. {
  346.   if ((auth_id < 0) || (auth_id >= auth_size) || (auth[auth_id] == 0))
  347.   {
  348.     LOG_BEGIN(WARNING_LOG | 4);
  349.     LOG("AuthPriv: Request to delete non existing auth protocol (id)");
  350.     LOG(auth_id);
  351.     LOG_END;
  352.     return SNMP_CLASS_ERROR;
  353.   }
  354.   delete auth[auth_id];
  355.   auth[auth_id] = 0;
  356.   LOG_BEGIN(INFO_LOG | 6);
  357.   LOG("AuthPriv: Removed auth protocol (id)");
  358.   LOG(auth_id);
  359.   LOG_END;
  360.   return SNMP_CLASS_SUCCESS;
  361. }
  362. int AuthPriv::add_priv(Priv *new_priv)
  363. {
  364.   if (!new_priv)
  365.   {
  366.     return SNMP_CLASS_ERROR;
  367.   }
  368.   int id = new_priv->get_id();
  369.   if (id < 0)
  370.   {
  371.     return SNMP_CLASS_ERROR;
  372.   }
  373.   if (id >= priv_size)
  374.   {
  375.     PrivPtr *new_array = new PrivPtr[id + 5];
  376.     if (!new_array)
  377.     {
  378.       LOG_BEGIN(ERROR_LOG | 1);
  379.       LOG("AuthPriv: Could not allocate new priv array.");
  380.       LOG_END;
  381.       return SNMP_CLASS_ERROR;
  382.     }
  383.     for (int i=0 ; i<priv_size; i++)
  384.       new_array[i] = priv[i];
  385.     for (int j=priv_size ; j<id + 5; j++)
  386.       new_array[j] = 0;
  387.     PrivPtr *victim = priv;
  388.     priv = new_array;
  389.     delete [] victim;
  390.     priv_size = id + 5;
  391.   }
  392.   new_priv->set_salt(&salt);
  393.   if (priv[id])
  394.   {
  395.     LOG_BEGIN(WARNING_LOG | 4);
  396.     LOG("AuthPriv: deleting old priv object before adding new one (id)");
  397.     LOG(id);
  398.     LOG_END;
  399.     delete priv[id];
  400.   }
  401.   priv[id] = new_priv;
  402.   LOG_BEGIN(INFO_LOG | 6);
  403.   LOG("AuthPriv: Added priv protocol (id)");
  404.   LOG(id);
  405.   LOG_END;
  406.   return SNMP_CLASS_SUCCESS;
  407. }
  408. int AuthPriv::del_priv(const int priv_id)
  409. {
  410.   if ((priv_id < 0) || (priv_id >= priv_size) || (priv[priv_id] == 0))
  411.   {
  412.     LOG_BEGIN(WARNING_LOG | 4);
  413.     LOG("AuthPriv: Request to delete non existing priv protocol (id)");
  414.     LOG(priv_id);
  415.     LOG_END;
  416.     return SNMP_CLASS_ERROR;
  417.   }
  418.   delete priv[priv_id];
  419.   priv[priv_id] = 0;
  420.   LOG_BEGIN(INFO_LOG | 6);
  421.   LOG("AuthPriv: Removed priv protocol (id)");
  422.   LOG(priv_id);
  423.   LOG_END;
  424.   return SNMP_CLASS_SUCCESS;
  425. }
  426. Auth *AuthPriv::get_auth(const int auth_prot)
  427. {
  428.   if ((auth_prot >= 0) && (auth_prot < auth_size))
  429.     return auth[auth_prot];
  430.   return 0;
  431. }
  432. Priv *AuthPriv::get_priv(const int priv_prot)
  433. {
  434.   if ((priv_prot >= 0) && (priv_prot < priv_size))
  435.     return priv[priv_prot];
  436.   return 0;
  437. }
  438. // Get the unique id for the given auth protocol.
  439. int AuthPriv::get_auth_id(const char *string_id) const
  440. {
  441.   for (int i = 0; i < auth_size; ++i)
  442.     if ((auth[i]) && (strcmp(string_id, auth[i]->get_id_string()) == 0))
  443.       return i;
  444.   return -1;
  445. }
  446. // Get the unique id for the given priv protocol.
  447. int AuthPriv::get_priv_id(const char *string_id) const
  448. {
  449.   for (int i = 0; i < priv_size; ++i)
  450.     if ((priv[i]) && (strcmp(string_id, priv[i]->get_id_string()) == 0))
  451.       return i;
  452.   return -1;
  453. }
  454. int AuthPriv::get_keychange_value(const int       auth_prot,
  455.                                   const OctetStr& old_key,
  456.                                   const OctetStr& new_key,
  457.                                   OctetStr&       keychange_value)
  458. {
  459.   // uses fixed key length determined from oldkey!
  460.   // works with SHA and MD5
  461.   // modifications needed to support variable length keys
  462.   // algorithm according to USM-document textual convention KeyChange
  463.   int key_len = old_key.len();
  464.   Auth *a = get_auth(auth_prot);
  465.   if (!a)
  466.     return SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL;
  467.   // compute random value
  468.   OctetStr random = "";
  469.   for (int i=0; i<key_len; i++) {
  470. #ifdef _TEST
  471.     // do not use random values for testing
  472.     random += OctetStr((unsigned char*)"",1);
  473. #else
  474.     char tmprand = rand();
  475.     random += tmprand;
  476. #endif
  477.   }
  478. #ifdef __DEBUG
  479.   debugprintf(21, "Values for keyChange:");
  480.   debughexcprintf(21, "old_key", old_key.data(), old_key.len());
  481.   debughexcprintf(21, "new_key", new_key.data(), new_key.len());
  482.   debughexcprintf(21, "random value", random.data(), random.len());
  483. #endif
  484.   // step 1: initialize temporary variable
  485.   OctetStr tmp = old_key;
  486.   // step 2: nothing to do as we only support fixed length keys ;-)
  487.   // step 3:
  488.   tmp += random;
  489.   unsigned char digest[SNMPv3_USM_MAX_KEY_LEN];
  490.   memset((char*)digest, 0, SNMPv3_USM_MAX_KEY_LEN);
  491.   a->hash(tmp.data(), tmp.len(), digest);
  492.   // step 4:
  493.   keychange_value = random;
  494.   keychange_value += new_key;
  495.   for (unsigned int j = key_len; j < keychange_value.len(); j++) {
  496.     keychange_value[j] = keychange_value[j] ^ digest[j - key_len];
  497.   }
  498. #ifdef __DEBUG
  499.   debughexcprintf(21, "keychange_value",
  500.                   keychange_value.data(), keychange_value.len());
  501. #endif
  502.   return SNMPv3_USM_OK;
  503. }
  504. int AuthPriv::password_to_key_auth(const int            auth_prot,
  505.                                    const unsigned char *password,
  506.                                    const unsigned int   password_len,
  507.                                    const unsigned char *engine_id,
  508.                                    const unsigned int   engine_id_len,
  509.                                    unsigned char *key,
  510.                                    unsigned int  *key_len)
  511. {
  512.   if (auth_prot == SNMP_AUTHPROTOCOL_NONE)
  513.   {
  514.     *key_len = 0;
  515.     return SNMPv3_USM_OK;
  516.   }
  517.   if (!password || (password_len == 0))
  518.   {
  519.     LOG_BEGIN(WARNING_LOG | 2);
  520.     LOG("AuthPriv: Password to key auth needs a non empty password");
  521.     LOG_END;
  522.     return SNMPv3_USM_ERROR;
  523.   }
  524.   Auth *a = get_auth(auth_prot);
  525.   if (!a)
  526.     return SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL;
  527.   int res = a->password_to_key(password, password_len,
  528.                                engine_id, engine_id_len,
  529.                                key, key_len);
  530.   return res;
  531. }
  532. int AuthPriv::password_to_key_priv(const int            auth_prot,
  533.                                    const int            priv_prot,
  534.                                    const unsigned char *password,
  535.                                    const unsigned int   password_len,
  536.                                    const unsigned char *engine_id,
  537.                                    const unsigned int   engine_id_len,
  538.                                    unsigned char *key,
  539.                                    unsigned int  *key_len)
  540. {
  541.   /* check for priv protocol */
  542.   if (priv_prot == SNMP_PRIVPROTOCOL_NONE)
  543.   {
  544.     *key_len = 0;
  545.     return SNMPv3_USM_OK;
  546.   }
  547.   if (!password || (password_len == 0))
  548.   {
  549.     LOG_BEGIN(WARNING_LOG | 2);
  550.     LOG("AuthPriv: Password to key priv needs a non empty password");
  551.     LOG_END;
  552.     return SNMPv3_USM_ERROR;
  553.   }
  554.   Priv *p = get_priv(priv_prot);
  555.   Auth *a = get_auth(auth_prot);
  556.   if (!p)  return SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL;
  557.   if (!a)  return SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL;
  558.   unsigned int max_key_len = *key_len; /* save length of buffer! */
  559.   unsigned int min_key_len = p->get_min_key_len();
  560.   /* check if buffer for key is long enough */
  561.   if (min_key_len > max_key_len)
  562.     return SNMPv3_USM_ERROR; // TODO: better error code!
  563.   int res = password_to_key_auth(auth_prot,
  564.  password, password_len,
  565.  engine_id, engine_id_len,
  566.  key, key_len);
  567.   if (res != SNMPv3_USM_OK)
  568.     return res;
  569.   /* We have a too short key: Call priv protocoll to extend it */
  570.   if (*key_len < min_key_len)
  571.   {
  572.     res = p->extend_short_key(password, password_len,
  573.       engine_id, engine_id_len,
  574.       key, key_len, max_key_len, a);
  575.     if (res != SNMPv3_USM_OK)
  576.       return res;
  577.   }
  578.   /* make sure key length is valid */
  579.   p->fix_key_len(*key_len);
  580.   return SNMPv3_USM_OK;
  581. }
  582. int AuthPriv::encrypt_msg(const int            priv_prot,
  583.                           const unsigned char *key,
  584.                           const unsigned int   key_len,
  585.                           const unsigned char *buffer,
  586.                           const unsigned int   buffer_len,
  587.                           unsigned char       *out_buffer,
  588.                           unsigned int        *out_buffer_len,
  589.                           unsigned char       *privacy_params,
  590.                           unsigned int        *privacy_params_len,
  591.                           const unsigned long  engine_boots,
  592.                           const unsigned long  engine_time)
  593. {
  594.   /* check for priv protocol */
  595.   Priv *p = get_priv(priv_prot);
  596.   if (!p)
  597.     return SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL;
  598.   return p->encrypt(key, key_len, buffer, buffer_len,
  599.                     out_buffer, out_buffer_len,
  600.                     privacy_params, privacy_params_len,
  601.                     engine_boots, engine_time);
  602. }
  603. int AuthPriv::decrypt_msg(const int            priv_prot,
  604.                           const unsigned char *key,
  605.                           const unsigned int   key_len,
  606.                           const unsigned char *buffer,
  607.                           const unsigned int   buffer_len,
  608.                           unsigned char       *out_buffer,
  609.                           unsigned int        *out_buffer_len,
  610.                           const unsigned char *privacy_params,
  611.                           const unsigned int   privacy_params_len,
  612.   const unsigned long  engine_boots,
  613.   const unsigned long  engine_time)
  614. {
  615.   /* check for priv protocol */
  616.   Priv *p = get_priv(priv_prot);
  617.   if (!p)
  618.     return SNMPv3_USM_UNSUPPORTED_PRIVPROTOCOL;
  619.   return p->decrypt(key, key_len, buffer, buffer_len,
  620.                     out_buffer, out_buffer_len,
  621.                     privacy_params, privacy_params_len,
  622.     engine_boots, engine_time);
  623. }
  624. int AuthPriv::add_default_modules()
  625. {
  626.   int ret = SNMP_CLASS_SUCCESS;
  627.   if (add_auth(new AuthSHA()) != SNMP_ERROR_SUCCESS)
  628.   {
  629.     LOG_BEGIN(ERROR_LOG | 1);
  630.     LOG("AuthPriv: Could not add default protocol AuthSHA.");
  631.     LOG_END;
  632.     ret = SNMP_CLASS_ERROR;
  633.   }
  634.   if (add_auth(new AuthMD5()) != SNMP_ERROR_SUCCESS)
  635.   {
  636.     LOG_BEGIN(ERROR_LOG | 1);
  637.     LOG("AuthPriv: Could not add default protocol AuthMD5.");
  638.     LOG_END;
  639.     ret = SNMP_CLASS_ERROR;
  640.   }
  641.   if (add_priv(new PrivDES()) != SNMP_ERROR_SUCCESS)
  642.   {
  643.     LOG_BEGIN(ERROR_LOG | 1);
  644.     LOG("AuthPriv: Could not add default protocol PrivDES.");
  645.     LOG_END;
  646.     ret = SNMP_CLASS_ERROR;
  647.   }
  648. #ifdef _USE_IDEA
  649.   if (add_priv(new PrivIDEA()) != SNMP_ERROR_SUCCESS)
  650.   {
  651.     LOG_BEGIN(ERROR_LOG | 1);
  652.     LOG("AuthPriv: Could not add default protocol PrivIDEA.");
  653.     LOG_END;
  654.     ret = SNMP_CLASS_ERROR;
  655.   }
  656. #endif
  657. #if defined(_USE_LIBTOMCRYPT) || defined(_USE_OPENSSL)
  658.   if (add_priv(new PrivAES(SNMP_PRIVPROTOCOL_AES128)) != SNMP_ERROR_SUCCESS)
  659.   {
  660.     LOG_BEGIN(ERROR_LOG | 1);
  661.     LOG("AuthPriv: Could not add default protocol PrivAES 128.");
  662.     LOG_END;
  663.     ret = SNMP_CLASS_ERROR;
  664.   }
  665.   if (add_priv(new PrivAES(SNMP_PRIVPROTOCOL_AES192)) != SNMP_ERROR_SUCCESS)
  666.   {
  667.     LOG_BEGIN(ERROR_LOG | 1);
  668.     LOG("AuthPriv: Could not add default protocol PrivAES 192.");
  669.     LOG_END;
  670.     ret = SNMP_CLASS_ERROR;
  671.   }
  672.   if (add_priv(new PrivAES(SNMP_PRIVPROTOCOL_AES256)) != SNMP_ERROR_SUCCESS)
  673.   {
  674.     LOG_BEGIN(ERROR_LOG | 1);
  675.     LOG("AuthPriv: Could not add default protocol PrivAES 256.");
  676.     LOG_END;
  677.     ret = SNMP_CLASS_ERROR;
  678.   }
  679. #endif
  680. #ifdef _USE_3DES_EDE
  681.   if (add_priv(new Priv3DES_EDE()) != SNMP_ERROR_SUCCESS)
  682.   {
  683.     LOG_BEGIN(ERROR_LOG | 1);
  684.     LOG("AuthPriv: Could not add default protocol Priv3DES_EDE.");
  685.     LOG_END;
  686.     ret = SNMP_CLASS_ERROR;
  687.   }
  688. #endif
  689.   if (ret == SNMP_CLASS_SUCCESS)
  690.   {
  691.     LOG_BEGIN(INFO_LOG | 3);
  692.     LOG("AuthPriv: Added default Auth and Priv protocols.");
  693.     LOG_END;
  694.   }
  695.   return ret;
  696. }
  697. int AuthPriv::get_auth_params_len(const int auth_prot)
  698. {
  699.   Auth *a = get_auth(auth_prot);
  700.   if (!a)
  701.     return 0;
  702.   return a->get_auth_params_len();
  703. }
  704. int AuthPriv::get_priv_params_len(const int priv_prot)
  705. {
  706.   Priv *p = get_priv(priv_prot);
  707.   if (!p)
  708.     return 0;
  709.   return p->get_priv_params_len();
  710. }
  711. int AuthPriv::auth_out_msg(const int            auth_prot,
  712.                            const unsigned char *key,
  713.                            unsigned char       *msg,
  714.                            const int            msg_len,
  715.                            unsigned char       *auth_par_ptr)
  716. {
  717.   if (auth_prot == SNMP_AUTHPROTOCOL_NONE)
  718.     return SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL;
  719.   Auth *a = get_auth(auth_prot);
  720.   if (!a)
  721.     return SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL;
  722.   return a->auth_out_msg(key, msg, msg_len, auth_par_ptr);
  723. }
  724. int AuthPriv::auth_inc_msg(const int            auth_prot,
  725.                            const unsigned char *key,
  726.                            unsigned char       *msg,
  727.                            const int            msg_len,
  728.                            unsigned char       *auth_par_ptr,
  729.                            const int            auth_par_len)
  730. {
  731.   if (auth_prot == SNMP_AUTHPROTOCOL_NONE)
  732.     return SNMPv3_USM_UNSUPPORTED_SECURITY_LEVEL;
  733.   Auth *a = get_auth(auth_prot);
  734.   if (!a)
  735.     return SNMPv3_USM_UNSUPPORTED_AUTHPROTOCOL;
  736.   /* @todo check if auth par is inside msg
  737.   if ((auth_par_ptr < msg) ||
  738.       (msg + msg_len < auth_par_ptr + auth_par_len))
  739.   {
  740.     LOG_BEGIN(WARNING_LOG | 1);
  741.     LOG("AuthPriv: Authentication data is not within message (msg start) (len) (auth start) (len)");
  742.     LOG(msg);
  743.     LOG(msg_len);
  744.     LOG(auth_par_ptr);
  745.     LOG(auth_par_len);
  746.     LOG_END;
  747.     return SNMPv3_USM_ERROR;
  748.   }
  749.   */
  750.   return a->auth_inc_msg(key, msg, msg_len, auth_par_ptr, auth_par_len);
  751. }
  752. /* ========================================================== */
  753. /* ----------------------- AuthSHA ---------------------------------------*/
  754. int AuthSHA::password_to_key(const unsigned char *password,
  755.                              const unsigned int   password_len,
  756.                              const unsigned char *engine_id,
  757.                              const unsigned int   engine_id_len,
  758.                              unsigned char *key,
  759.                              unsigned int *key_len)
  760. {
  761.   *key_len = 20; /* All SHA keys have 20 bytes length */
  762. #ifdef __DEBUG
  763.   debugprintf(5,"password_to_key SHA: password: (%s).",
  764.       OctetStr(password, password_len).get_printable());
  765.   debugprintf(5,"password_to_key SHA: engine_id: (%s).",
  766.       OctetStr(engine_id, engine_id_len).get_printable());
  767. #endif
  768.   SHAHashStateType sha_hash_state;
  769.   unsigned char *cp, password_buf[72];
  770.   unsigned long  password_index = 0;
  771.   unsigned long  count = 0, i;
  772.   SHA1_INIT(&sha_hash_state);   /* initialize SHA */
  773.   /**********************************************/
  774.   /* Use while loop until we've done 1 Megabyte */
  775.   /**********************************************/
  776.   while (count < 1048576) {
  777.     cp = password_buf;
  778.     for (i = 0; i < 64; i++) {
  779.       /*************************************************/
  780.       /* Take the next octet of the password, wrapping */
  781.       /* to the beginning of the password as necessary.*/
  782.       /*************************************************/
  783.       *cp++ = password[password_index++ % password_len];
  784.     }
  785.     SHA1_PROCESS(&sha_hash_state, password_buf, 64);
  786.     count += 64;
  787.   }
  788.   SHA1_DONE(&sha_hash_state, key);          /* tell SHA we're done */
  789. #ifdef __DEBUG
  790.   debughexcprintf(21, "key", key, *key_len);
  791. #endif
  792.   /*****************************************************/
  793.   /* Now localize the key with the engine_id and pass  */
  794.   /* through SHA to produce final key                  */
  795.   /* May want to ensure that engine_id_len <= 32,      */
  796.   /* otherwise need to use a buffer larger than 72     */
  797.   /*****************************************************/
  798.   memcpy(password_buf,                            key,       *key_len);
  799.   memcpy(password_buf + *key_len,                 engine_id, engine_id_len);
  800.   memcpy(password_buf + *key_len + engine_id_len, key,       *key_len);
  801.   SHA1_INIT(&sha_hash_state);
  802.   SHA1_PROCESS(&sha_hash_state, password_buf, (2 * *key_len) + engine_id_len);
  803.   SHA1_DONE(&sha_hash_state, key);
  804. #ifdef __DEBUG
  805.   debughexcprintf(21, "localized key", key, *key_len);
  806. #endif
  807.   return SNMPv3_USM_OK;
  808. }
  809. int AuthSHA::hash(const unsigned char *data,
  810.                   const unsigned int   data_len,
  811.                   unsigned char       *digest) const
  812. {
  813.   SHAHashStateType sha_hash_state;
  814.   SHA1_INIT(&sha_hash_state);
  815.   SHA1_PROCESS(&sha_hash_state, data, data_len);
  816.   SHA1_DONE(&sha_hash_state, digest);
  817.   return SNMPv3_USM_OK;
  818. }
  819. int AuthSHA::auth_out_msg(const unsigned char *key,
  820.                           unsigned char *msg,
  821.                           const int msg_len,
  822.                           unsigned char *auth_par_ptr)
  823. {
  824.   SHAHashStateType sha_hash_state;
  825.   int           key_len = 20; /* We use only 20 Byte Key! */
  826.   unsigned char digest[20];
  827.   unsigned char k_ipad[65];   /* inner padding - key XORd with ipad */
  828.   unsigned char k_opad[65];   /* outer padding - key XORd with opad */
  829.   memset((char*)(auth_par_ptr), 0, 12);
  830. #ifdef __DEBUG
  831.   debughexcprintf(21, "key", key, 16);
  832. #endif
  833.   /*
  834.    * the HMAC_SHA transform looks like:
  835.    *
  836.    * SHA(K XOR opad, SHA(K XOR ipad, msg))
  837.    *
  838.    * where K is an n byte key
  839.    * ipad is the byte 0x36 repeated 64 times
  840.    * opad is the byte 0x5c repeated 64 times
  841.    * and text is the data being protected
  842.    */
  843.   /* start out by storing ipads and opads in pads */
  844.   memset( (char*)k_ipad, 0x36, sizeof k_ipad);
  845.   memset( (char*)k_opad, 0x5c, sizeof k_opad);
  846.   /* XOR pads with key */
  847.   for (int i=0; i < key_len; ++i) {
  848.     k_ipad[i] ^= key[i];
  849.     k_opad[i] ^= key[i];
  850.   }
  851.   /* perform inner SHA */
  852.   SHA1_INIT(&sha_hash_state);           /* init sha_hash_state for 1st pass */
  853.   SHA1_PROCESS(&sha_hash_state, k_ipad, 64);   /* start with inner pad      */
  854.   SHA1_PROCESS(&sha_hash_state, msg, msg_len); /* then text of datagram     */
  855.   SHA1_DONE(&sha_hash_state, digest);          /* finish up 1st pass        */
  856.   /* perform outer SHA */
  857.   SHA1_INIT(&sha_hash_state);           /* init sha_hash_state for 2nd pass */
  858.   SHA1_PROCESS(&sha_hash_state, k_opad, 64);   /* start with outer pad      */
  859.   SHA1_PROCESS(&sha_hash_state, digest, 20);   /* then results of 1st hash  */
  860.   SHA1_DONE(&sha_hash_state, digest);          /* finish up 2nd pass        */
  861. #ifdef __DEBUG
  862.   debughexcprintf(21,"digest", digest, 160 / 8);
  863. #endif
  864.   memcpy(auth_par_ptr, digest, 12);
  865.   return SNMPv3_USM_OK;
  866. }
  867. int AuthSHA::auth_inc_msg(const unsigned char *key,
  868.                           unsigned char *msg,
  869.                           const int msg_len,
  870.                           unsigned char *auth_par_ptr,
  871.                           const int      auth_par_len)
  872. {
  873.   unsigned char receivedDigest[20];
  874.   if (auth_par_len != 12)
  875.   {
  876.     debugprintf(4, "SHA illegal digest length (%d), authentication FAILED.",
  877. auth_par_len);
  878.     return SNMPv3_USM_AUTHENTICATION_FAILURE;
  879.   }
  880. #ifdef __DEBUG
  881.   debughexcprintf(21, "digest in Message", auth_par_ptr, 12);
  882.   debughexcprintf(21, "key", key, 20);
  883. #endif
  884.   /* Save received digest */
  885.   memcpy(receivedDigest, auth_par_ptr, 12);
  886.   if (SNMPv3_USM_OK != auth_out_msg(key, msg, msg_len, auth_par_ptr))
  887.   {
  888.     /* copy digest back into message and return error */
  889.     memcpy(auth_par_ptr, receivedDigest, 12);
  890.     debugprintf(4, "SHA authentication FAILED (1).");
  891.     return SNMPv3_USM_AUTHENTICATION_FAILURE;
  892.   }
  893.   /* compare digest to received digest */
  894.   for (int i=0; i < 12 ; ++i)
  895.   {
  896.     if (auth_par_ptr[i] != receivedDigest[i])
  897.     {
  898.       /* copy digest back into message and return error */
  899.       memcpy(auth_par_ptr, receivedDigest, 12);
  900.       debugprintf(4, "SHA authentication FAILED.");
  901.       return SNMPv3_USM_AUTHENTICATION_FAILURE;
  902.     }
  903.   }
  904.   debugprintf(4, "SHA authentication OK.");
  905.   return SNMPv3_USM_OK;
  906. }
  907. /* ----------------------- AuthMD5 ---------------------------------------*/
  908. int AuthMD5::password_to_key(const unsigned char *password,
  909.                              const unsigned int   password_len,
  910.                              const unsigned char *engine_id,
  911.                              const unsigned int   engine_id_len,
  912.                              unsigned char *key,
  913.                              unsigned int *key_len)
  914. {
  915.   *key_len = 16; /* All MD5 keys have 16 bytes length */
  916. #ifdef __DEBUG
  917.   debugprintf(5,"password: %s.",
  918.               OctetStr(password, password_len).get_printable());
  919.   debugprintf(5,"engineID: %s.",
  920.               OctetStr(engine_id, engine_id_len).get_printable());
  921. #endif
  922.   MD5HashStateType md5_hash_state;
  923.   unsigned char  *cp, password_buf[65];
  924.   unsigned long   password_index = 0;
  925.   unsigned long   count = 0, i;
  926.   MD5_INIT(&md5_hash_state);   /* initialize MD5 */
  927.   /**********************************************/
  928.   /* Use while loop until we've done 1 Megabyte */
  929.   /**********************************************/
  930.   while (count < 1048576) {
  931.     cp = password_buf;
  932.     for (i = 0; i < 64; i++) {
  933.       /*************************************************/
  934.       /* Take the next octet of the password, wrapping */
  935.       /* to the beginning of the password as necessary.*/
  936.       /*************************************************/
  937.       *cp++ = password[password_index++ % password_len];
  938.     }
  939.     MD5_PROCESS(&md5_hash_state, password_buf, 64);
  940.     count += 64;
  941.   }
  942.   MD5_DONE(&md5_hash_state, key);      /* tell MD5 we're done */
  943. #ifdef __DEBUG
  944.   debughexcprintf(21, "key", key, *key_len);
  945. #endif
  946.   /*****************************************************/
  947.   /* Now localize the key with the engine_id and pass  */
  948.   /* through MD5 to produce final key                  */
  949.   /* May want to ensure that engine_id_len <= 32,      */
  950.   /* otherwise need to use a buffer larger than 64     */
  951.   /*****************************************************/
  952.   memcpy(password_buf,                            key,       *key_len);
  953.   memcpy(password_buf + *key_len,                 engine_id, engine_id_len);
  954.   memcpy(password_buf + *key_len + engine_id_len, key,       *key_len);
  955.   MD5_INIT(&md5_hash_state);
  956.   MD5_PROCESS(&md5_hash_state, password_buf, (2 * *key_len) + engine_id_len);
  957.   MD5_DONE(&md5_hash_state, key);
  958. #ifdef __DEBUG
  959.   debughexcprintf(21, "localized key", key, *key_len);
  960. #endif
  961.   return SNMPv3_USM_OK;
  962. }
  963. int AuthMD5::hash(const unsigned char *data,
  964.                   const unsigned int   data_len,
  965.                   unsigned char       *digest) const
  966. {
  967.   MD5HashStateType md5_hash_state;
  968.   MD5_INIT(&md5_hash_state);
  969.   MD5_PROCESS(&md5_hash_state, data, data_len);
  970.   MD5_DONE(&md5_hash_state, digest);
  971.   return SNMPv3_USM_OK;
  972. }
  973. int AuthMD5::auth_out_msg(const unsigned char *key,
  974.                           unsigned char *msg,
  975.                           const int      msg_len,
  976.                           unsigned char *auth_par_ptr)
  977. {
  978.   MD5HashStateType md5_hash_state;
  979.   int           key_len = 16; /* We use only 16 Byte Key! */
  980.   unsigned char digest[16];
  981.   unsigned char k_ipad[65];   /* inner padding - key XORd with ipad */
  982.   unsigned char k_opad[65];   /* outer padding - key XORd with opad */
  983.   memset((char*)(auth_par_ptr), 0, 12);
  984. #ifdef __DEBUG
  985.   debughexcprintf(21, "key", key, 16);
  986. #endif
  987.   /*
  988.    * the HMAC_MD5 transform looks like:
  989.    *
  990.    * MD5(K XOR opad, MD5(K XOR ipad, msg))
  991.    *
  992.    * where K is an n byte key
  993.    * ipad is the byte 0x36 repeated 64 times
  994.    * opad is the byte 0x5c repeated 64 times
  995.    * and text is the data being protected
  996.    */
  997.   /* start out by storing key in pads */
  998.   memset( (char*)k_ipad, 0, sizeof k_ipad);
  999.   memset( (char*)k_opad, 0, sizeof k_opad);
  1000.   memcpy( (char*)k_ipad, (char*)key, key_len);
  1001.   memcpy( (char*)k_opad, (char*)key, key_len);
  1002.   /* XOR key with ipad and opad values */
  1003.   for (int i=0; i<64; i++) {
  1004.     k_ipad[i] ^= 0x36;
  1005.     k_opad[i] ^= 0x5c;
  1006.   }
  1007.   /* perform inner MD5 */
  1008.   MD5_INIT(&md5_hash_state);            /* init md5_hash_state for 1st pass */
  1009.   MD5_PROCESS(&md5_hash_state, k_ipad, 64);    /* start with inner pad      */
  1010.   MD5_PROCESS(&md5_hash_state, msg, msg_len);  /* then text of datagram     */
  1011.   MD5_DONE(&md5_hash_state, digest);           /* finish up 1st pass        */
  1012.   /* perform outer MD5 */
  1013.   MD5_INIT(&md5_hash_state);            /* init md5_hash_state for 2nd pass */
  1014.   MD5_PROCESS(&md5_hash_state, k_opad, 64);    /* start with outer pad      */
  1015.   MD5_PROCESS(&md5_hash_state, digest, 16);    /* then results of 1st hash  */
  1016.   MD5_DONE(&md5_hash_state, digest);           /* finish up 2nd pass        */
  1017. #ifdef __DEBUG
  1018.   debughexcprintf(21, "digest", digest, 128 / 8);
  1019. #endif
  1020.   memcpy(auth_par_ptr, digest, 12);
  1021.   return SNMPv3_USM_OK;
  1022. }
  1023. int AuthMD5::auth_inc_msg(const unsigned char *key,
  1024.                           unsigned char *msg,
  1025.                           const int msg_len,
  1026.                           unsigned char *auth_par_ptr,
  1027.                           const int      auth_par_len)
  1028. {
  1029.   unsigned char receivedDigest[16];
  1030.   if (auth_par_len != 12)
  1031.   {
  1032.     debugprintf(4, "MD5 illegal digest length (%d), authentication FAILED.",
  1033. auth_par_len);
  1034.     return SNMPv3_USM_AUTHENTICATION_FAILURE;
  1035.   }
  1036. #ifdef __DEBUG
  1037.   debughexcprintf(21, "digest in Message", auth_par_ptr, 12);
  1038.   debughexcprintf(21, "key", key, 16);
  1039. #endif
  1040.   memcpy(receivedDigest, auth_par_ptr, 12);
  1041.   if (SNMPv3_USM_OK != auth_out_msg(key, msg, msg_len, auth_par_ptr))
  1042.   {
  1043.     /* copy digest back into message and return error */
  1044.     memcpy(auth_par_ptr, receivedDigest, 12);
  1045.     debugprintf(4, "MD5 authentication FAILED (1).");
  1046.     return SNMPv3_USM_AUTHENTICATION_FAILURE;
  1047.   }
  1048.   /* compare digest to received digest */
  1049.   for (int i=0; i < 12 ; ++i)
  1050.   {
  1051.     if (auth_par_ptr[i] != receivedDigest[i])
  1052.     {
  1053.       /* copy digest back into message and return error */
  1054.       memcpy(auth_par_ptr, receivedDigest, 12);
  1055.       debugprintf(4, "MD5 authentication FAILED.");
  1056.       return SNMPv3_USM_AUTHENTICATION_FAILURE;
  1057.     }
  1058.   }
  1059.   debugprintf(4, "MD5 authentication OK.");
  1060.   return SNMPv3_USM_OK;
  1061. }
  1062. /* ========================= PRIV ================================*/
  1063. /* ----------------------- PrivDES ---------------------------------------*/
  1064. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  1065. PrivDES::PrivDES()
  1066. {
  1067.   cipher = find_cipher("des");
  1068. }
  1069. #endif
  1070. int PrivDES::encrypt(const unsigned char *key,
  1071.                      const unsigned int   /*key_len*/,
  1072.                      const unsigned char *buffer,
  1073.                      const unsigned int   buffer_len,
  1074.                      unsigned char       *out_buffer,
  1075.                      unsigned int        *out_buffer_len,
  1076.                      unsigned char       *privacy_params,
  1077.                      unsigned int        *privacy_params_len,
  1078.                      const unsigned long  engine_boots,
  1079.                      const unsigned long  /*engine_time*/)
  1080. {
  1081.   unsigned char initVect[8];
  1082.   pp_uint64     my_salt = (*salt)++;
  1083. #ifdef INVALID_ENCRYPTION
  1084.   debugprintf(-10, "nWARNING: Encrypting with zeroed salt!n");
  1085.   my_salt = 0;
  1086. #endif
  1087.   /* check space in privacy_params buffer */
  1088.   if (*privacy_params_len < 8)
  1089.   {
  1090.     debugprintf(4, "Buffer too small: should be 8, is (%i).",
  1091.                 *privacy_params_len);
  1092.     return SNMPv3_USM_ENCRYPTION_ERROR;
  1093.   }
  1094.   /* Length is always 8 */
  1095.   *privacy_params_len = 8;
  1096.   // last 8 bytes of key are used as base for initialization vector
  1097.   memcpy((char*)initVect, key+8, 8);
  1098.   // put salt in privacy_params
  1099.   for (int j=0; j<4; j++)
  1100.   {
  1101.     privacy_params[3-j] = (unsigned char) (0xFF & (engine_boots >> (8*j)));
  1102.     privacy_params[7-j] = (unsigned char) (0xFF & (my_salt >> (8*j)));
  1103.   }
  1104.   // xor initVect with salt
  1105.   for (int i=0; i<8; i++)
  1106.     initVect[i] ^= privacy_params[i];
  1107. #ifdef __DEBUG
  1108.   debughexcprintf(21, "apDESEncryptData: Data to encrypt",
  1109.                  buffer, buffer_len);
  1110.   debughexcprintf(21, "apDESEncryptData: used key (only 8 bytes used)",
  1111.                   key, 16);
  1112.   debughexcprintf(21, "apDESEncryptData: used iv",
  1113.                   initVect, 8);
  1114. #endif
  1115.   DESCBCType symcbc;
  1116.   DES_CBC_START_ENCRYPT(cipher, initVect, key, 8, 16, symcbc);
  1117.   for(unsigned int k = 0; k <= buffer_len - 8; k += 8) {
  1118.     DES_CBC_ENCRYPT(buffer + k, out_buffer + k, symcbc, initVect, 8);
  1119.   }
  1120.   /* last part of buffer */
  1121.   if (buffer_len % 8)
  1122.   {
  1123.     unsigned char tmp_buf[8];
  1124.     unsigned char *tmp_buf_ptr = tmp_buf;
  1125.     int start = buffer_len - (buffer_len % 8);
  1126.     memset(tmp_buf, 0, 8);
  1127.     for (unsigned int l = start; l < buffer_len; l++)
  1128.       *tmp_buf_ptr++ = buffer[l];
  1129.     DES_CBC_ENCRYPT(tmp_buf, out_buffer + start, symcbc, initVect, 8);
  1130.     *out_buffer_len = buffer_len + 8 - (buffer_len % 8);
  1131.   }
  1132.   else
  1133.     *out_buffer_len = buffer_len;
  1134.   /* Clear context buffer (paranoia!)*/
  1135.   DES_MEMSET(symcbc, 0, sizeof(symcbc));
  1136. #ifdef __DEBUG
  1137.   debughexcprintf(21, "apDESEncryptData: created privacy_params",
  1138.                   privacy_params, 8);
  1139.   debughexcprintf(21, "apDESEncryptData: encrypted Data",
  1140.                   out_buffer, *out_buffer_len);
  1141. #endif
  1142.   return SNMPv3_USM_OK;
  1143. }
  1144. int PrivDES::decrypt(const unsigned char *key,
  1145.                      const unsigned int   /*key_len*/,
  1146.                      const unsigned char *buffer,
  1147.                      const unsigned int   buffer_len,
  1148.                      unsigned char *outBuffer,
  1149.                      unsigned int  *outBuffer_len,
  1150.                      const unsigned char *privacy_params,
  1151.                      const unsigned int   privacy_params_len,
  1152.      const unsigned long  /*engine_boots*/,
  1153.      const unsigned long  /*engine_time*/)
  1154. {
  1155.   unsigned char initVect[8];
  1156.   /* Privacy params length has to be 8  && Length has to be a multiple of 8 */
  1157.   if (( buffer_len % 8 ) || (privacy_params_len != 8))
  1158.     return SNMPv3_USM_DECRYPTION_ERROR;
  1159.   for (int i=0; i<8; i++)
  1160.     initVect[i] = privacy_params[i] ^ key[i+8];
  1161.   memset((char*)outBuffer, 0, *outBuffer_len);
  1162. #ifdef __DEBUG
  1163.   debughexcprintf(21, "apDESDecryptData: Data to decrypt",
  1164.                   buffer, buffer_len);
  1165.   debughexcprintf(21, "apDESDecryptData: used key (only 8 bytes used)",
  1166.                   key, 16);
  1167.   debughexcprintf(21, "apDESDecryptData: used privacy_params",
  1168.                   privacy_params, 8);
  1169.   debughexcprintf(21, "apDESDecryptData: used iv",
  1170.                   initVect, 8);
  1171. #endif
  1172.   DESCBCType symcbc;
  1173.   DES_CBC_START_DECRYPT(cipher, initVect, key, 8, 16, symcbc);
  1174.   for(unsigned int j=0; j<buffer_len; j+=8 ) {
  1175.     DES_CBC_DECRYPT(buffer + j, outBuffer + j, symcbc, initVect, 8);
  1176.   }
  1177.   /* Clear context (paranoia!) */
  1178.   DES_MEMSET(symcbc, 0, sizeof(symcbc));
  1179.   *outBuffer_len = buffer_len;
  1180. #ifdef __DEBUG
  1181.   debughexcprintf(21, "apDESDecryptData: decrypted Data",
  1182.                   outBuffer, *outBuffer_len);
  1183. #endif
  1184.   return SNMPv3_USM_OK;
  1185. }
  1186. /* ----------------------- PrivIDEA --------------------------------------*/
  1187. #ifdef _USE_IDEA
  1188. int PrivIDEA::encrypt(const unsigned char *key,
  1189.                       const unsigned int   /*key_len*/,
  1190.                       const unsigned char *buffer,
  1191.                       const unsigned int   buffer_len,
  1192.                       unsigned char       *out_buffer,
  1193.                       unsigned int        *out_buffer_len,
  1194.                       unsigned char       *privacy_params,
  1195.                       unsigned int        *privacy_params_len,
  1196.                       const unsigned long  engine_boots,
  1197.                       const unsigned long  /*engine_time*/)
  1198. {
  1199.   IDEAContext CFB_Context;
  1200.   pp_uint64 my_salt = (*salt)++;
  1201. #ifdef INVALID_ENCRYPTION
  1202.   debugprintf(-10, "nWARNING: Encrypting with zeroed salt!n");
  1203.   my_salt = 0;
  1204. #endif
  1205.   /* check space in privacy_params buffer */
  1206.   if (*privacy_params_len < 8)
  1207.   {
  1208.     debugprintf(4, "Buffer too small: should be 8, is (%i).", *privacy_params_len);
  1209.     return SNMPv3_USM_ENCRYPTION_ERROR;
  1210.   }
  1211.   /* Length is always 8 */
  1212.   *privacy_params_len = 8;
  1213.   // last 8 bytes of key are used as base for initialization vector
  1214.   unsigned char iv[8];
  1215.   memcpy((char*)iv, key+8, 8);
  1216.   // put salt in privacy_params
  1217.   for (int j=0; j<4; j++)
  1218.   {
  1219.     privacy_params[3-j] = (unsigned char) (0xFF & (engine_boots >> (8*j)));
  1220.     privacy_params[7-j] = (unsigned char) (0xFF & (my_salt >> (8*j)));
  1221.   }
  1222.   // xor iv with privacy_params
  1223.   for (int i=0; i<8; i++)
  1224.     iv[i] ^= privacy_params[i];
  1225.   idea_set_key(&CFB_Context, key);
  1226.   idea_cfb_encrypt(&CFB_Context, iv, out_buffer,
  1227.                    buffer, buffer_len);
  1228.   /* Clear context (paranoia!) */
  1229.   idea_destroy_context(&CFB_Context);
  1230.   *out_buffer_len = buffer_len;
  1231. #ifdef __DEBUG
  1232.   debughexcprintf(21, "apIDEAEncryptData: Data to encrypt",
  1233.                   buffer, buffer_len);
  1234.   debughexcprintf(21, "apIDEAEncryptData: key",
  1235.                   key, 16);
  1236.   debughexcprintf(21, "apIDEAEncryptData: privacy_params",
  1237.                   privacy_params, 8);
  1238.   debughexcprintf(21, "apIDEAEncryptData: encrypted Data",
  1239.                   out_buffer, *out_buffer_len);
  1240. #endif
  1241.   return SNMPv3_USM_OK;
  1242. }
  1243. int PrivIDEA::decrypt(const unsigned char *key,
  1244.                       const unsigned int   /*key_len*/,
  1245.                       const unsigned char *buffer,
  1246.                       const unsigned int   buffer_len,
  1247.                       unsigned char *out_buffer,
  1248.                       unsigned int  *out_buffer_len,
  1249.                       const unsigned char *privacy_params,
  1250.                       const unsigned int   privacy_params_len,
  1251.       const unsigned long  /*engine_boots*/,
  1252.       const unsigned long  /*engine_time*/)
  1253. {
  1254.   unsigned char iv[8];
  1255.   IDEAContext CFB_Context;
  1256.   /* privacy params length has to be 8 */
  1257.   if (privacy_params_len != 8)
  1258.     return SNMPv3_USM_DECRYPTION_ERROR;
  1259.   idea_set_key(&CFB_Context, key);
  1260.   memset((char*)out_buffer, 0, *out_buffer_len);
  1261.   /* Initialize iv with last 8 bytes of key and xor with privacy_params */
  1262.   memcpy((char*)iv, key+8, 8);
  1263.   for (int i=0; i<8; i++)
  1264.     iv[i] ^= privacy_params[i];
  1265.   idea_cfb_decrypt(&CFB_Context, iv, out_buffer,
  1266.                    buffer, buffer_len);
  1267.   /* Clear context (paranoia!) */
  1268.   idea_destroy_context(&CFB_Context);
  1269.   memset((char*)iv, 0, 8);
  1270.   *out_buffer_len = buffer_len;
  1271. #ifdef __DEBUG
  1272.   debughexcprintf(21, "apIDEADecryptData: Data to decrypt",
  1273.                   buffer, buffer_len);
  1274.   debughexcprintf(21, "apIDEADecryptData: key", key, 16);
  1275.   debughexcprintf(21, "apIDEAEncryptData: privacy_params", privacy_params, 8);
  1276.   debughexcprintf(21, "apIDEADecryptData: decrypted Data",
  1277.                   out_buffer, *out_buffer_len);
  1278. #endif
  1279.   return SNMPv3_USM_OK;
  1280. }
  1281. #endif // _USE_IDEA
  1282. #if defined(_USE_LIBTOMCRYPT) || defined(_USE_OPENSSL)
  1283. PrivAES::PrivAES(const int aes_type_)
  1284.   : aes_type(aes_type_)
  1285. {
  1286. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  1287.   cipher = find_cipher("rijndael");
  1288. #endif
  1289.   switch (aes_type)
  1290.   {
  1291.     case SNMP_PRIVPROTOCOL_AES128:
  1292.       key_bytes = 16;
  1293.       rounds = 10;
  1294.       break;
  1295.     case SNMP_PRIVPROTOCOL_AES192:
  1296.       key_bytes = 24;
  1297.       rounds = 12;
  1298.       break;
  1299.     case SNMP_PRIVPROTOCOL_AES256:
  1300.       key_bytes = 32;
  1301.       rounds = 14;
  1302.       break;
  1303.     default:
  1304.       debugprintf(0, "Wrong AES type: %i.", aes_type);
  1305.       key_bytes = 0;
  1306.       rounds = 0;
  1307.       aes_type = -1; // will cause an error in AuthPriv::add_priv()
  1308.   }
  1309.   unsigned int testswap = htonl(0x01020304);
  1310.   if (testswap == 0x01020304)
  1311.     need_byteswap = FALSE;
  1312.   else
  1313.     need_byteswap = TRUE;
  1314. }
  1315. const char *PrivAES::get_id_string() const
  1316. {
  1317.   switch (aes_type)
  1318.   {
  1319.     case SNMP_PRIVPROTOCOL_AES128: return "AES128";  break;
  1320.     case SNMP_PRIVPROTOCOL_AES192: return "AES192";  break;
  1321.     case SNMP_PRIVPROTOCOL_AES256: return "AES256";  break;
  1322.     default:                       return "error";   break;
  1323.   }
  1324. };
  1325. int PrivAES::encrypt(const unsigned char *key,
  1326.      const unsigned int   key_len,
  1327.      const unsigned char *buffer,
  1328.      const unsigned int   buffer_len,
  1329.      unsigned char       *out_buffer,
  1330.      unsigned int        *out_buffer_len,
  1331.      unsigned char       *privacy_params,
  1332.      unsigned int        *privacy_params_len,
  1333.      const unsigned long  engine_boots,
  1334.      const unsigned long  engine_time)
  1335. {
  1336.   unsigned char initVect[16];
  1337.   pp_uint64 my_salt = (*salt)++;
  1338. #ifdef INVALID_ENCRYPTION
  1339.   debugprintf(-10, "nWARNING: Encrypting with zeroed salt!n");
  1340.   my_salt = 0;
  1341. #endif
  1342.   /* check space in privacy_params buffer */
  1343.   if (*privacy_params_len < 8)
  1344.   {
  1345.     debugprintf(4, "Buffer too small: should be 8, is (%i).",
  1346.                 *privacy_params_len);
  1347.     return SNMPv3_USM_ENCRYPTION_ERROR;
  1348.   }
  1349.   /* Length is always 8 */
  1350.   *privacy_params_len = 8;
  1351.   /* Set IV as engine_boots + engine_time + salt */
  1352.   unsigned int *tmpi = (unsigned int *)initVect;
  1353.   *tmpi++ = htonl(engine_boots);
  1354.   *tmpi++ = htonl(engine_time);
  1355.   if (need_byteswap)
  1356.   {
  1357.     *tmpi++ = htonl(my_salt & 0xFFFFFFFF);
  1358.     *tmpi   = htonl((my_salt >> 32) & 0xFFFFFFFF);
  1359.   }
  1360.   else
  1361.     memcpy(tmpi, &my_salt, 8);
  1362.   /* put byteswapped salt in privacy_params */
  1363.   memcpy(privacy_params, initVect + 8, 8);
  1364.   debughexcprintf(21, "aes initVect:", initVect, 16);
  1365. #ifdef _USE_OPENSSL
  1366.   AES_KEY symcfb;
  1367.   int dummy = 0;
  1368.   if (AES_set_encrypt_key(key, key_len * 8, &symcfb) < 0)
  1369.   {
  1370.     
  1371.     debugprintf(1, "AES_set_encrypt_key(%p, %d, %p) failed.",
  1372. key, key_len * 8, &symcfb);
  1373.     return SNMPv3_USM_ERROR;
  1374.   }
  1375.   AES_cfb128_encrypt(buffer, out_buffer, buffer_len,
  1376.      &symcfb, initVect, &dummy, AES_ENCRYPT);
  1377. #else
  1378.   symmetric_CFB symcfb;
  1379.   cfb_start(cipher, initVect, key, key_bytes, rounds, &symcfb);
  1380.   cfb_encrypt((unsigned char*)buffer, out_buffer, buffer_len, &symcfb);
  1381. #endif
  1382.   /* Clear context and plaintext buffer (paranoia!)*/
  1383.   memset(&symcfb, 0, sizeof(symcfb));
  1384.   *out_buffer_len = buffer_len;
  1385. #ifdef __DEBUG
  1386.   debughexcprintf(21, "aes EncryptData: Data to encrypt", buffer, buffer_len);
  1387.   debughexcprintf(21, "aes EncryptData: used key", key, key_len);
  1388.   debughexcprintf(21, "aes EncryptData: created privacy_params",
  1389.                   privacy_params, 8);
  1390.   debughexcprintf(21, "aes EncryptData: encrypted Data",
  1391.                   out_buffer, *out_buffer_len);
  1392. #endif
  1393.   return SNMPv3_USM_OK;
  1394. }
  1395. int PrivAES::decrypt(const unsigned char *key,
  1396.      const unsigned int   key_len,
  1397.      const unsigned char *buffer,
  1398.      const unsigned int   buffer_len,
  1399.      unsigned char       *out_buffer,
  1400.      unsigned int        *out_buffer_len,
  1401.      const unsigned char *privacy_params,
  1402.      const unsigned int   privacy_params_len,
  1403.      const unsigned long  engine_boots,
  1404.      const unsigned long  engine_time)
  1405. {
  1406.   unsigned char initVect[16];
  1407.   /* Privacy params length has to be 8 */
  1408.   if (privacy_params_len != 8)
  1409.     return SNMPv3_USM_DECRYPTION_ERROR;
  1410.   /* build IV */
  1411.   unsigned int *tmp;
  1412.   tmp = (unsigned int *)initVect;
  1413.   *tmp++ = htonl(engine_boots);
  1414.   *tmp = htonl(engine_time);
  1415.   memcpy(initVect + 8, privacy_params, 8);
  1416.   debughexcprintf(21, "aes initVect:", initVect, 16);
  1417. #ifdef _USE_OPENSSL
  1418.   int dummy = 0;
  1419.   AES_KEY symcfb;
  1420.   AES_set_encrypt_key(key, key_len * 8, &symcfb);
  1421.   AES_cfb128_encrypt(buffer, out_buffer, buffer_len,
  1422.      &symcfb, initVect, &dummy, AES_DECRYPT);
  1423. #else
  1424.   symmetric_CFB symcfb;
  1425.   cfb_start(cipher, initVect, key, key_bytes, rounds, &symcfb);
  1426.   cfb_decrypt((unsigned char*)buffer, out_buffer, buffer_len, &symcfb);
  1427. #endif
  1428.   /* Clear context and plaintext buffer (paranoia!)*/
  1429.   memset(&symcfb, 0, sizeof(symcfb));
  1430.   *out_buffer_len = buffer_len;
  1431. #ifdef __DEBUG
  1432.   debughexcprintf(21, "aes DecryptData: Data to decrypt", buffer, buffer_len);
  1433.   debughexcprintf(21, "aes DecryptData: used key", key, key_len);
  1434.   debughexcprintf(21, "aes DecryptData: used privacy_params",
  1435.                   privacy_params, 8);
  1436.   debughexcprintf(21, "aes DecryptData: decrypted Data",
  1437.                   out_buffer, *out_buffer_len);
  1438. #endif
  1439.   return SNMPv3_USM_OK;
  1440. }
  1441. int PrivAES::extend_short_key(const unsigned char *password,
  1442.                               const unsigned int   password_len,
  1443.                               const unsigned char *engine_id,
  1444.                               const unsigned int   engine_id_len,
  1445.                               unsigned char       *key,
  1446.                               unsigned int        *key_len,
  1447.                               const unsigned int   max_key_len,
  1448.                               Auth                *auth)
  1449. {
  1450.   if (max_key_len < (unsigned)key_bytes)
  1451.       return SNMPv3_USM_ERROR;
  1452.   int res = 0;
  1453.   unsigned char *hash_buf = new unsigned char[auth->get_hash_len()];
  1454.   if (!hash_buf)
  1455.   {
  1456.     debugprintf(0, "Out of mem. Did not get %i bytes.", auth->get_hash_len());
  1457.     return SNMPv3_USM_ERROR;
  1458.   }
  1459.   while (*key_len < (unsigned)key_bytes)
  1460.   {
  1461.     res = auth->hash(key, *key_len, hash_buf);
  1462.     if (res != SNMPv3_USM_OK)
  1463.       break;
  1464.     int copy_bytes = key_bytes - *key_len;
  1465.     if (copy_bytes > auth->get_hash_len())
  1466.       copy_bytes = auth->get_hash_len();
  1467.     if (*key_len + copy_bytes > max_key_len)
  1468. copy_bytes = max_key_len - *key_len;
  1469.     memcpy(key + *key_len, hash_buf, copy_bytes);
  1470.     *key_len += copy_bytes;
  1471.   }
  1472.   if (hash_buf) delete [] hash_buf;
  1473.   return res;
  1474. }
  1475. #endif // _USE_LIBTOMCRYPT or _USE_OPENSSL
  1476. #ifdef _USE_3DES_EDE
  1477. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  1478. Priv3DES_EDE::Priv3DES_EDE()
  1479. {
  1480.   cipher = find_cipher("3des");
  1481.   debugprintf(10, "tomcrypt returned cipher %d", cipher);
  1482. }
  1483. #endif
  1484. int 
  1485. Priv3DES_EDE::encrypt(const unsigned char *key,
  1486.       const unsigned int   key_len,
  1487.       const unsigned char *buffer,
  1488.       const unsigned int   buffer_len,
  1489.       unsigned char       *out_buffer,
  1490.       unsigned int        *out_buffer_len,
  1491.       unsigned char       *privacy_params,
  1492.       unsigned int        *privacy_params_len,
  1493.       const unsigned long  engine_boots,
  1494.       const unsigned long  engine_time)
  1495. {
  1496.   unsigned char initVect[8];
  1497.   pp_uint64     my_salt = (*salt)++;
  1498.   
  1499. #ifdef INVALID_ENCRYPTION
  1500.   debugprintf(-10, "nWARNING: Encrypting with zeroed salt!n");
  1501.   my_salt = 0;
  1502. #endif
  1503.   /* check space in privacy_params buffer */
  1504.   if (*privacy_params_len < 8)
  1505.   {
  1506.     debugprintf(4, "Buffer too small: should be 8, is (%i).",
  1507.                 *privacy_params_len);
  1508.     return SNMPv3_USM_ENCRYPTION_ERROR;
  1509.   }
  1510.   /* Length is always 8 */
  1511.   *privacy_params_len = 8;
  1512.   /* check key length */
  1513.   if (key_len < TRIPLEDES_EDE_KEY_LEN)
  1514.   {
  1515.     debugprintf(4, "Key too small: should be %d, is (%d).",
  1516.                 TRIPLEDES_EDE_KEY_LEN, key_len);
  1517.     return SNMPv3_USM_ENCRYPTION_ERROR;
  1518.   }
  1519.   /* TODO: check if K1 != K2 != K3 */
  1520.   // last 8 bytes of key are used as base for initialization vector
  1521.   memcpy((char*)initVect, key+24, 8);
  1522.   /* TODO: generate salt as specified in draft */
  1523.   // put salt in privacy_params
  1524.   for (int j=0; j<4; j++)
  1525.   {
  1526.     privacy_params[3-j] = (unsigned char) (0xFF & (engine_boots >> (8*j)));
  1527.     privacy_params[7-j] = (unsigned char) (0xFF & (my_salt >> (8*j)));
  1528.   }
  1529.   // xor initVect with salt
  1530.   for (int i=0; i<8; i++)
  1531.     initVect[i] ^= privacy_params[i];
  1532. #ifdef __DEBUG
  1533.   debughexcprintf(21, "3DES Data to encrypt", buffer, buffer_len);
  1534.   debughexcprintf(21, "3DES used iv", initVect, 8);
  1535.   debughexcprintf(21, "3DES key", key, key_len);
  1536. #endif
  1537.   // The first 24 octets of the 32-octet secret are used as a 3DES-EDE
  1538.   // key. Since 3DES-EDE uses only 168 bits the least significant bit
  1539.   // in each octet is disregarded
  1540. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  1541.   DESCBCType symcbc;
  1542.   DES_CBC_START_ENCRYPT(cipher, initVect, key, 24, 16, symcbc);
  1543.   for(unsigned int k = 0; k <= buffer_len - 8; k += 8) {
  1544.     DES_CBC_ENCRYPT(buffer + k, out_buffer + k, symcbc, initVect, 8);
  1545.   }
  1546.   /* last part of buffer */
  1547.   if (buffer_len % 8)
  1548.   {
  1549.     unsigned char tmp_buf[8];
  1550.     unsigned char *tmp_buf_ptr = tmp_buf;
  1551.     int start = buffer_len - (buffer_len % 8);
  1552.     memset(tmp_buf, 0, 8);
  1553.     for (unsigned int l = start; l < buffer_len; l++)
  1554.       *tmp_buf_ptr++ = buffer[l];
  1555.     DES_CBC_ENCRYPT(tmp_buf, out_buffer + start, symcbc, initVect, 8);
  1556.     *out_buffer_len = buffer_len + 8 - (buffer_len % 8);
  1557.   }
  1558.   else
  1559.     *out_buffer_len = buffer_len;
  1560.   /* Clear context buffer (paranoia!)*/
  1561.   DES_MEMSET(symcbc, 0, sizeof(symcbc));
  1562. #else
  1563.   DESCBCType ks1, ks2, ks3;
  1564.   if ((des_key_sched((C_Block*)(key),     ks1) < 0) ||
  1565.       (des_key_sched((C_Block*)(key +8),  ks2) < 0) ||
  1566.       (des_key_sched((C_Block*)(key +16), ks3) < 0))
  1567.   {
  1568.       debugprintf(0, "Starting 3DES-EDE encryption failed.");
  1569.       return SNMPv3_USM_ERROR;
  1570.   }
  1571.   if (buffer_len >= 8)
  1572.     for(unsigned int k = 0; k <= (buffer_len - 8); k += 8) 
  1573.     {
  1574.       DES_EDE3_CBC_ENCRYPT(buffer+k, out_buffer+k, 8,
  1575.    ks1, ks2, ks3, initVect);
  1576.     }
  1577.   // Last part
  1578.   if (buffer_len % 8)
  1579.     {
  1580.       unsigned char tmp_buf[8];
  1581.       unsigned char *tmp_buf_ptr = tmp_buf;
  1582.       int start = buffer_len - (buffer_len % 8);
  1583.       memset(tmp_buf, 0, 8);
  1584.       for (unsigned int l = start; l < buffer_len; l++)
  1585. *tmp_buf_ptr++ = buffer[l];
  1586.       DES_EDE3_CBC_ENCRYPT(tmp_buf, out_buffer + start, 8,
  1587.    ks1, ks2, ks3, initVect);
  1588.       
  1589.       *out_buffer_len = buffer_len + 8 - (buffer_len % 8);
  1590.     }
  1591.   else
  1592.     *out_buffer_len = buffer_len;
  1593.   /* Clear context buffer (paranoia!)*/
  1594.   DES_MEMSET(ks1, 0, sizeof(ks1));
  1595.   DES_MEMSET(ks2, 0, sizeof(ks2));
  1596.   DES_MEMSET(ks3, 0, sizeof(ks3));
  1597. #endif
  1598. #ifdef __DEBUG
  1599.   debughexcprintf(21, "3DES created privacy_params", privacy_params, 8);
  1600.   debughexcprintf(21, "3DES encrypted Data", out_buffer, *out_buffer_len);
  1601. #endif
  1602.   return SNMPv3_USM_OK;
  1603. }
  1604. int 
  1605. Priv3DES_EDE::decrypt(const unsigned char *key,
  1606.       const unsigned int   key_len,
  1607.       const unsigned char *buffer,
  1608.       const unsigned int   buffer_len,
  1609.       unsigned char       *out_buffer,
  1610.       unsigned int        *out_buffer_len,
  1611.       const unsigned char *privacy_params,
  1612.       const unsigned int   privacy_params_len,
  1613.       const unsigned long  engine_boots,
  1614.       const unsigned long  engine_time)
  1615. {
  1616.   unsigned char initVect[8];
  1617.   /* Privacy params length has to be 8  && Length has to be a multiple of 8 */
  1618.   if (( buffer_len % 8 ) || (privacy_params_len != 8))
  1619.     return SNMPv3_USM_DECRYPTION_ERROR;
  1620.   for (int i=0; i<8; i++)
  1621.     initVect[i] = privacy_params[i] ^ key[i+24];
  1622.   memset((char*)out_buffer, 0, *out_buffer_len);
  1623. #ifdef __DEBUG
  1624.   debughexcprintf(21, "3DES Data to decrypt", buffer, buffer_len);
  1625.   debughexcprintf(21, "3DES privacy_params",  privacy_params, 8);
  1626.   debughexcprintf(21, "3DES used iv",   initVect, 8);
  1627.   debughexcprintf(21, "3DES key", key, key_len);
  1628. #endif
  1629. #if defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
  1630.   DESCBCType symcbc;
  1631.   DES_CBC_START_DECRYPT(cipher, initVect, key, 24, 16, symcbc);
  1632.   for(unsigned int j=0; j<buffer_len; j+=8 ) {
  1633.     DES_CBC_DECRYPT(buffer + j, out_buffer + j, symcbc, initVect, 8);
  1634.   }
  1635.   /* Clear context (paranoia!) */
  1636.   DES_MEMSET(symcbc, 0, sizeof(symcbc));
  1637. #else
  1638.   DESCBCType ks1, ks2, ks3;
  1639.   if ((des_key_sched((C_Block*)(key),     ks1) < 0) ||
  1640.       (des_key_sched((C_Block*)(key+8),  ks2) < 0) ||
  1641.       (des_key_sched((C_Block*)(key+16), ks3) < 0))
  1642.     {
  1643.       debugprintf(0, "Starting 3DES-EDE decryption failed.");
  1644.       return SNMPv3_USM_ERROR;
  1645.     }
  1646.   for(unsigned int k=0; k<buffer_len; k+=8 ) 
  1647.     {
  1648.       DES_EDE3_CBC_DECRYPT(buffer+k, out_buffer+k, 8,
  1649.    ks1, ks2, ks3, initVect);
  1650.     }
  1651.   /* Clear context (paranoia!) */
  1652.   DES_MEMSET(ks1, 0, sizeof(ks1));
  1653.   DES_MEMSET(ks2, 0, sizeof(ks2));
  1654.   DES_MEMSET(ks3, 0, sizeof(ks3));
  1655. #endif
  1656.   *out_buffer_len = buffer_len;
  1657. #ifdef __DEBUG
  1658.   debughexcprintf(21, "3DES decrypted Data", out_buffer, *out_buffer_len);
  1659. #endif
  1660.   return SNMPv3_USM_OK;  
  1661. }
  1662. int 
  1663. Priv3DES_EDE::extend_short_key(const unsigned char *password,
  1664.        const unsigned int   password_len,
  1665.        const unsigned char *engine_id,
  1666.        const unsigned int   engine_id_len,
  1667.        unsigned char       *key,
  1668.        unsigned int        *key_len,
  1669.        const unsigned int   max_key_len,
  1670.        Auth                *auth)
  1671. {
  1672.   if (max_key_len < TRIPLEDES_EDE_KEY_LEN)
  1673.     return SNMPv3_USM_ERROR;
  1674.   unsigned int p2k_output_len = *key_len;
  1675.   unsigned char *p2k_buf = new unsigned char[p2k_output_len];
  1676.   int res = 0;
  1677.   if (!p2k_buf) return SNMPv3_USM_ERROR;
  1678.   while (*key_len < TRIPLEDES_EDE_KEY_LEN)
  1679.   {
  1680.     unsigned int p2k_buf_len = p2k_output_len;
  1681.     res = auth->password_to_key(key, *key_len,
  1682. engine_id, engine_id_len,
  1683. p2k_buf, &p2k_buf_len);
  1684.     if (res != SNMPv3_USM_OK)
  1685.       break;
  1686.     unsigned int copy_bytes = TRIPLEDES_EDE_KEY_LEN - *key_len;
  1687.     if (copy_bytes > p2k_buf_len)
  1688. copy_bytes = p2k_buf_len;
  1689.     if (*key_len + copy_bytes > max_key_len)
  1690. copy_bytes = max_key_len - *key_len;
  1691.     memcpy(key + *key_len, p2k_buf, copy_bytes);
  1692.     *key_len += copy_bytes;
  1693.   }
  1694.   if (p2k_buf) delete [] p2k_buf;
  1695.   return res;
  1696. }
  1697. #ifdef _TEST
  1698. bool Priv3DES_EDE::test()
  1699. {
  1700.   int status;
  1701.   AuthPriv ap(status);
  1702.   if (status != SNMPv3_USM_OK)
  1703.       return false;
  1704.   if (ap.add_auth(new AuthSHA()) != SNMP_ERROR_SUCCESS)
  1705.   {
  1706.       debugprintf(0, "Error: could not add AuthSHA.");
  1707.       return false;
  1708.   }
  1709.   if (ap.add_auth(new AuthMD5()) != SNMP_ERROR_SUCCESS)
  1710.   {
  1711.       debugprintf(0, "Error: could not add AuthMD5.");
  1712.       return false;
  1713.   }
  1714.   if (ap.add_priv(new Priv3DES_EDE()) != SNMP_ERROR_SUCCESS)
  1715.   {
  1716.       debugprintf(0, "Error: could not add Priv3DES_EDE.");
  1717.       return false;
  1718.   }
  1719.   unsigned char password[11] = "maplesyrup";
  1720.   unsigned char engine_id[12];
  1721.   memset(engine_id, 0, 11);
  1722.   engine_id[11] = 2;
  1723.   unsigned char key[TRIPLEDES_EDE_KEY_LEN];
  1724.   unsigned int key_len = TRIPLEDES_EDE_KEY_LEN;
  1725.   status = ap.password_to_key_priv(SNMP_AUTHPROTOCOL_HMACSHA,
  1726.                                    SNMP_PRIVPROTOCOL_3DESEDE,
  1727.                                    password, 10,
  1728.                                    engine_id, 12,
  1729.                                    key,  &key_len);
  1730.   debughexcprintf(1, "result key 3DES SHA",
  1731.                   key, key_len);
  1732.   key_len = TRIPLEDES_EDE_KEY_LEN;
  1733.   status = ap.password_to_key_priv(SNMP_AUTHPROTOCOL_HMACMD5,
  1734.                                    SNMP_PRIVPROTOCOL_3DESEDE,
  1735.                                    password, 10,
  1736.                                    engine_id, 12,
  1737.                                    key,  &key_len);
  1738.   debughexcprintf(1, "result key 3DES MD5",
  1739.                   key, key_len);
  1740.   unsigned char msg[80] = "This is the secret message, that has to be encrypted!";
  1741.   unsigned char enc_buffer[80];
  1742.   unsigned int enc_buffer_len = 80;
  1743.   unsigned char dec_buffer[80];
  1744.   unsigned int dec_buffer_len = 80;
  1745.   unsigned char priv_params[64];
  1746.   unsigned int priv_params_len = 64;
  1747.   status = ap.encrypt_msg(SNMP_PRIVPROTOCOL_3DESEDE,
  1748.   key, key_len, msg, 53,
  1749.   enc_buffer, &enc_buffer_len,
  1750.   priv_params, &priv_params_len, 0x5abc, 0x6def);
  1751.   
  1752.   debughexcprintf(1, "encrypted text",
  1753.                   enc_buffer, enc_buffer_len);
  1754.   status = ap.decrypt_msg(SNMP_PRIVPROTOCOL_3DESEDE,
  1755.   key, key_len, enc_buffer, enc_buffer_len,
  1756.   dec_buffer, &dec_buffer_len,
  1757.   priv_params, priv_params_len, 0x5abc, 0x6def);
  1758.   dec_buffer[dec_buffer_len] = 0;
  1759.   debugprintf(1, "decrypted text: %s",
  1760.                   dec_buffer);
  1761.   // TODO: check keys and return real value
  1762.   return true;
  1763. }
  1764. #endif
  1765. #endif // _USE_3DES_EDE
  1766. #ifdef SNMP_PP_NAMESPACE
  1767. }; // end of namespace Snmp_pp
  1768. #endif 
  1769. #endif // _SNMPv3