Reeder key localization for AES192/256 encryption implemented

pull/20/head
Ilya Etingof 2016-08-21 23:00:16 +02:00
parent 9efc0872d7
commit 6eed8eff24
6 changed files with 84 additions and 4 deletions

View File

@ -9,6 +9,12 @@ Github `repo <https://github.com/etingof/pysnmp>`_
MIB objects. A side effect of this change is that additional
var-binds can only be added prior to .resolveMibObjects() is
run.
- Non-standard (but apparently used by many vendors) Reeder AES192/256
key localization algorithm implemented and set as default for
usmAesCfb192Protocol and usmAesCfb256Protocol identifiers.
Original and more standard implementation can still be used
with the usmAesBlumenthalCfb192Protocol and
usmAesBlumenthalCfb192Protocol IDs respectively.
- Fix to NotificationType to make additional var-binds overriding
MIB objects implicitly included through NOTIFICATION-TYPE OBJECTS.
- Fix to SNMP engine boots counter persistence on Python 3.

View File

@ -29,8 +29,10 @@ usmNoAuthProtocol = noauth.NoAuth.serviceID
usmDESPrivProtocol = des.Des.serviceID
usm3DESEDEPrivProtocol = des3.Des3.serviceID
usmAesCfb128Protocol = aes.Aes.serviceID
usmAesCfb192Protocol = aes192.Aes192.serviceID
usmAesCfb256Protocol = aes256.Aes256.serviceID
usmAesBlumenthalCfb192Protocol = aes192.Aes192.serviceID # semi-standard but not widely used
usmAesBlumenthalCfb256Protocol = aes256.Aes256.serviceID # semi-standard but not widely used
usmAesCfb192Protocol = aes192.AesReeder192.serviceID # non-standard but used by many vendors
usmAesCfb256Protocol = aes256.AesReeder256.serviceID # non-standard but used by many vendors
usmNoPrivProtocol = nopriv.NoPriv.serviceID
# Auth services
@ -44,6 +46,8 @@ privServices = {des.Des.serviceID: des.Des(),
aes.Aes.serviceID: aes.Aes(),
aes192.Aes192.serviceID: aes192.Aes192(),
aes256.Aes256.serviceID: aes256.Aes256(),
aes192.AesReeder192.serviceID: aes192.AesReeder192(), # non-standard
aes256.AesReeder256.serviceID: aes256.AesReeder256(), # non-standard
nopriv.NoPriv.serviceID: nopriv.NoPriv()}

View File

@ -8,9 +8,26 @@ from pysnmp.proto.secmod.eso.priv import aesbase
class Aes192(aesbase.AbstractAes):
"""AES 192/256 bit encryption (Internet draft)
"""AES 192 bit encryption (Internet draft)
Reeder AES encryption:
http://tools.ietf.org/html/draft-blumenthal-aes-usm-04
"""
serviceID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 1) # cusmAESCfb192PrivProtocol
keySize = 24
class AesReeder192(aesbase.AbstractAesReeder):
"""AES 192 bit encryption (Internet draft)
Reeder AES encryption with non-standard key localization algorithm
borrowed from Reeder 3DES draft:
http://tools.ietf.org/html/draft-blumenthal-aes-usm-04
https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00
Known to be used by many vendors including Cisco and others.
"""
serviceID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 101) # cusmAESCfb192PrivProtocol (non-standard)
keySize = 24

View File

@ -8,9 +8,24 @@ from pysnmp.proto.secmod.eso.priv import aesbase
class Aes256(aesbase.AbstractAes):
"""AES 192/256 bit encryption (Internet draft)
"""AES 256 bit encryption (Internet draft)
http://tools.ietf.org/html/draft-blumenthal-aes-usm-04
"""
serviceID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 2) # cusmAESCfb256PrivProtocol
keySize = 32
class AesReeder256(aesbase.AbstractAesReeder):
"""AES 256 bit encryption (Internet draft)
Reeder AES encryption with non-standard key localization algorithm
borrowed from Reeder 3DES draft:
http://tools.ietf.org/html/draft-blumenthal-aes-usm-04
https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00
Known to be used by many vendors including Cisco and others.
"""
serviceID = (1, 3, 6, 1, 4, 1, 9, 12, 6, 1, 102) # cusmAESCfb256PrivProtocol (non-standard)
keySize = 32

View File

@ -41,3 +41,39 @@ class AbstractAes(aes.Aes):
'Unknown auth protocol %s' % (authProtocol,)
)
return localPrivKey[:self.keySize]
class AbstractAesReeder(AbstractAes):
"""AES encryption with non-standard key localization.
Cisco devices do not use:
https://tools.itef.org/pdf/draft_bluementhal-aes-usm-04.txt
for key localization instead, they use the procedure for 3DES key localization
specified in:
https://tools.itef.org/pdf/draft_reeder_snmpv3-usm-3desede-00.pdf
The difference between the two is that the Reeder draft does key extension by repeating
the steps in the password to key algorithm (hash phrase, then localize with SNMPEngine ID).
"""
# 2.1 of https://tools.itef.org/pdf/draft_bluementhal-aes-usm-04.txt
def localizeKey(self, authProtocol, privKey, snmpEngineID):
if authProtocol == hmacmd5.HmacMd5.serviceID:
localPrivKey = localkey.localizeKeyMD5(privKey, snmpEngineID)
# now extend this key if too short by repeating steps that includes the hashPassphrase step
while len(localPrivKey) < self.keySize:
newKey = hashPassphraseMD5(localPrivKey) # this is the difference between reeder and bluementhal
localPrivKey += localizeKeyMD5(newKey, snmpEngineID)
elif authProtocol == hmacsha.HmacSha.serviceID:
localPrivKey = localkey.localizeKeySHA(privKey, snmpEngineID)
while len(localPrivKey < self.keySize):
newKey = hashPassphraseSHA(localPrivKey)
localPrivKey += localizeKeySHA(newKey, snmpEngineID)
else:
raise error.ProtocolError(
'Unknown auth protocol %s' % (authProtocol,)
)
return localPrivKey[:self.keySize]

View File

@ -46,6 +46,8 @@ class SnmpUSMSecurityModel(AbstractSecurityModel):
aes.Aes.serviceID: aes.Aes(),
aes192.Aes192.serviceID: aes192.Aes192(),
aes256.Aes256.serviceID: aes256.Aes256(),
aes192.AesReeder192.serviceID: aes192.AesReeder192(), # non-standard
aes256.AesReeder256.serviceID: aes256.AesReeder256(), # non-standard
nopriv.NoPriv.serviceID: nopriv.NoPriv()}
def __init__(self):