diff options
author | elie <elie> | 2007-07-09 13:39:47 +0000 |
---|---|---|
committer | elie <elie> | 2007-07-09 13:39:47 +0000 |
commit | 1e519091d197e17acf5c6363d7c25b5ffd98ad08 (patch) | |
tree | 82a986ebc97f321911c64f7ec9cfd12d27e648c4 | |
parent | 3517969eaf8fce91f9f43b19fa280e8d376f7dfb (diff) | |
download | pysnmp-1e519091d197e17acf5c6363d7c25b5ffd98ad08.tar.gz |
added support for AES cipher (rfc3826)
-rw-r--r-- | CHANGES | 5 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | docs/pysnmp-tutorial.html | 3 | ||||
-rw-r--r-- | examples/v3arch/agent/cmdrsp.py | 1 | ||||
-rw-r--r-- | examples/v3arch/manager/getgen.py | 1 | ||||
-rw-r--r-- | pysnmp/entity/config.py | 5 | ||||
-rw-r--r-- | pysnmp/entity/rfc3413/oneliner/cmdgen.py | 1 | ||||
-rw-r--r-- | pysnmp/entity/rfc3413/oneliner/ntforg.py | 1 | ||||
-rw-r--r-- | pysnmp/proto/secmod/rfc3414/priv/des.py | 30 | ||||
-rw-r--r-- | pysnmp/proto/secmod/rfc3414/service.py | 100 | ||||
-rw-r--r-- | pysnmp/proto/secmod/rfc3826/__init__.py | 0 | ||||
-rw-r--r-- | pysnmp/proto/secmod/rfc3826/priv/__init__.py | 0 | ||||
-rw-r--r-- | pysnmp/proto/secmod/rfc3826/priv/aes.py | 115 | ||||
-rw-r--r-- | pysnmp/smi/mibs/SNMP-USM-AES-MIB.py | 28 |
14 files changed, 228 insertions, 64 deletions
@@ -33,6 +33,7 @@ Revision 4.1.8a respectively. - Multi-target oneliner API-based example script added. - Ignore more socket errors in datagram-type async socket code. +- AES cipher now supported (rfc3826). Revision 4.1.7a --------------- @@ -82,14 +83,14 @@ Revision 4.1.7a - Memory leak fixed in indices.OidOrderedDict implementation. - Fix to VACM shortcuts to let notifications and requests to co-exist for the same user otherwise. -- Fix to ...oneliner.cmdgen.UsmUserData to support non-default cyphers. +- Fix to ...oneliner.cmdgen.UsmUserData to support non-default ciphers. - USM now uses local notion of snmpEngineBoots/Time when authoritative and cached estimate otherwise. Also, a security fix applied to to USM time-window verification (SF bug #1649032). - Fix to notification objects resolution code at NotificationOriginator.sendNotification() - Do not raise securityLevel for USM error reports that lacks user - information, as these reports could never be cyphered (SF bug #1624720). + information, as these reports could never be ciphered (SF bug #1624720). - Non-default BULK PDU params now actually applied. - SnmpEngineID default value generation algorithmic function changed to allow multiple SNMP engines running on the same host. @@ -21,7 +21,7 @@ FEATURES Features, specific to SNMPv3 model include: -* USM authentication (MD5/SHA) and privacy (DES) protocols (RFC3414) +* USM authentication (MD5/SHA) and privacy (DES/AES) protocols (RFC3414) * View-based access control to use with any SNMP model (RFC3415) * Built-in SNMP proxy PDU converter for building multi-lingual SNMP entities (RFC2576) diff --git a/docs/pysnmp-tutorial.html b/docs/pysnmp-tutorial.html index ea29a04..9e5e363 100644 --- a/docs/pysnmp-tutorial.html +++ b/docs/pysnmp-tutorial.html @@ -1463,7 +1463,8 @@ non-default hash function algorithm. Possible values include <P> Optional <STRONG>privProtocol</STRONG> parameter may be used to specify non-default ciphering algorithm. Possible values include -<STRONG>usmDESPrivProtocol</STRONG> and +<STRONG>usmDESPrivProtocol</STRONG>, +<STRONG>usmAesCfb128Protocol</STRONG>, and <STRONG>usmNoPrivProtocol</STRONG>. </P> </DD> diff --git a/examples/v3arch/agent/cmdrsp.py b/examples/v3arch/agent/cmdrsp.py index 1748ba5..3d147f0 100644 --- a/examples/v3arch/agent/cmdrsp.py +++ b/examples/v3arch/agent/cmdrsp.py @@ -34,6 +34,7 @@ config.addV3User( snmpEngine, 'test-user', config.usmHMACMD5AuthProtocol, 'authkey1', config.usmDESPrivProtocol, 'privkey1' +# config.usmAesCfb128Protocol, 'privkey1' ) # Install default Agent configuration diff --git a/examples/v3arch/manager/getgen.py b/examples/v3arch/manager/getgen.py index 115d008..ed8b7f4 100644 --- a/examples/v3arch/manager/getgen.py +++ b/examples/v3arch/manager/getgen.py @@ -13,6 +13,7 @@ config.addV3User( snmpEngine, 'test-user', config.usmHMACMD5AuthProtocol, 'authkey1', config.usmDESPrivProtocol, 'privkey1' +# config.usmAesCfb128Protocol, 'privkey1' ) # Transport params diff --git a/pysnmp/entity/config.py b/pysnmp/entity/config.py index eb4485a..a9ee81b 100644 --- a/pysnmp/entity/config.py +++ b/pysnmp/entity/config.py @@ -13,6 +13,7 @@ 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.smi.error import NotWritableError from pysnmp import error @@ -28,6 +29,7 @@ usmNoAuthProtocol = noauth.NoAuth.serviceID # Privacy protocol usmDESPrivProtocol = des.Des.serviceID +usmAesCfb128Protocol = aes.Aes.serviceID usmNoPrivProtocol = nopriv.NoPriv.serviceID def __cookV1SystemInfo(snmpEngine, securityName): @@ -136,7 +138,8 @@ def addV3User(snmpEngine, securityName, else: raise error.PySnmpError('Unknown auth protocol %s' % (authProtocol,)) - if privProtocol == usmDESPrivProtocol: + if privProtocol == usmDESPrivProtocol or \ + privProtocol == usmAesCfb128Protocol: if authProtocol == usmHMACMD5AuthProtocol: hashedPrivPassphrase = localkey.hashPassphraseMD5( privKey and privKey or '' diff --git a/pysnmp/entity/rfc3413/oneliner/cmdgen.py b/pysnmp/entity/rfc3413/oneliner/cmdgen.py index 2377bcd..36db105 100644 --- a/pysnmp/entity/rfc3413/oneliner/cmdgen.py +++ b/pysnmp/entity/rfc3413/oneliner/cmdgen.py @@ -13,6 +13,7 @@ usmNoAuthProtocol = config.usmNoAuthProtocol # Privacy protocol usmDESPrivProtocol = config.usmDESPrivProtocol +usmAesCfb128Protocol = config.usmAesCfb128Protocol usmNoPrivProtocol = config.usmNoPrivProtocol class CommunityData: diff --git a/pysnmp/entity/rfc3413/oneliner/ntforg.py b/pysnmp/entity/rfc3413/oneliner/ntforg.py index 467cc90..bc29431 100644 --- a/pysnmp/entity/rfc3413/oneliner/ntforg.py +++ b/pysnmp/entity/rfc3413/oneliner/ntforg.py @@ -10,6 +10,7 @@ usmNoAuthProtocol = cmdgen.usmNoAuthProtocol # Privacy protocol usmDESPrivProtocol = cmdgen.usmDESPrivProtocol +usmAesCfb128Protocol = cmdgen.usmAesCfb128Protocol usmNoPrivProtocol = cmdgen.usmNoPrivProtocol # Credentials diff --git a/pysnmp/proto/secmod/rfc3414/priv/des.py b/pysnmp/proto/secmod/rfc3414/priv/des.py index fd2c553..d8bb7e8 100644 --- a/pysnmp/proto/secmod/rfc3414/priv/des.py +++ b/pysnmp/proto/secmod/rfc3414/priv/des.py @@ -16,14 +16,11 @@ class Des(base.AbstractEncryptionService): serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 2) # usmDESPrivProtocol _localInt = long(random.random()*0xffffffffL) # 8.1.1.1 - def __getEncryptionKey(self, mibInstrumController, privKey): + def __getEncryptionKey(self, privKey, snmpEngineBoots): desKey = privKey[:8] preIV = privKey[8:16] - snmpEngineBoots, = mibInstrumController.mibBuilder.importSymbols( - '__SNMP-FRAMEWORK-MIB', 'snmpEngineBoots' - ) - securityEngineBoots = long(snmpEngineBoots.syntax) + securityEngineBoots = long(snmpEngineBoots) salt = [ securityEngineBoots>>24&0xff, @@ -44,28 +41,30 @@ class Des(base.AbstractEncryptionService): string.join(map(lambda x: chr(x), salt), ''), \ string.join(map(lambda x,y: chr(x^ord(y)), salt, preIV), '') - def __getDecryptionKey(self, mibInstrumController, privKey, salt): + def __getDecryptionKey(self, privKey, salt): 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, mibInstrumController, encryptKey, dataToEncrypt): + def encryptData(self, encryptKey, privParameters, dataToEncrypt): if DES is None: raise error.StatusInformation( errorIndication='encryptionError' ) + + snmpEngineBoots, snmpEngineTime, salt = privParameters # 8.3.1.1 desKey, salt, iv = self.__getEncryptionKey( - mibInstrumController, str(encryptKey) + str(encryptKey), snmpEngineBoots ) # 8.3.1.2 privParameters = univ.OctetString(salt) # 8.1.1.2 - desObj = DES.new(desKey, DES.MODE_CBC, iv) # XXX + desObj = DES.new(desKey, DES.MODE_CBC, iv) plaintext = dataToEncrypt + '\x00' * (8 - len(dataToEncrypt) % 8) ciphertext = desObj.encrypt(plaintext) @@ -73,26 +72,25 @@ class Des(base.AbstractEncryptionService): return univ.OctetString(ciphertext), privParameters # 8.2.4.2 - def decryptData(self, mibInstrumController, decryptKey, - privParameters, encryptedData): + def decryptData(self, decryptKey, privParameters, encryptedData): if DES is None: raise error.StatusInformation( errorIndication='decryptionError' ) + + snmpEngineBoots, snmpEngineTime, salt = privParameters # 8.3.2.1 - if len(privParameters) != 8: + if len(salt) != 8: raise error.StatusInformation( errorIndication='decryptionError' ) # 8.3.2.2 - salt = str(privParameters) + salt = str(salt) # 8.3.2.3 - desKey, iv = self.__getDecryptionKey( - mibInstrumController, str(decryptKey), salt - ) + desKey, iv = self.__getDecryptionKey(str(decryptKey), salt) # 8.3.2.4 -> 8.1.1.3 if len(encryptedData) % 8 != 0: diff --git a/pysnmp/proto/secmod/rfc3414/service.py b/pysnmp/proto/secmod/rfc3414/service.py index 90c2cfa..2e07337 100644 --- a/pysnmp/proto/secmod/rfc3414/service.py +++ b/pysnmp/proto/secmod/rfc3414/service.py @@ -2,6 +2,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.smi.error import NoSuchInstanceError from pysnmp.proto import rfc1155, error @@ -33,6 +34,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): } privServices = { des.Des.serviceID: des.Des(), + aes.Aes.serviceID: aes.Aes(), nopriv.NoPriv.serviceID: nopriv.NoPriv() } _securityParametersSpec = UsmSecurityParameters() @@ -159,7 +161,8 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): pysnmpUsmKeyPrivLocalized = pysnmpUsmKeyEntry.getNode( pysnmpUsmKeyEntry.name + (2,) + tblIdx ) - if usmUserPrivProtocol.syntax == des.Des.serviceID: + if usmUserPrivProtocol.syntax == des.Des.serviceID or \ + usmUserPrivProtocol.syntax == aes.Aes.serviceID: if usmUserAuthProtocol.syntax == hmacsha.HmacSha.serviceID: localPrivKey = localkey.localizeKeySHA( pysnmpUsmKeyPriv.syntax, securityEngineID @@ -277,38 +280,6 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): scopedPDUData = msg.setComponentByPosition(3).getComponentByPosition(3) scopedPDUData.setComponentByPosition(0, scopedPDU) - # 3.1.4a - if securityLevel == 3: - privHandler = self.privServices.get(usmUserPrivProtocol) - if privHandler is None: - raise error.StatusInformation( - errorIndication = 'encryptionError' - ) - dataToEncrypt = encoder.encode(scopedPDU) - - debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: scopedPDU encoded') - - try: - ( encryptedData, - privParameters ) = privHandler.encryptData( - snmpEngine.msgAndPduDsp.mibInstrumController, - usmUserPrivKeyLocalized, dataToEncrypt - ) - except error.StatusInformation, statusInformation: - raise - - debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: scopedPDU cyphered') - - securityParameters.setComponentByPosition(5, privParameters) - scopedPDUData.setComponentByPosition(1, encryptedData) - - # 3.1.4b - elif securityLevel == 1 or securityLevel == 2: - securityParameters.setComponentByPosition(5, '') - - # 3.1.5 - securityParameters.setComponentByPosition(0, securityEngineID) - # 3.1.6a if securityStateReference is None and ( # request type check added securityLevel == 3 or securityLevel == 2 @@ -338,7 +309,41 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: assuming zero snmpEngineBoots, snmpEngineTime') debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: use snmpEngineBoots %s snmpEngineTime %s for securityEngineID %s' % (snmpEngineBoots, snmpEngineTime, securityEngineID)) + + # 3.1.4a + if securityLevel == 3: + privHandler = self.privServices.get(usmUserPrivProtocol) + if privHandler is None: + raise error.StatusInformation( + errorIndication = 'encryptionError' + ) + dataToEncrypt = encoder.encode(scopedPDU) + + debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: scopedPDU encoded') + + try: + ( encryptedData, + privParameters ) = privHandler.encryptData( + usmUserPrivKeyLocalized, + ( snmpEngineBoots, snmpEngineTime, None ), + dataToEncrypt + ) + except error.StatusInformation, statusInformation: + raise + + securityParameters.setComponentByPosition(5, privParameters) + scopedPDUData.setComponentByPosition(1, encryptedData) + + debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: scopedPDU ciphered') + + # 3.1.4b + elif securityLevel == 1 or securityLevel == 2: + securityParameters.setComponentByPosition(5, '') + + debug.logger & debug.flagSM and debug.logger('__generateRequestOrResponseMsg: %s' % scopedPDUData.prettyPrint()) + # 3.1.5 + securityParameters.setComponentByPosition(0, securityEngineID) securityParameters.setComponentByPosition(1, snmpEngineBoots) securityParameters.setComponentByPosition(2, snmpEngineTime) @@ -699,7 +704,7 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): ) scopedPduData = msg.getComponentByPosition(3) - + # 3.2.8a if securityLevel == 3: privHandler = self.privServices.get(usmUserPrivProtocol) @@ -709,16 +714,19 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): ) encryptedPDU = scopedPduData.getComponentByPosition(1) if encryptedPDU is None: # no ciphertext - raise error.StatusInformation( + raise error.StatusInformation( errorIndication = 'decryptionError' - ) + ) + try: - decryptedData = privHandler.decryptData( - snmpEngine.msgAndPduDsp.mibInstrumController, usmUserPrivKeyLocalized, - securityParameters.getComponentByPosition(5), + decryptedData = privHandler.decryptData( + usmUserPrivKeyLocalized, + ( securityParameters.getComponentByPosition(1), + securityParameters.getComponentByPosition(2), + securityParameters.getComponentByPosition(5) ), encryptedPDU ) - debug.logger & debug.flagSM and debug.logger('processIncomingMsg: PDU decyphered') + debug.logger & debug.flagSM and debug.logger('processIncomingMsg: PDU deciphered') except error.StatusInformation: usmStatsDecryptionErrors, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-USER-BASED-SM-MIB', 'usmStatsDecryptionErrors') usmStatsDecryptionErrors.syntax = usmStatsDecryptionErrors.syntax+1 @@ -732,9 +740,15 @@ class SnmpUSMSecurityModel(AbstractSecurityModel): maxSizeResponseScopedPDU=maxSizeResponseScopedPDU ) scopedPduSpec = scopedPduData.setComponentByPosition(0).getComponentByPosition(0) - scopedPDU, rest = decoder.decode( - decryptedData, asn1Spec=scopedPduSpec - ) + try: + scopedPDU, rest = decoder.decode( + decryptedData, asn1Spec=scopedPduSpec + ) + except PyAsn1Error, why: + debug.logger & debug.flagSM and debug.logger('processIncomingMsg: PDU decoder failed %s' % why) + raise error.StatusInformation( + errorIndication = 'decryptionError' + ) else: # 3.2.8b scopedPDU = scopedPduData.getComponentByPosition(0) diff --git a/pysnmp/proto/secmod/rfc3826/__init__.py b/pysnmp/proto/secmod/rfc3826/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pysnmp/proto/secmod/rfc3826/__init__.py diff --git a/pysnmp/proto/secmod/rfc3826/priv/__init__.py b/pysnmp/proto/secmod/rfc3826/priv/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pysnmp/proto/secmod/rfc3826/priv/__init__.py diff --git a/pysnmp/proto/secmod/rfc3826/priv/aes.py b/pysnmp/proto/secmod/rfc3826/priv/aes.py new file mode 100644 index 0000000..d1286c8 --- /dev/null +++ b/pysnmp/proto/secmod/rfc3826/priv/aes.py @@ -0,0 +1,115 @@ +import random, string +from pysnmp.proto.secmod.rfc3414.priv import base +from pyasn1.type import univ +from pysnmp.proto import error + +try: + from Crypto.Cipher import AES +except ImportError: + AES = None + +random.seed() + +# RFC3826 + +# + +class Aes(base.AbstractEncryptionService): + serviceID = (1, 3, 6, 1, 6, 3, 10, 1, 2, 4) # usmAesCfb128Protocol + _localInt = long(random.random()*0xffffffffffffffffL) + # 3.1.2.1 + def __getEncryptionKey(self, privKey, snmpEngineBoots, snmpEngineTime): + salt = [ + self._localInt>>56&0xff, + self._localInt>>48&0xff, + self._localInt>>40&0xff, + self._localInt>>32&0xff, + self._localInt>>24&0xff, + self._localInt>>16&0xff, + self._localInt>>8&0xff, + self._localInt&0xff + ] + + if self._localInt == 0xffffffffffffffffL: + self._localInt = 0 + else: + self._localInt = self._localInt + 1 + + salt = string.join(map(lambda x: chr(x), salt), '') + + return self.__getDecryptionKey(privKey, snmpEngineBoots, + snmpEngineTime, salt) + ( salt, ) + + def __getDecryptionKey(self, privKey, snmpEngineBoots, + snmpEngineTime, salt): + snmpEngineBoots, snmpEngineTime, salt = ( + long(snmpEngineBoots), long(snmpEngineTime), str(salt) + ) + + iv = [ + snmpEngineBoots>>24&0xff, + snmpEngineBoots>>16&0xff, + snmpEngineBoots>>8&0xff, + snmpEngineBoots&0xff, + snmpEngineTime>>24&0xff, + snmpEngineTime>>16&0xff, + snmpEngineTime>>8&0xff, + snmpEngineTime&0xff, + ord(salt[7]), + ord(salt[6]), + ord(salt[5]), + ord(salt[4]), + ord(salt[3]), + ord(salt[2]), + ord(salt[1]), + ord(salt[0]) + ] + + return privKey[:16], string.join(map(lambda x: chr(x), iv), '') + + + # 3.2.4.1 + def encryptData(self, encryptKey, privParameters, dataToEncrypt): + if AES is None: + raise error.StatusInformation( + errorIndication='encryptionError' + ) + + snmpEngineBoots, snmpEngineTime, salt = privParameters + + # 3.3.1.1 + aesKey, iv, salt = self.__getEncryptionKey( + str(encryptKey), snmpEngineBoots, snmpEngineTime + ) + + # 3.3.1.3 + aesObj = AES.new(aesKey, AES.MODE_CFB, iv) + ciphertext = aesObj.encrypt(dataToEncrypt) + + # 3.3.1.4 + return univ.OctetString(ciphertext), salt + + # 3.2.4.2 + def decryptData(self, decryptKey, privParameters, encryptedData): + if AES is None: + raise error.StatusInformation( + errorIndication='decryptionError' + ) + + snmpEngineBoots, snmpEngineTime, salt = privParameters + + # 3.3.2.1 + if len(salt) != 8: + raise error.StatusInformation( + errorIndication='decryptionError' + ) + + # 3.3.2.3 + aesKey, iv = self.__getDecryptionKey( + str(decryptKey), snmpEngineBoots, snmpEngineTime, salt + ) + + aesObj = AES.new(aesKey, AES.MODE_CFB, iv) + + # 3.3.2.4-6 + return aesObj.decrypt(str(encryptedData)) diff --git a/pysnmp/smi/mibs/SNMP-USM-AES-MIB.py b/pysnmp/smi/mibs/SNMP-USM-AES-MIB.py new file mode 100644 index 0000000..8097260 --- /dev/null +++ b/pysnmp/smi/mibs/SNMP-USM-AES-MIB.py @@ -0,0 +1,28 @@ +# PySNMP SMI module. Autogenerated from smidump -f python SNMP-USM-AES-MIB +# by libsmi2pysnmp-0.0.7-alpha at Mon Jul 9 17:29:49 2007, +# Python version (2, 4, 3, 'final', 0) + +# Imported just in case new ASN.1 types would be created +from pyasn1.type import constraint, namedval + +# Imports + +( Integer, ObjectIdentifier, OctetString, ) = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString") +( snmpPrivProtocols, ) = mibBuilder.importSymbols("SNMP-FRAMEWORK-MIB", "snmpPrivProtocols") +( Bits, Integer32, ModuleIdentity, MibIdentifier, ObjectIdentity, TimeTicks, snmpModules, ) = mibBuilder.importSymbols("SNMPv2-SMI", "Bits", "Integer32", "ModuleIdentity", "MibIdentifier", "ObjectIdentity", "TimeTicks", "snmpModules") + +# Objects + +usmAesCfb128Protocol = MibIdentifier((1, 3, 6, 1, 6, 3, 10, 1, 2, 4)) +snmpUsmAesMIB = ModuleIdentity((1, 3, 6, 1, 6, 3, 20)).setRevisions(("2004-06-14 00:00",)) + +# Augmentions + +# Exports + +# Module identity +mibBuilder.exportSymbols("SNMP-USM-AES-MIB", PYSNMP_MODULE_ID=snmpUsmAesMIB) + +# Objects +mibBuilder.exportSymbols("SNMP-USM-AES-MIB", usmAesCfb128Protocol=usmAesCfb128Protocol, snmpUsmAesMIB=snmpUsmAesMIB) + |