summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelie <elie>2011-01-16 23:59:08 +0000
committerelie <elie>2011-01-16 23:59:08 +0000
commit9cd30024f0e8638c4905bdd433d19d68e1f91246 (patch)
tree98368e3038cc39da43377097376ef51de9fd3441
parente095034ca1a3355dafb5e5958d1aa69acc140c03 (diff)
downloadpysnmp-9cd30024f0e8638c4905bdd433d19d68e1f91246.tar.gz
extended Security Options (3DESEDE, AES192, AES256) privacy protocols
implemented.
-rw-r--r--CHANGES2
-rw-r--r--examples/v3arch/agent/cmdrsp.py4
-rw-r--r--pysnmp/entity/config.py66
-rw-r--r--pysnmp/entity/rfc3413/oneliner/cmdgen.py3
-rw-r--r--pysnmp/entity/rfc3413/oneliner/ntforg.py3
-rw-r--r--pysnmp/proto/secmod/eso/__init__.py0
-rw-r--r--pysnmp/proto/secmod/eso/priv/__init__.py0
-rw-r--r--pysnmp/proto/secmod/eso/priv/aes192.py27
-rw-r--r--pysnmp/proto/secmod/eso/priv/aes256.py27
-rw-r--r--pysnmp/proto/secmod/eso/priv/des3.py158
-rw-r--r--pysnmp/proto/secmod/rfc3414/auth/base.py7
-rw-r--r--pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py7
-rw-r--r--pysnmp/proto/secmod/rfc3414/auth/hmacsha.py7
-rw-r--r--pysnmp/proto/secmod/rfc3414/auth/noauth.py7
-rw-r--r--pysnmp/proto/secmod/rfc3414/priv/base.py8
-rw-r--r--pysnmp/proto/secmod/rfc3414/priv/des.py26
-rw-r--r--pysnmp/proto/secmod/rfc3414/priv/nopriv.py6
-rw-r--r--pysnmp/proto/secmod/rfc3414/service.py39
-rw-r--r--pysnmp/proto/secmod/rfc3826/priv/aes.py25
-rw-r--r--setup.py2
20 files changed, 364 insertions, 60 deletions
diff --git a/CHANGES b/CHANGES
index ba95b3c..57ac2bd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
Revision 4.1.16a
----------------
+- Extended Security Options (3DESEDE, AES192, AES256) privacy
+ protocols implemented.
- The error-indication codes moved from literals to objects for reliability
and clarity
diff --git a/examples/v3arch/agent/cmdrsp.py b/examples/v3arch/agent/cmdrsp.py
index 51d473a..9e2e9b2 100644
--- a/examples/v3arch/agent/cmdrsp.py
+++ b/examples/v3arch/agent/cmdrsp.py
@@ -41,7 +41,11 @@ config.addV1System(snmpEngine, 'test-agent', 'public')
config.addV3User(
snmpEngine, 'test-user',
config.usmHMACMD5AuthProtocol, 'authkey1',
+# config.usmHMACSHAAuthProtocol, 'authkey1',
config.usmDESPrivProtocol, 'privkey1'
+# config.usm3DESEDEPrivProtocol, 'privkey1'
+# config.usmAesCfb192Protocol, 'privkey1'
+# config.usmAesCfb256Protocol, 'privkey1'
# config.usmAesCfb128Protocol, 'privkey1'
)
diff --git a/pysnmp/entity/config.py b/pysnmp/entity/config.py
index e6fed2b..1ffb04b 100644
--- a/pysnmp/entity/config.py
+++ b/pysnmp/entity/config.py
@@ -9,11 +9,11 @@ try:
except ImportError: # UNIX-specific -- may not be always available
pass
from pysnmp.proto import rfc3412
-from pysnmp.proto.secmod.rfc3414 import localkey
from pysnmp.entity import engine
from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha, noauth
from pysnmp.proto.secmod.rfc3414.priv import des, nopriv
from pysnmp.proto.secmod.rfc3826.priv import aes
+from pysnmp.proto.secmod.eso.priv import des3, aes192, aes256
from pysnmp.smi.error import NotWritableError
from pysnmp import error
@@ -30,9 +30,29 @@ usmNoAuthProtocol = noauth.NoAuth.serviceID
# Privacy protocol
usmDESPrivProtocol = des.Des.serviceID
+usm3DESEDEPrivProtocol = des3.Des3.serviceID
usmAesCfb128Protocol = aes.Aes.serviceID
+usmAesCfb192Protocol = aes192.Aes192.serviceID
+usmAesCfb256Protocol = aes256.Aes256.serviceID
usmNoPrivProtocol = nopriv.NoPriv.serviceID
+# Auth services
+authServices = {
+ hmacmd5.HmacMd5.serviceID: hmacmd5.HmacMd5(),
+ hmacsha.HmacSha.serviceID: hmacsha.HmacSha(),
+ noauth.NoAuth.serviceID: noauth.NoAuth()
+ }
+
+# Privacy services
+privServices = {
+ des.Des.serviceID: des.Des(),
+ des3.Des3.serviceID: des3.Des3(),
+ aes.Aes.serviceID: aes.Aes(),
+ aes192.Aes192.serviceID: aes192.Aes192(),
+ aes256.Aes256.serviceID: aes256.Aes256(),
+ nopriv.NoPriv.serviceID: nopriv.NoPriv()
+ }
+
def __cookV1SystemInfo(snmpEngine, securityName):
snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID')
@@ -117,47 +137,23 @@ def addV3User(snmpEngine, securityName,
)
# Localize keys
- if authProtocol == usmHMACMD5AuthProtocol:
- hashedAuthPassphrase = localkey.hashPassphraseMD5(
+ if authServices.has_key(authProtocol):
+ hashedAuthPassphrase = authServices[authProtocol].hashPassphrase(
authKey and authKey or ''
)
- localAuthKey = localkey.localizeKeyMD5(
+ localAuthKey = authServices[authProtocol].localizeKey(
hashedAuthPassphrase, snmpEngineID
)
- elif authProtocol == usmHMACSHAAuthProtocol:
- hashedAuthPassphrase = localkey.hashPassphraseSHA(
- authKey and authKey or ''
- )
- localAuthKey = localkey.localizeKeySHA(
- hashedAuthPassphrase, snmpEngineID
- )
- elif authProtocol == usmNoAuthProtocol:
- hashedAuthPassphrase = localAuthKey = None
else:
raise error.PySnmpError('Unknown auth protocol %s' % (authProtocol,))
- if privProtocol == usmDESPrivProtocol or \
- privProtocol == usmAesCfb128Protocol:
- if authProtocol == usmHMACMD5AuthProtocol:
- hashedPrivPassphrase = localkey.hashPassphraseMD5(
- privKey and privKey or ''
- )
- localPrivKey = localkey.localizeKeyMD5(
- hashedPrivPassphrase, snmpEngineID
- )
- elif authProtocol == usmHMACSHAAuthProtocol:
- hashedPrivPassphrase = localkey.hashPassphraseSHA(
- privKey and privKey or ''
- )
- localPrivKey = localkey.localizeKeySHA(
- hashedPrivPassphrase, snmpEngineID
- )
- else:
- raise error.PySnmpError(
- 'Unknown auth protocol %s' % (authProtocol,)
- )
- elif privProtocol == usmNoPrivProtocol:
- hashedPrivPassphrase = localPrivKey = None
+ if privServices.has_key(privProtocol):
+ hashedPrivPassphrase = privServices[privProtocol].hashPassphrase(
+ authProtocol, privKey and privKey or ''
+ )
+ localPrivKey = privServices[privProtocol].localizeKey(
+ authProtocol, hashedPrivPassphrase, snmpEngineID
+ )
else:
raise error.PySnmpError(
'Unknown priv protocol %s' % (privProtocol,)
diff --git a/pysnmp/entity/rfc3413/oneliner/cmdgen.py b/pysnmp/entity/rfc3413/oneliner/cmdgen.py
index d49a6e5..1204c67 100644
--- a/pysnmp/entity/rfc3413/oneliner/cmdgen.py
+++ b/pysnmp/entity/rfc3413/oneliner/cmdgen.py
@@ -13,7 +13,10 @@ usmNoAuthProtocol = config.usmNoAuthProtocol
# Privacy protocol
usmDESPrivProtocol = config.usmDESPrivProtocol
+usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol
usmAesCfb128Protocol = config.usmAesCfb128Protocol
+usmAesCfb192Protocol = config.usmAesCfb192Protocol
+usmAesCfb256Protocol = config.usmAesCfb256Protocol
usmNoPrivProtocol = config.usmNoPrivProtocol
nextID = nextid.Integer(0xffffffffL)
diff --git a/pysnmp/entity/rfc3413/oneliner/ntforg.py b/pysnmp/entity/rfc3413/oneliner/ntforg.py
index 45a5a25..3c78b63 100644
--- a/pysnmp/entity/rfc3413/oneliner/ntforg.py
+++ b/pysnmp/entity/rfc3413/oneliner/ntforg.py
@@ -10,7 +10,10 @@ usmNoAuthProtocol = cmdgen.usmNoAuthProtocol
# Privacy protocol
usmDESPrivProtocol = cmdgen.usmDESPrivProtocol
+usm3DESEDEPrivProtocol = cmdgen.usm3DESEDEPrivProtocol
usmAesCfb128Protocol = cmdgen.usmAesCfb128Protocol
+usmAesCfb192Protocol = cmdgen.usmAesCfb192Protocol
+usmAesCfb256Protocol = cmdgen.usmAesCfb256Protocol
usmNoPrivProtocol = cmdgen.usmNoPrivProtocol
# Credentials
diff --git a/pysnmp/proto/secmod/eso/__init__.py b/pysnmp/proto/secmod/eso/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pysnmp/proto/secmod/eso/__init__.py
diff --git a/pysnmp/proto/secmod/eso/priv/__init__.py b/pysnmp/proto/secmod/eso/priv/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pysnmp/proto/secmod/eso/priv/__init__.py
diff --git a/pysnmp/proto/secmod/eso/priv/aes192.py b/pysnmp/proto/secmod/eso/priv/aes192.py
new file mode 100644
index 0000000..abfff5c
--- /dev/null
+++ b/pysnmp/proto/secmod/eso/priv/aes192.py
@@ -0,0 +1,27 @@
+# AES 192/256 bit encryption (Internet draft)
+# http://tools.ietf.org/html/draft-blumenthal-aes-usm-04
+from pysnmp.proto.secmod.rfc3826.priv import aes
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
+
+class Aes192(aes.Aes):
+ serviceID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 1) # cusmAESCfb192PrivProtocol
+ keySize = 24
+
+ # 3.1.2.1
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID)
+ localPrivKey = localPrivKey + localkey.localizeKeyMD5(
+ localPrivKey, snmpEngineID
+ )
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID)
+ localPrivKey = localPrivKey + localkey.localizeKeySHA(
+ localPrivKey, snmpEngineID
+ )
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+ return localPrivKey[:24]
diff --git a/pysnmp/proto/secmod/eso/priv/aes256.py b/pysnmp/proto/secmod/eso/priv/aes256.py
new file mode 100644
index 0000000..874c83a
--- /dev/null
+++ b/pysnmp/proto/secmod/eso/priv/aes256.py
@@ -0,0 +1,27 @@
+# AES 192/256 bit encryption (Internet draft)
+# http://tools.ietf.org/html/draft-blumenthal-aes-usm-04
+from pysnmp.proto.secmod.rfc3826.priv import aes
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
+
+class Aes256(aes.Aes):
+ serviceID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 2) # cusmAESCfb256PrivProtocol
+ keySize = 32
+
+ # 3.1.2.1
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID)
+ localPrivKey = localPrivKey + localkey.localizeKeyMD5(
+ localPrivKey, snmpEngineID
+ )
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID)
+ localPrivKey = localPrivKey + localkey.localizeKeySHA(
+ localPrivKey, snmpEngineID
+ )
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+ return localPrivKey[:32]
diff --git a/pysnmp/proto/secmod/eso/priv/des3.py b/pysnmp/proto/secmod/eso/priv/des3.py
new file mode 100644
index 0000000..5a1a154
--- /dev/null
+++ b/pysnmp/proto/secmod/eso/priv/des3.py
@@ -0,0 +1,158 @@
+# Reeder 3DES-EDE for USM (Internet draft)
+# http://www.snmp.com/eso/draft-reeder-snmpv3-usm-3desede-00.txt
+import random, string
+from pysnmp.proto.secmod.rfc3414.priv import base
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
+from pyasn1.type import univ
+from pysnmp.proto import error
+
+try:
+ from sys import version_info
+except ImportError:
+ version_info = ( 0, 0 ) # a really early version
+
+try:
+ from Crypto.Cipher import DES3
+except ImportError:
+ DES3 = None
+
+random.seed()
+
+# 5.1.1
+
+class Des3(base.AbstractEncryptionService):
+ serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 3) # usm3DESEDEPrivProtocol
+ if version_info < (2, 3):
+ _localInt = long(random.random()*0xffffffffL)
+ else:
+ _localInt = random.randrange(0, 0xffffffffL)
+
+ def hashPassphrase(self, authProtocol, privKey):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ return localkey.hashPassphraseMD5(privKey)
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ return localkey.hashPassphraseSHA(privKey)
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID)
+ localPrivKey = localPrivKey + localkey.localizeKeyMD5(
+ localPrivKey, snmpEngineID
+ )
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID)
+ localPrivKey = localPrivKey + localkey.localizeKeySHA(
+ localPrivKey, snmpEngineID
+ )
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+ return localPrivKey[:32] # key+IV
+
+ # 5.1.1.1
+ def __getEncryptionKey(self, privKey, snmpEngineBoots):
+ # 5.1.1.1.1
+ des3Key = privKey[:24]
+ preIV = privKey[24:32]
+
+ securityEngineBoots = long(snmpEngineBoots)
+
+ salt = [
+ securityEngineBoots>>24&0xff,
+ securityEngineBoots>>16&0xff,
+ securityEngineBoots>>8&0xff,
+ securityEngineBoots&0xff,
+ self._localInt>>24&0xff,
+ self._localInt>>16&0xff,
+ self._localInt>>8&0xff,
+ self._localInt&0xff
+ ]
+ if self._localInt == 0xffffffffL:
+ self._localInt = 0
+ else:
+ self._localInt = self._localInt + 1
+
+ # salt not yet hashed XXX
+
+ return des3Key, \
+ string.join(map(chr, salt), ''), \
+ string.join(map(lambda x,y: chr(x^ord(y)), salt, preIV), '')
+
+ def __getDecryptionKey(self, privKey, salt):
+ return privKey[:24], string.join(
+ map(lambda x,y: chr(ord(x)^ord(y)), salt, privKey[24:32]), ''
+ )
+
+ # 5.1.1.2
+ def encryptData(self, encryptKey, privParameters, dataToEncrypt):
+ if DES3 is None:
+ raise error.StatusInformation(
+ errorIndication=errind.encryptionError
+ )
+
+ snmpEngineBoots, snmpEngineTime, salt = privParameters
+
+ des3Key, salt, iv = self.__getEncryptionKey(
+ str(encryptKey), snmpEngineBoots
+ )
+
+ des3Obj = DES3.new(des3Key, DES3.MODE_CBC, iv)
+
+ privParameters = univ.OctetString(salt)
+
+ plaintext = dataToEncrypt + '\x00' * (8 - len(dataToEncrypt) % 8)
+ cipherblock = iv
+ ciphertext = ''
+ while plaintext:
+ cipherblock = des3Obj.encrypt(
+ string.join(map(lambda x,y: chr(ord(x)^ord(y)), cipherblock, plaintext[:8]), '')
+ )
+ ciphertext = ciphertext + cipherblock
+ plaintext = plaintext[8:]
+
+ return univ.OctetString(ciphertext), privParameters
+
+ # 5.1.1.3
+ def decryptData(self, decryptKey, privParameters, encryptedData):
+ if DES3 is None:
+ raise error.StatusInformation(
+ errorIndication=errind.decryptionError
+ )
+ snmpEngineBoots, snmpEngineTime, salt = privParameters
+
+ if len(salt) != 8:
+ raise error.StatusInformation(
+ errorIndication=errind.decryptionError
+ )
+
+ salt = str(salt)
+
+ des3Key, iv = self.__getDecryptionKey(str(decryptKey), salt)
+
+ if len(encryptedData) % 8 != 0:
+ raise error.StatusInformation(
+ errorIndication=errind.decryptionError
+ )
+
+ des3Obj = DES3.new(des3Key, DES3.MODE_CBC, iv)
+
+ plaintext = ''
+ ciphertext = str(encryptedData)
+ cipherblock = iv
+ while ciphertext:
+ plaintext = plaintext + string.join(map(
+ lambda x,y: chr(ord(x)^ord(y)),
+ cipherblock,
+ des3Obj.decrypt(ciphertext[:8])
+ ), '')
+ cipherblock = ciphertext[:8]
+ ciphertext = ciphertext[8:]
+
+ return plaintext
+
diff --git a/pysnmp/proto/secmod/rfc3414/auth/base.py b/pysnmp/proto/secmod/rfc3414/auth/base.py
index 9b83458..8cefe1b 100644
--- a/pysnmp/proto/secmod/rfc3414/auth/base.py
+++ b/pysnmp/proto/secmod/rfc3414/auth/base.py
@@ -2,6 +2,13 @@ from pysnmp.proto import errind, error
class AbstractAuthenticationService:
serviceID = None
+
+ def hashPassphrase(self, authKey):
+ raise error.ProtocolError(errind.noAuthentication)
+
+ def localizeKey(self, authKey, snmpEngineID):
+ raise error.ProtocolError(errind.noAuthentication)
+
# 7.2.4.1
def authenticateOutgoingMsg(self, authKey, wholeMsg):
raise error.ProtocolError(errind.noAuthentication)
diff --git a/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py b/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py
index da98506..54efbef 100644
--- a/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py
+++ b/pysnmp/proto/secmod/rfc3414/auth/hmacmd5.py
@@ -5,6 +5,7 @@ except ImportError:
md5 = md5.new
import string
from pysnmp.proto.secmod.rfc3414.auth import base
+from pysnmp.proto.secmod.rfc3414 import localkey
from pysnmp.proto import errind, error
_twelveZeros = '\x00'*12
@@ -17,6 +18,12 @@ class HmacMd5(base.AbstractAuthenticationService):
__ipad = [0x36]*64
__opad = [0x5C]*64
+ def hashPassphrase(self, authKey):
+ return localkey.hashPassphraseMD5(authKey)
+
+ def localizeKey(self, authKey, snmpEngineID):
+ return localkey.localizeKeyMD5(authKey, snmpEngineID)
+
# 6.3.1
def authenticateOutgoingMsg(self, authKey, wholeMsg):
# Here we expect calling secmod to indicate where the digest
diff --git a/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py b/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py
index 9b5e5e3..f813109 100644
--- a/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py
+++ b/pysnmp/proto/secmod/rfc3414/auth/hmacsha.py
@@ -5,6 +5,7 @@ except ImportError:
sha1 = sha.new
import string
from pysnmp.proto.secmod.rfc3414.auth import base
+from pysnmp.proto.secmod.rfc3414 import localkey
from pysnmp.proto import errind, error
_twelveZeros = '\x00'*12
@@ -17,6 +18,12 @@ class HmacSha(base.AbstractAuthenticationService):
__ipad = [0x36]*64
__opad = [0x5C]*64
+ def hashPassphrase(self, authKey):
+ return localkey.hashPassphraseSHA(authKey)
+
+ def localizeKey(self, authKey, snmpEngineID):
+ return localkey.localizeKeySHA(authKey, snmpEngineID)
+
# 7.3.1
def authenticateOutgoingMsg(self, authKey, wholeMsg):
# 7.3.1.1
diff --git a/pysnmp/proto/secmod/rfc3414/auth/noauth.py b/pysnmp/proto/secmod/rfc3414/auth/noauth.py
index 59f3dec..e44b515 100644
--- a/pysnmp/proto/secmod/rfc3414/auth/noauth.py
+++ b/pysnmp/proto/secmod/rfc3414/auth/noauth.py
@@ -3,6 +3,13 @@ from pysnmp.proto import errind, error
class NoAuth(base.AbstractAuthenticationService):
serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 1, 1) # usmNoAuthProtocol
+
+ def hashPassphrase(self, authKey):
+ return
+
+ def localizeKey(self, authKey, snmpEngineID):
+ return
+
# 7.2.4.2
def authenticateOutgoingMsg(self, authKey, wholeMsg):
raise error.StatusInformation(errorIndication=errind.noAuthentication)
diff --git a/pysnmp/proto/secmod/rfc3414/priv/base.py b/pysnmp/proto/secmod/rfc3414/priv/base.py
index d981319..8b71ddb 100644
--- a/pysnmp/proto/secmod/rfc3414/priv/base.py
+++ b/pysnmp/proto/secmod/rfc3414/priv/base.py
@@ -2,8 +2,16 @@ from pysnmp.proto import error
class AbstractEncryptionService:
serviceID = None
+
+ def hashPassphrase(self, authProtocol, privKey):
+ raise error.ProtocolError('no encryption')
+
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ raise error.ProtocolError('no encryption')
+
def encryptData(self, encryptKey, privParameters, dataToEncrypt):
raise error.ProtocolError('no encryption')
def decryptData(self, decryptKey, privParameters, encryptedData):
raise error.ProtocolError('no encryption')
+
diff --git a/pysnmp/proto/secmod/rfc3414/priv/des.py b/pysnmp/proto/secmod/rfc3414/priv/des.py
index f59b833..1f9d7ed 100644
--- a/pysnmp/proto/secmod/rfc3414/priv/des.py
+++ b/pysnmp/proto/secmod/rfc3414/priv/des.py
@@ -1,5 +1,7 @@
import random, string
from pysnmp.proto.secmod.rfc3414.priv import base
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
from pyasn1.type import univ
from pysnmp.proto import error
@@ -23,6 +25,28 @@ class Des(base.AbstractEncryptionService):
_localInt = long(random.random()*0xffffffffL)
else:
_localInt = random.randrange(0, 0xffffffffL)
+
+ def hashPassphrase(self, authProtocol, privKey):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ return localkey.hashPassphraseMD5(privKey)
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ return localkey.hashPassphraseSHA(privKey)
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID)
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID)
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+ return localPrivKey[:32] # key+IV
+
# 8.1.1.1
def __getEncryptionKey(self, privKey, snmpEngineBoots):
desKey = privKey[:8]
@@ -53,7 +77,7 @@ class Des(base.AbstractEncryptionService):
return privKey[:8], string.join(
map(lambda x,y: chr(ord(x)^ord(y)), salt, privKey[8:16]), ''
)
-
+
# 8.2.4.1
def encryptData(self, encryptKey, privParameters, dataToEncrypt):
if DES is None:
diff --git a/pysnmp/proto/secmod/rfc3414/priv/nopriv.py b/pysnmp/proto/secmod/rfc3414/priv/nopriv.py
index cce2c4e..f7b6092 100644
--- a/pysnmp/proto/secmod/rfc3414/priv/nopriv.py
+++ b/pysnmp/proto/secmod/rfc3414/priv/nopriv.py
@@ -3,6 +3,12 @@ from pysnmp.proto import errind, error
class NoPriv(base.AbstractEncryptionService):
serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 1) # usmNoPrivProtocol
+ def hashPassphrase(self, authProtocol, privKey):
+ return
+
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ return
+
def encryptData(self, encryptKey, privParameters, dataToEncrypt):
raise error.StatusInformation(errorIndication=errind.noEncryption)
diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py
index b26f167..5b3e134 100644
--- a/pysnmp/proto/secmod/rfc3414/service.py
+++ b/pysnmp/proto/secmod/rfc3414/service.py
@@ -3,7 +3,7 @@ from pysnmp.proto.secmod.base import AbstractSecurityModel
from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha, noauth
from pysnmp.proto.secmod.rfc3414.priv import des, nopriv
from pysnmp.proto.secmod.rfc3826.priv import aes
-from pysnmp.proto.secmod.rfc3414 import localkey
+from pysnmp.proto.secmod.eso.priv import des3, aes192, aes256
from pysnmp.smi.error import NoSuchInstanceError
from pysnmp.proto import rfc1155, errind, error
from pyasn1.type import univ, namedtype, constraint
@@ -30,11 +30,13 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
hmacmd5.HmacMd5.serviceID: hmacmd5.HmacMd5(),
hmacsha.HmacSha.serviceID: hmacsha.HmacSha(),
noauth.NoAuth.serviceID: noauth.NoAuth()
-
}
privServices = {
des.Des.serviceID: des.Des(),
+ des3.Des3.serviceID: des3.Des3(),
aes.Aes.serviceID: aes.Aes(),
+ aes192.Aes192.serviceID: aes192.Aes192(),
+ aes256.Aes256.serviceID: aes256.Aes256(),
nopriv.NoPriv.serviceID: nopriv.NoPriv()
}
_securityParametersSpec = UsmSecurityParameters()
@@ -142,16 +144,12 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
pysnmpUsmKeyAuthLocalized = pysnmpUsmKeyEntry.getNode(
pysnmpUsmKeyEntry.name + (1,) + tblIdx
)
- if usmUserAuthProtocol.syntax == hmacsha.HmacSha.serviceID:
- localAuthKey = localkey.localizeKeySHA(
- pysnmpUsmKeyAuth.syntax, securityEngineID
- )
- elif usmUserAuthProtocol.syntax == hmacmd5.HmacMd5.serviceID:
- localAuthKey = localkey.localizeKeyMD5(
- pysnmpUsmKeyAuth.syntax, securityEngineID
+ if self.authServices.has_key(usmUserAuthProtocol.syntax):
+ localizeKey = self.authServices[usmUserAuthProtocol.syntax].localizeKey
+ localAuthKey = localizeKey(
+ pysnmpUsmKeyAuth.syntax,
+ securityEngineID
)
- elif usmUserAuthProtocol.syntax == noauth.NoAuth.serviceID:
- localAuthKey = None
else:
raise error.StatusInformation(
errorIndication = errind.unsupportedAuthProtocol
@@ -161,18 +159,13 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
pysnmpUsmKeyPrivLocalized = pysnmpUsmKeyEntry.getNode(
pysnmpUsmKeyEntry.name + (2,) + tblIdx
)
- if usmUserPrivProtocol.syntax == des.Des.serviceID or \
- usmUserPrivProtocol.syntax == aes.Aes.serviceID:
- if usmUserAuthProtocol.syntax == hmacsha.HmacSha.serviceID:
- localPrivKey = localkey.localizeKeySHA(
- pysnmpUsmKeyPriv.syntax, securityEngineID
- )
- else:
- localPrivKey = localkey.localizeKeyMD5(
- pysnmpUsmKeyPriv.syntax, securityEngineID
- )
- elif usmUserPrivProtocol.syntax == nopriv.NoPriv.serviceID:
- localPrivKey = None
+ if self.privServices.has_key(usmUserPrivProtocol.syntax):
+ localizeKey = self.privServices[usmUserPrivProtocol.syntax].localizeKey
+ localPrivKey = localizeKey(
+ usmUserAuthProtocol.syntax,
+ pysnmpUsmKeyPriv.syntax,
+ securityEngineID
+ )
else:
raise error.StatusInformation(
errorIndication = errind.unsupportedPrivProtocol
diff --git a/pysnmp/proto/secmod/rfc3826/priv/aes.py b/pysnmp/proto/secmod/rfc3826/priv/aes.py
index 89f7460..d927577 100644
--- a/pysnmp/proto/secmod/rfc3826/priv/aes.py
+++ b/pysnmp/proto/secmod/rfc3826/priv/aes.py
@@ -1,5 +1,7 @@
import random, string
from pysnmp.proto.secmod.rfc3414.priv import base
+from pysnmp.proto.secmod.rfc3414.auth import hmacmd5, hmacsha
+from pysnmp.proto.secmod.rfc3414 import localkey
from pyasn1.type import univ
from pysnmp.proto import errind, error
@@ -21,6 +23,7 @@ random.seed()
class Aes(base.AbstractEncryptionService):
serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 4) # usmAesCfb128Protocol
+ keySize = 16
if version_info < (2, 3):
_localInt = long(random.random()*0xffffffffffffffffL)
else:
@@ -73,9 +76,29 @@ class Aes(base.AbstractEncryptionService):
ord(salt[7])
]
- return privKey[:16], string.join(map(chr, iv), '')
+ return privKey[:self.keySize], string.join(map(chr, iv), '')
+ def hashPassphrase(self, authProtocol, privKey):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ return localkey.hashPassphraseMD5(privKey)
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ return localkey.hashPassphraseSHA(privKey)
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+ def localizeKey(self, authProtocol, privKey, snmpEngineID):
+ if authProtocol == hmacmd5.HmacMd5.serviceID:
+ localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID)
+ elif authProtocol == hmacsha.HmacSha.serviceID:
+ localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID)
+ else:
+ raise error.ProtocolError(
+ 'Unknown auth protocol %s' % (authProtocol,)
+ )
+ return localPrivKey[:16]
+
# 3.2.4.1
def encryptData(self, encryptKey, privParameters, dataToEncrypt):
if AES is None:
diff --git a/setup.py b/setup.py
index 765ecea..25196e8 100644
--- a/setup.py
+++ b/setup.py
@@ -58,6 +58,8 @@ params.update( {
'pysnmp.proto.secmod.rfc3414.priv',
'pysnmp.proto.secmod.rfc3826',
'pysnmp.proto.secmod.rfc3826.priv',
+ 'pysnmp.proto.secmod.eso',
+ 'pysnmp.proto.secmod.eso.priv',
'pysnmp.proto.acmod',
'pysnmp.proto.proxy',
'pysnmp.proto.api' ],