Cover V09, I05
Article
Figure 1

may2000.tar


SNMPv3 -- User Security Model

Eric Davis

This is the first of two articles describing the security features of the SNMP version 3 protocol. The SNMPv3 RFCs describe a new framework that is used for defining the relationships between the SNMP versions 1, 2, and 3 specifications. This framework is partitioned in a modular fashion and is heavily based on previous work (i.e., SNMPv1, SNMPv2c, SNMPv2u, and SNMPv2*).

Two core modules within the framework are the User-based Security Model (USM) and the View-based Access Control Model (VACM). The USM is in charge of authenticating, encrypting, and decrypting SNMP packets, and the VACM is in charge of administering access to MIB data. This article gives an overview of the USM. Next month we will take a look at the VACM.

The USM is specified in RFC 2574. A weak point of all the previous well-known SNMP versions has been the lack of a solid, agreed upon security scheme. In designing the USM, these classic security threats had to be addressed:

  • Modification of Information (Data Integrity) -- Ensure that the data is not maliciously altered during transit by an unauthorized entity.
  • Masquerading (Data Origin Authentication) -- Ensure that it is known exactly who and where the data came from to prevent an unauthorized entity from assuming the identity of an authorized user.
  • Disclosure (Data Confidentiality) -- Ensure that an unauthorized entity cannot eavesdrop on the data exchanges.
  • Message Stream Modification (Message Timeliness) -- Ensure that the data was received in a timely manner to prevent malicious re-ordering of data by an unauthorized entity.

The USM is able to protect SNMPv3 packets from the above threats by utilizing a concept of multiple users where each user provides secret keys for authentication and privacy. The authentication protocols specified for use are HMAC-MD5 and HMAC-SHA. The privacy protocol specified is CBC-DES. The RFC states that the security protocols used for the USM are considered acceptably secure at the time of its writing. However, the model allows for new authentication and privacy protocols to be specified at a future time if the need arises.

Concepts

The SNMPv3 framework introduces many new concepts. Most of these concepts are used by multiple modules within the framework. Here are a few that are used by the USM:

  • snmpEngineID -- A unique identifier for an SNMP engine within an administrative domain. The value of this octet string cannot be zero length, all ‘0x00'H, or all ‘0xFF'H. The snmpEngineID is usually computed using a combination of the enterprise number, IP or MAC address, and an administratively assigned string.
  • snmpEngineBoots -- A count of the number of times an SNMP engine has rebooted or re-initialized since the snmpEngineID was last set. This counter is initially set to zero.
  • snmpEngineTime -- The number of seconds since the snmpEngineBoots counter was last incremented. This counter is initially set to zero. If the snmpEngineTime reaches its maximum (2147483647), then the snmpEngineBoots is incremented by one, and the snmpEngineTime starts counting again from zero.
  • snmpSecurityLevel -- There are three possible security levels: noAuthNoPriv, authNoPriv, and authPriv. The noAuthNoPriv level specifies no authentication or privacy is performed. The authNoPriv level specifies that authentication is performed but not privacy. The authPriv level specifies that both authentication and privacy are being performed. One reason a noAuthPriv security level does not exist is because a message authentication digest is needed to ensure the integrity of the security parameters, namely the privacy parameters (i.e., DES salt).
  • Authoritative SNMP Engine -- To protect against message replay, delay, and redirection, one of the communicating SNMP engines is designated as the Authoritative SNMP Engine. The Authoritative SNMP Engine is an engine that receives SNMP messages that need a response. This is always the agent that a manager communicates with.

SNMPv3 Packet Format

The SNMP packet structure for version 3 has been changed to accommodate the use of a security model like the USM (see Figure 1).

  • msgVersion -- The SNMP version of the packet (e.g., 1, 2, or 3).
  • msgID -- The msgID is used to coordinate request and response messages between manager and agent. A msgID in a response must be the same as the msgID received in the request.
  • msgMaxSize -- The msgMaxSize conveys the maximum message size that the sender is able to accept from another SNMP engine.
  • msgFlags -- The msgFlags is a single octet, which is used to convey how the message is to be processed. For instance, two bits of the msgFlags are used to specify whether the packet has been authenticated and whether it has been encrypted.
  • msgSecurityModel -- SNMPv3 was designed for the use of multiple co-existing security models. The msgSecurityModel field specifies the security model that was used to generate the message. Therefore, the receiving entity knows which security model must be used to perform security processing upon message reception.
  • msgSecurityParameters -- The msgSecurityParameters is an octet string that contains the security model specific data. This data is defined by and used only by the security model specified by the msgSecurityModel.
  • scopedPDU -- The scopedPDU contains the normal PDU and information for identifying the administratively unique context for processing the PDU.

USM Security Parameters

