Daniel L. McDonald
Sun Microsystems, USA
Bao G. Phan
Naval Research Laboratory, USA
Randall J. Atkinson
Cisco Systems, USA
This paper presents an application programmer interface (API) which, in combination with interfaces presented to a protocol stack implementation, provides a set of abstractions allowing different session key management schemes to be built outside the operating system kernel.
As the global Internet continues its exponential growth, many concerns once disregarded now fall under the scrutiny of the Internet community. Security is among the top areas of concern for the Internet Engineering Task Force (IETF). The IETF has advanced to Proposed Standard, a security architecture for the Internet Protocol [Atk95a, Atk95b, Atk95c]. The presence of these security mechanisms in the Internet Protocol does not, by itself, ensure good security. The establishment and maintenance of cryptographic keys and related security information, also known as key management, is also crucial to effective security. Key management for the Internet Protocol is a subject of much experimentation and debate [MS95] [AMP96a] [AMP96b] [Orm96]. Furthermore, key management strategies have a history of subtle flaws that are not discovered until after they are published or deployed [NS87]. This paper presents an environment which allows implementations of key management strategies to exist outside the operating system kernel, where they can be implemented, debugged, and updated in a safe environment.
The Internet Protocol suite has gained popularity largely because of its availability in the Berkeley Software Distribution (BSD) versions of the Unix operating system. Even though many commercial operating systems no longer use the BSD networking implementation, they still support BSD abstractions for application programmers, such as the sockets API [LMKQ89]. The sockets interface allows applications in BSD to communicate with other applications, or sometimes, even with the operating system itself. One of the recent developments in BSD was the routing socket [Skl91], which allows a privileged application to alter a node's network routing tables. This abstraction allows a BSD system to use an appropriate routing protocol, without requiring changes inside the kernel. Instead, routing protocols are implemented in user-space daemons, such as routed or gated.
An analogous concept, a key socket, enables placing cryptographic keys inside the operating system for IP or other networking protocols to use. Like routing information, cryptographic keys should be easily and quickly accessible by the network protocol implementation. Also, like routing information, the method of obtaining and creating these cryptographic keys is largely up to the administrator of that machine, and the environment in which the machine exists. The creator of cryptographic keys can be implemented in user-space, without altering the kernel.
Figure 1--Component Interactions
Figure 1 illustrates the interaction between components that comprise the necessary security information, the consumers of that information, and the producers of that information.
Everything to the right of the gray vertical line in Figure 1 comprises a traditional networking implementation. The networking protocols are implemented in the kernel, and applications access those protocols through some sort of API, in this case, BSD-style network sockets.
Left of the vertical gray line of Figure 1 lies what needs to be added for the IP security architecture to be implemented. The IP security architecture [Atk95a] defines a security association. A security association exists between two communication endpoints, and contains information (not exclusively limited to) the cryptographic key for traffic between the two endpoints, what sort of cryptographic algorithm is being used, the lifetime of this association (or of the key being used in this association), and other association-specific attributes, such as a sensitivity label [Ken91]. Security associations are stored inside the kernel, so that the networking protocol implementation can quickly and easily access them. Additionally, public key certificates could also be stored in the kernel using PF_KEY. The remainder of this paper, however will deal with security associations.
Alongside the security associations is the key engine which presents interfaces to both the protocol implementation, and user-level key management programs. The key engine also sends messages to key management applications that need to obtain new or updated security information at the request of the protocol implementation. Additionally, the key engine may perform maintenance on the entries in the security association table, such as deleting associations that are past their expiration times or are no longer in
Aiding the protocol implementation in making decisions about which packets to secure, or which to reject based on the lack of security is a policy engine. The policy engine will interface with the key engine, especially when deciding if a security association is to be used across multiple communications between the same IP endpoints, or if each new communication deserves its own unique security association. This separation of policy from mechanisms in the protocol implementation allows policies to be implemented per system, or even be changed by user-level direction.
While the protocol implementation and the policy engine consume and request security associations, something needs to produce security associations and feed them to the key engine. Key management protocols create and produce such information. The PF_KEY key management socket provides a set of messages that the kernel can use to indicate the need for a new or updated security association, and that key management applications can use to add, remove, or update security associations. Automated key management implementations can send self-authenticated network packets and update associations based on the results of that communication, or system administrators can use programs which add, delete, or update single associations.
User-level key management programs and the kernel communicate key-management information through a socket with the protocol family PF_KEY. PF_KEY supports a series of messages, which can be generated by the kernel or the user-level program, and received by all registered listeners. The messages are as follows:
KEY_ADD - A user-level program sends KEY_ADD messages to the kernel to create a new security association. This new security association contains all of the relevant parameters, as mentioned in the Abstractions section, as well as what networking protocol will use this association.
KEY_DELETE - Like the name suggests, this message from the user-level program to the kernel will delete a security association. Usually, the Security Parameters Index (SPI) [Atk95a], the type of networking protocol which uses the association, and the protocol addresses are used as an index to find the association to be deleted.
KEY_UPDATE - Giving the same parameters as KEY_DELETE, this message instead updates the security association with new values (e.g. key, lifetime).
KEY_GET - Retrieve a security association based on the SPI and other parameters.
KEY_ACQUIRE - Unlike most PF_KEY messages, this message is sent from the kernel to the user-level programs which registered with the KEY_REGISTER message. This is a directive from the kernel to the user-level program to go and obtain a security association for communication between two IP endpoints. For example, a KEY_ACQUIRE message may initiate an authenticated Diffie-Hellman key exchange of some variety.
KEY_GETSPI - This message asks the kernel for a unique value for an SPI. The reason for a separate PF_KEY message is that the SPI may be transmitted as part of the key management actions set in motion by a KEY_ACQUIRE message. Only the kernel has enough information to generate a unique SPI.
KEY_REGISTER - This message differentiates programs that write messages (such as a manual security association program) from programs that should receive KEY_ACQUIRE messages. Any program that needs to receive KEY_ACQUIRE messages from the kernel should send a KEY_REGISTER message immediately upon execution. A type can be passed in with KEY_ACQUIRE messages so that only certain classes of KEY_ACQUIRE message are passed to the application. This allows different key management strategies for different network protocols (IP, IPv6, etc.).
KEY_EXPIRE - If the key engine is performing maintenance on security associations, it may use this message to indicate that a security association has somehow expired, and that perhaps another negotiation similar to what KEY_ACQUIRE initiates.
KEY_DUMP - If a diagnostic program requires a complete list of the current security association table, it issues this message to the kernel. The kernel sends back KEY_DUMP messages containing the security association entries. Early implementation experience has shown that, because of socket buffering limitations, this message may not be the optimal way to access the entire contents of the security association table.
KEY_FLUSH - If a situation requires rapid removal of all security associations (such as a system compromise or system failure), this message may be sent, either by user programs, or by the kernel itself in its failure code.
Applications will not necessarily use all of the PF_KEY messages, though they provide a set of abstractions needed to implement key management in user-space, while allowing the actual encryption or authentication of packets inside the kernel.
The key engine supports two function calls made by either the protocol implementation on arriving packets, or by the network security policy engine on departing packets.
The first call, getassocbyspi(), is made by the networking protocol implementation itself. When an incoming packet contains either Encapsulating Security Payload (ESP) or Authentication Header (AH) as its payload, the protocol implementation extracts the SPI from the ESP or AH header. This SPI is the argument to getassocbyspi(), which should return the required information to either decrypt or authenticate the packet. Getassocbyspi() should return a security association because the association should be present either after manual configuration, or after some sort of key exchange has taken place. In the event getassocbyspi() fails, the incoming packet should be dropped. After the networking protocol implementation authenticates or decrypts the packet, the packet is marked as (not) authenticated or (not) decrypted, so policy decisions can be made closer to when the data is delivered to the application.
On outgoing packets, the policy engine makes decisions regarding what needs to be done to the packet. The policy engine enforces what the system requires for security, as well as trying to accommodate any application-directed security requests. These decisions include whether the security association(s) used can be shared across other communications, or whether they should be unique to this one, and possibly what, if any, sensitivity label is needed. With this information, the policy engine calls getassocbysocket(), which returns a security association used to encrypt or authenticate the outgoing packet. The "by socket" part of the function name refers to the fact that the security association may be unique to this particular instance of communication (which in BSD is the socket). The actual process of authenticating or encrypting will probably not happen until the packet is ready to be passed to the network device driver, but the security association will be already allocated when that happens.
Getassocbysocket() is where KEY_ACQUIRE messages may be sent up to key management applications, if no key is available, and if a key management daemon has registered using the KEY_REGISTER message, getassocbysocket() may return an indicator to its caller that packets requiring this particular security association should be queued up and retried after a certain amount of time, or dropped. Which is done is primarily a function of implementation, but either is acceptable in an unreliable protocol such as IP.
It is possible for the key engine to perform maintenance tasks on security associations. These tasks are largely orthogonal to the interfaces presented above, but the KEY_EXPIRE and KEY_ACQUIRE messages can be used to aid the internal maintenance of the security association table. A common internal maintenance function is to age and possibly remove security associations that have exceeded their lifetimes.
Many classes of applications can use the PF_KEY socket to either perform, or enhance their tasks. The two primary tasks, manual or automated key management, will be illustrated below. Other applications that could use the PF_KEY socket include system monitoring applications, which would track the progress of KEY_ACQUIRE requests as they came from the kernel, and security auditing programs, which could sample random associations for sufficient key strength, or send KEY_FLUSH commands if a situation warranted such action.
Figure 2--Manual Key Management
Figure 2 illustrates a simple manual key management program. In essence, a manual key management program is nothing more than a user interface to the PF_KEY messages. A manual key management program should only be executable by privileged users, but apart from that, the construction of such a program should only be a problem of converting user input into PF_KEY messages.
Figure 3--Automated Key Management
Figure 3 illustrates a more complex setup, where an automated key management application is in place. Under automated key management systems [MS95] [AMP96a] [AMP96b], network communication needs to take place. This network communication cannot have a network security policy enforced on it, because it would lead to a bootstrapping problem. All other communications have the same policy enforced on them, and may cause the key engine to send KEY_ACQUIRE messages up to any listening PF_KEY sockets.
The automated key management application will, upon startup, issue a KEY_REGISTER message to the kernel, so that the kernel is aware that automated key management services are available.
If the key engine is performing maintenance on security associations, it may send up KEY_EXPIRE messages to the key management application just before a security association (or part of it) expires. The application can then either extend the lifetime, delete the association, or update it with cached information or information obtained on another network communication.
Presented here is an API and surrounding infrastructure to allow modular and relatively easy implementation of key management strategies. It uses concepts and abstractions introduced in various works [LMKQ86] [Skl91] [Atk95a] and ties them together so that good abstractions to both key management strategies and networking protocol implementation.
A sample implementation of PF_KEY is available in the NRL IPv6/IPsec distribution. The distribution can be obtained by U. S. citizens at ftp://ftp.c2.org or by anyone at ftp://ftp.ripe.net/.
1 Work on this paper was done while the authors were at the U. S. Naval Research Laboratory. Daniel L. McDonald is now at Sun Microsystems, and Randall J. Atkinson is now at Cisco Systems.
2 The term endpoint is perhaps too strong, as a security association can exist without a defined source, so that a multicast security association can exist.
[Atk95a] Atkinson, R., "Security Architecture for the Internet Protocol," RFC 1825, August, 1995.
[Atk95b] Atkinson, R., "IP Authentication Header," RFC 1826, August, 1995.
[Atk95c] Atkinson, R., "IP Encapsulating Security Payload," RFC 1827, August, 1995.
[AMP96a] Aziz, A., Markson, T., and Prafullchandra, H., "Simple Key-Management for Internet Protocols (SKIP)," work in progress.
[AMP96b] Aziz, A., Markson, T., and Prafullchandra, H., "Certificate Discovery Protocol," work in progress.
[Ken91] Kent, S., "U. S. Department of Defense Security Options for the Internet Protocol," RFC 1108, November, 1991.
[LMKQ89] Leffler, S. J., McKusick, M. K., Karels, M. J., and Quarterman, J. S., The Design and Implementation of the 4.3BSD Unix Operating System. Addison-Wesley, Reading, Mass., 1989.
[MS95] Maughan, D. and Schertler, M., "Internet Security Association and Key Management Protocol (ISAKMP)," work in progress.
[NS87] Needham, R. M. and Schroeder, M. D., "Authentication Revisited," Operating Systems Review, vol. 21, num. 1, 1987 p. 7.
[Orm96] Orman, H. K., "The Oakley Key Determination Protocol," work in progress.
[Skl91] Sklower, K., "A Tree-Based Packet
Routing Table for Berkeley Unix," Proceedings of the 1991
Winter USENIX Conference, pp. 93-99.