The USM uses the msgSecurityParameters to hold five values. These values are used by the authentication module to ensure data integrity and origin authentication, by the timeliness module to protect against message delay or replay, and by the privacy module to protect against message payload disclosure.

  • msgAuthoritativeEngineID -- The snmpEngineID of the authoritative engine is always put in this field no matter which side the packet originates from.
  • msgAuthoritativeEngineBoots -- The snmpEngineBoots of the authoritative engine.
  • msgAuthoritativeEngineTime -- The snmpEngineTime of the authoritative engine.
  • msgUserName -- The name of the user whose secret keys were used to possibly authenticate and encrypt the packet.
  • msgAuthenticationParameters -- If the packet has been authenticated, then this field contains the computed HMAC-MD5 or HMAC-SHA message digest for the packet.
  • msgPrivacyParameters -- If the scopedPDU of the packet has been encrypted, then this field contains the salt (i.e., random variant) that was used as input to the DES algorithm.

Agent Discovery

As mentioned above, the USM requires that the snmpEngineID, snmpEngineBoots, and snmpEngineTime of the authoritative engine be placed in the msgSecurityParameters. This requires the non-authoritative engine (i.e., manager) to know these values for the authoritative engine (i.e., agent) before a GET, NEXT, or SET operation can be completed.

This is achieved by a discovery process. There are two discovery transactions that occur. The first is to discover the snmpEngineID of the agent. The second is to discover the snmpEngineBoots and snmpEngineTime. The second transaction is only needed if the manager wants to use a security level of authNoPriv or authPriv. This is because the msgAuthoritativeEngineBoots and msgAuthoritativeEngineTime are used by the timeliness module, which is part of the authentication process.

The first discovery transaction is initiated by the manager sending an SNMPv3 packet with the msgAuthoritativeEngineID containing a bogus value. When the agent receives a packet where the msgAuthoritativeEngineID is different from its own, the packet is discarded and a discovery packet is returned to the manager. The returned discovery packet contains the correct snmpEngineID, which must be used by the manager.

The second discovery transaction requires an authenticated packet to be sent to the agent. This means that the authentication flag is set in the msgFlags, and the msgAuthenticationParameters contains the computed message digest for the packet. The secret key used for authenticating the packet is from the user specified in msgUserName. What makes this a discovery packet is that the msgAuthoritativeEngineBoots and msgAuthoritativeEngineTime contain bogus values. When the agent receives this packet, it is first authenticated. Once the authentication is completed, the msgAuthoritativeEngineBoots and msgAuthoritativeEngineTime values are checked. Since the values are bogus, the packet is discarded and a second discovery packet is returned to the manager. The returned discovery packet is authenticated, using the same user, and contains the correct values of the snmpEngineBoots and snmpEngineTime, which must be used by the manager.

Timeliness

Once a manager has learned the snmpEngineBoots and snmpEngineTime of an agent, the manager must maintain its own local notion of what these values are supposed to be. This requires the manager to increment the learned snmpEngineTime every second, so the value will be very close to the master values maintained by the agent. If the snmpEngineTime rolls over, then the snmpEngineBoots must be incremented. A manager must keep local notions of these values for each agent in which it wishes to communicate.

The timeliness checks by an agent are considered part of the authentication process and are done right after the received packet has been authenticated. If the msgAuthoritativeEngineBoots is different from the agent's current value of the snmpEngineBoots, the packet is discarded and a discovery packet is sent back to the manager. If that check passes, then the msgAuthoritativeEngineTime is checked against the agent's current value of the snmpEngineTime. If the difference between the two is more or less than 150 seconds, the packet is discarded and a discovery packet is sent back to the manager. If both of the checks pass, then the packet is considered to have been received in a timely manner and processing continues.

The value of +/- 150 seconds for the comparison of the snmpEngineTime is the default value specified by the RFC. This value could be modified to something more suitable based on the speed and size of your network.

Authentication

The USM specifies the use of the Message Digest 5 (MD5) and Secure Hash Algorithm 1 (SHA-1) algorithms for authenticating SNMPv3 packets. These algorithms are used to create unique fixed-sized message digests, also called digital signatures or fingerprints, of a variable length message. MD5 creates a digest of 128 bits (16 bytes), and SHA-1 creates a digest of 160 bits (20 bytes). Both MD5 and SHA-1 cannot be used directly as a message authentication code because they do not use secret keys as input to derivate the computed message digest. This is why the Keyed Hashing for Message Authentication (HMAC) algorithm in combination with MD5 and SHA-1 is used for computing message digests. The HMAC algorithm defines a procedure for appending a secret key to the data and then computing the MD5 or SHA-1 message digest. This guarantees that parties who wish to compute identical message digests for the same block of data must share a common secret key. Here are the steps that are taken for sending and receiving an authenticated SNMPv3 packet.

Sending an authenticated SNMPv3 packet:

1. The entire packet is created. The authentication flag is turned on in the msgFlags, and the msgAuthenticationParameters is zeroed out.

2. A message digest is computed of the packet using the secret authentication key for the user specified in msgUserName. The algorithm used (e.g., HMAC-MD5 or HMAC-SHA) is determined by the authentication protocol specified for the user in the User Table.

3. The computed message digest is inserted in the msgAuthenticationParameters.

4. The packet is sent.

Receiving an authenticated SNMPv3 packet:

1. The packet is received.

2. If the authentication flag is turned on in the msgFlags, then continue with the authentication process at step 3. If the packet was not authenticated by the sender, authentication is skipped.

3. The msgAuthenticationParameters is saved.

4. The msgAuthenticationParameters is zeroed out.

5. A message digest is computed of the packet using the secret authentication key for the user specified in msgUserName. The algorithm used (e.g., HMAC-MD5 or HMAC-SHA) is determined by the authentication protocol specified for the user in the User Table. If the user does not exist in the User Table, then the packet can not be authenticated and it is dropped.

6. The computed message digest is compared to the previously saved msgAuthenticationParameters. If they are different, then the packet is not authentic and it is dropped. If they are the same, then the packet is authentic and processing may continue.

Privacy

The USM specifies the use of the Cipher Block Chaining mode to the Data Encryption Standard (CBC-DES) algorithm for encrypting and decrypting SNMPv3 packets. The scope of the encryption only covers the scopedPDU, which contains the PDU and context data used by the VACM. The DES algorithm takes three inputs. These inputs are the data to be encrypted, a 56-bit secret key, and a 56-bit randomly generated salt used to ensure that two different initialization vectors are used for two different data inputs encrypted with the same secret key. For two parties to use encryption during communication, each must share a secret privacy key as well as the salt used to derivate the initialization vector. The secret privacy keys are stored in the User Table, and the salt is transmitted with the packet in the msgPrivacyParameters. Here are the steps that are taken for sending and receiving an encrypted packet.

Sending an encrypted SNMPv3 packet:

1. The entire packet is created, and the authentication and privacy flags are turned on in the msgFlags.

2. A random salt value is computed.

3. The scopedPDU is encrypted using the salt and the secret privacy key for the user specified in msgUserName.

4. The salt is inserted into the msgPrivacyParameters.

5. Authenticate the packet as previously described.

6. The packet is sent.

Receiving an encrypted SNMPv3 packet:

1. The packet is received.

2. If the authentication flag is turned on in the msgFlags, then the packet must be authenticated as previously described and continue to step 3. If the authentication flag is turned off in the msgFlags, then decryption is skipped.

3. If the privacy flag is turned on in the msgFlags, continue with the decryption process at step 4. If the packet was not encrypted by the sender, then decryption is skipped.

4. Decrypt the scopedPDU using the salt specified in the msgSecurityParameters and the secret privacy key for the user specified in msgUserName.

5. Continue processing the packet.

User Table

Every agent maintains a User Table, which is used to store all the users that have access to the system via SNMP. Each user entry in the table contains the following information, all of which can be modified via SNMP operations on the USM MIB:

  • User Name -- A human readable string representing the name of the user.
  • Authentication Protocol -- An indication of whether or not messages sent or received on behalf of this user can be authenticated and, if so, which authentication protocol to use. The current values for this field are: usmNoAuthProtocol, usmHMACMD5AuthProtocol, and usmHMACSHAAuthProtocol.
  • Authentication Key -- The localized secret key used by the authentication protocol for authenticating messages.
  • Privacy Protocol -- An indication of whether or not messages sent or received on behalf of this user can be encrypted and, if so, which privacy protocol to use. The current values for this field are: usmNoPrivProtocol and usmDESPrivProtocol.
  • Privacy Key -- The localized secret key used by the privacy protocol for encrypting and decrypting messages.

The User Table has a spin lock associated with it named usmUserSpinLock. A spin lock is an advisory lock, which is used to allow several SNMP managers to coordinate their attempts in modifying a MIB table. The concept is simple. Whenever a change is going to be made to the User Table on an agent, the value of the usmUserSpinLock must be retrieved via a GET command by the manager. Then the manager sends a SET command to the agent, which contains a PDU to set the usmUserSpinLock and whatever variables in the User Table that need to be modified. The value of the usmUserSpinLock in the SET command must be the value that was retrieved in the previous GET command. Once the agent receives the message containing the SET command, the usmUserSpinLock is immediately processed. If the current value of the usmUserSpinLock is not the same as the value specified in the SET command, the SET operation has failed and an error is returned. If the two values are the same, then the User Table variables specified in the PDU of the SET command are set. When the agent has finished processing the entire PDU, the usmUserSpinLock value is incremented by one. Thus, if the value of the usmUserSpinLock is different when it is being set, then the User Table has been modified since the initial retrieval of the usmUserSpinLock value.

Localized Keys

A localized key is a concept that allows the use of the same password for a user on many different agents. It would be very cumbersome to be forced to remember a different password for each agent in which the user exists. The localized key is computed using a one-way hash function (e.g., MD5 or SHA-1) against a secret password and the snmpEngineID of the agent where the user exists. This results in secret keys that, although use the same password, are completely different for each agent.

Changing Keys

The USM introduces the KeyChange type that describes a convention for using secret keys. The KeyChange definition provides a secure means of sending localized keys across networks, which allows users to change their keys. The following steps will occur when a user changes their key.

Manager:

1. The user enters in a new password.

2. The localized key is computed using the new password, and the snmpEngineID of the agent where the key is going to be changed.

3. A one-way function is used to produce a value from the old key.

4. This value is exclusively or'ed (XOR) with the new key.

5. The final KeyChange value is sent to the agent in a SET operation.

Agent: (after receiving the KeyChange SET operation)

1. The same one-way function that the manager used to produce a value from the old key is performed.

2. This value is exclusively or'ed (XOR) with the received KeyChange to produce the new key.

3. The new key for the user is set in the User Table.

Creating/Cloning Users

It is possible to create a new user in an agent's User Table. This is performed by cloning an existing user. All the data for the clone-from user is copied to the newly created entry for the new user. Once the new user entry has been created, it is suggested to immediately change the keys. Note that you can only create a new user by cloning from another existing user. This requires that the User Table for a particular agent must be initialized to contain the minimum set of users needed in your environment.

Using your SNMPv3 manager of choice, here is an example of how to create a new user from an existing user named foo and changing the secret keys. Note that the actual name of the new user being created is not shown here because the name is specified in the OID index of the variables which are being set. The User Table is indexed by the user name.

First, get the spin lock value and create the user. To ensure the new user entry cannot be immediately used, set the status to createAndWait.

sValue = GET (usmUserSpinLock)
SET((usmUserSpinLock = sValue),
    (usmUserCloneFrom = foo),
    (usmUserStatus = createAndWait))
Now, change the secret privacy key. Note you must know the secret privacy key for foo to compute the KeyChange. The privKeyChange value is computed using the privacy key of the clone-from user and the new secret key to be used for the new user. Make sure to use the spin lock. Also, the usmUserPublic variable can be written as part of the procedure for changing a user's secret key, and later read to determine whether the change of the secret was completed.

sValue = GET(usmUserSpinLock)
SET((usmUserSpinLock = sValue),
    (usmUserPrivKeyChange = privKeyChange),
    (usmUserPublic = randomValue))
if (randomValue != GET(usmUserPublic)) then try again
If the new user is never going to use encryption, then you can set the privProtocol to usmNoPrivProtocol and not bother with changing the privacy key.

sValue = GET(usmUserSpinLock)
SET((usmUserSpinLock = sValue),
    (usmUserPrivProtocol = usmNoPrivProtocol))
Next, change the secret authentication key. Note you must know the secret authentication key for foo to compute the KeyChange. The authKeyChange value is computed using the authentication key of the clone-from user and the new secret key to be used for the new user. Once again, make sure to use the spin lock.

sValue = GET(usmUserSpinLock)
SET((usmUserSpinLock = sValue),
    (usmUserAuthKeyChange = authKeyChange),
    (usmUserPublic = randomValue))
if (randomValue != GET(usmUserPublic)) then try again
If the new user is never going to use authentication, then you can set the authProtocol to usmNoAuthProtocol and not bother with changing the authentication key.

sValue = GET(usmUserSpinLock)
SET((usmUserSpinLock = sValue),
    (usmUserAuthProtocol = usmNoAuthProtocol))
Finally, activate this new user by setting the status to active.

sValue = GET(usmUserSpinLock)

SET((usmUserSpinLock = sValue),
    (usmUserStatus = active))
Conclusion

This overview of the USM should give you an understanding of what is involved in authenticating and encrypting/decrypting SNMPv3 packets. In addition, you can start to think about how you will configure the agents in your environment when you deploy SNMPv3 capable routers, switches, and servers. Next month, I will take a look at the VACM and show how it is used to administer access to MIB data.

References

SNMPv3: RFCs 2570, 2571, 2572, 2573, 2574, 2575

SNMP, SNMPv2, SNMPv3, and RMON 1 and 2 (Third Edition) by William Stallings, Addison-Wesley Publishing Company.

Understanding SNMP MIBs by David Perkins and Evan McGinnis, Prentice Hall PTR.

About the Author

Eric Davis is a Software Engineer in the networking division of Wind River Systems where he works on the TCP/IP stack of the VxWorks embedded OS. He lives in the SF Bay Area with his wife, Kathie, and dog, Maka. He can be reached at: edavis@windriver.com.