Network Working Group | A. Bittau |
Internet-Draft | |
Intended status: Informational | D. Boneh |
Expires: April 2, 2018 | D. Giffin |
Stanford University | |
M. Handley | |
University College London | |
D. Mazieres | |
Stanford University | |
E. Smith | |
Kestrel Institute | |
September 29, 2017 |
Interface Extensions for TCP-ENO and tcpcrypt
draft-ietf-tcpinc-api-05
TCP-ENO and tcpcrypt perform encryption at the transport layer. They also define a few parameters that are intended to be used or configured by applications. This document specifies operating system interfaces for access to these parameters. We describe the interfaces in terms of socket options, the de facto standard API for adjusting per-connection behavior in TCP/IP, and sysctl, a popular mechanism for setting global defaults. Operating systems that lack socket or sysctl functionality can implement similar interfaces in their native frameworks, but should ideally adapt their interfaces from those presented in this document.
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."
This Internet-Draft will expire on April 2, 2018.
Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.
The TCP Encryption Negotiation Option (TCP-ENO) [I-D.ietf-tcpinc-tcpeno] permits hosts to negotiate encryption of a TCP connection. One of TCP-ENO's use cases is to encrypt traffic transparently, unbeknownst to legacy applications. Transparent encryption requires no changes to existing APIs. However, other use cases require applications to interact with TCP-ENO. In particular:
The tcpcrypt protocol [I-D.ietf-tcpinc-tcpcrypt] may be negotiated via TCP-ENO, and can operate without configuration. But users may wish to control a few operational details of the protocol:
The remainder of this document describes APIs through which systems can meet the above needs. The API extensions relate back to quantities defined by TCP-ENO and tcpcrypt.
This section describes an API for per-connection options, followed by a discussion of system-wide configuration options.
Table 1 summarizes a set of options that TCP-ENO implementations should provide on a per-socket basis. For each option, the table lists whether it is read-only (R) or read-write (RW), as well as the type of the option's value. Read-write options, when read, always return the previously successfully written value or the default if they have not been written. Options of type bytes consist of a variable-length array of bytes, while options of type int consist of a small integer with the exact range indicated in parentheses. We discuss each option in more detail below.
Option name | RW | Type |
---|---|---|
TCP_ENO_ENABLED | RW | int (-1, 0, or 1) |
TCP_ENO_SESSID | R | bytes |
TCP_ENO_NEGTEP | R | int (32-127, 160-255) |
TCP_ENO_TEPS | RW | bytes |
TCP_ENO_SELF_GOPT | RW | int (0-31) |
TCP_ENO_PEER_GOPT | R | int (0-31) |
TCP_ENO_AA_MANDATORY | RW | int (0 or 1) |
TCP_ENO_TEP_MANDATORY | RW | int (0 or 1) |
TCP_ENO_ROLE | R | int (0 or 1) |
TCP_ENO_SELF_NAME | R | bytes |
TCP_ENO_PEER_NAME | R | bytes |
TCP_ENO_RAW | RW | bytes |
TCP_ENO_TRANSCRIPT | R | bytes |
The socket options must return errors under certain circumstances. These errors are mapped to three suggested error codes shown in Table 2. Systems based on sockets already have constants for these errors. Non-socket systems should use error codes corresponding to the same conditions. EINVAL is the existing error returned when attempting to set options or otherwise operate on a socket that has been shut down or is otherwise no longer valid. EISCONN corresponds to calling connect a second time, while ENOTCONN corresponds to requesting the peer address of an unconnected socket.
Symbol | Description |
---|---|
EINVAL | General error signifying bad parameters |
EISCONN | Option no longer valid because connection established |
ENOTCONN | Option not (yet) valid because no connection established |
With ENO, a connection can be in one of three high-level states: negotiating or ready to negotiate encryption, encrypting, or disabled. Unless otherwise specified, all of the read-only options (R) succeed only when a connection is in the encrypting state. Specifically, attempts to read options should return ENOTCONN while the connection is in the negotiating state and EINVAL if ENO is disabled.
In addition to these per-socket options, implementations should use a system-wide configuration mechanism to allow administrators to configure a default value for TCP_ENO_TEPS, as well as default behavior for when TCP_ENO_ENABLED is -1. These defaults can be truly system-wide, or else scoped to a network namespace on systems that provide network namespaces.
Table 3 provides a table of suggested parameters. The type words corresponds to a list of 16-bit unsigned words representing TCP port numbers (similar to the baddynamic sysctls that, on some operating systems, blacklist automatic assignment of particular port numbers).
Name | Type |
---|---|
eno_teps | bytes |
eno_enable_connect | int (0 - 1) |
eno_enable_listen | int (0 - 1) |
eno_bad_connect_ports | words |
eno_bad_listen_ports | words |
eno_teps is simply a string of bytes; it provides the default value for the TCP_ENO_TEPS socket option. If TCP_ENO_TEPS is non-empty, the remaining sysctls determine whether to attempt TCP-ENO negotiation when the TCP_ENO_ENABLED option is -1 (the default), using the following rules.
Because initial deployment may run into issues with middleboxes or incur slowdown for unnecessary double-encryption, sites may wish to blacklist particular ports. For example setting eno_bad_connect_ports to 443,993 would disable ENO encryption on outgoing connections to ports 443 and 993 (which use application-layer encryption for HTTP and IMAP, respectively). If the per-socket TCP_ENO_ENABLED is not -1, it overrides the sysctl values.
Similarly, on a server, setting eno_bad_listen_ports to 443 makes it possible to disable TCP-ENO for incoming HTTPS connection without modifying the web server to set TCP_ENO_ENABLED to 0.
This section recommends further extensions to the API set forth in Section 2 that are specific to the tcpcrypt TEP. Future TEPs may similarly provide TEP-specific options.
Option name | RW | Type |
---|---|---|
TCP_CRYPT_CONF | R | int (0-255) |
TCP_CRYPT_CACHE_FLUSH | W | int (1) |
TCP_CRYPT_ACONF | RW | bytes |
TCP_CRYPT_BCONF | RW | bytes |
Table 4 summarizes the proposed tcpcrypt-specific per-connection options.
Name | Type |
---|---|
crypt_aconf | bytes |
crypt_bconf | bytes |
System administrators should also be able to set defaults for the per-socket connection parameters. Table 5 lists the system-wide parameters for doing so, which can exist alongside the system-wide ENO parameters described in Table 3.
The previous sections presented abstract APIs for per-connection and global options. One implementation strategy would be to map these APIs to existing per-socket and global configuration mechanisms. By way of example, this section describes a way to map the per-connection settings to BSD socket options and the global configuration settings to the Unix sysctl interface.
Systems with sockets can allow applications to configure TCP-ENO through the same mechanism they use for other TCP connection configuration such as TCP_NODELAY [RFC0896], namely the getsockopt and setsockopt system calls shown in Figure 1.
int getsockopt(int socket, int level, int option_name, void *option_value, socklen_t *option_len); int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);
Figure 1: Socket option API
Socket-based TCP-ENO implementations can define a set of new option_name values accessible at level IPPROTO_TCP (generally defined as 6, to match the IP protocol field), where each entry in Table 1 corresponds to a unique option_name constant.
User-level implementations of TCP-ENO can use a configuration file to set global options. However, such an approach may be awkward for kernel-based implementations. Instead, kernel-level implementations can use the sysctl configuration tool. With this approach, TCP-ENO parameters should be placed alongside most TCP parameters. For example, on BSD derived systems a suitable name would be net.inet.tcp.eno.teps, while on Linux a more appropriate name would be net.ipv4.tcp_eno_teps.
This section provides examples of how applications might authenticate session IDs. Authentication requires exchanging messages over the TCP connection, and hence is not backwards compatible with existing application protocols. To fall back to opportunistic encryption in the event that both applications have not been updated to authenticate the session ID, TCP-ENO provides the application-aware bit. To signal it has been upgraded to support application-level authentication, an application should set the second-least significant bit of TCP_ENO_SELF_GOPT before opening a connection. An application should then check that TCP_ENO_PEER_GOPT has this bit set before attempting to send authenticators that would otherwise be misinterpreted as application data.
In cookie-based authentication, a client and server both share a cryptographically strong random or pseudo-random secret known as a "cookie". Such a cookie is preferably at least 128 bits long. To authenticate a session ID using a cookie, each host computes and sends the following value to the other side:
authenticator = PRF(cookie, local-name)
Here PRF is a pseudo-random function such as HMAC-SHA-256 [RFC6234]. local-name is the result of the TCP_ENO_LOCAL_NAME socket option. Each side must verify that the other side's authenticator is correct. To do so, software obtains the remote host's name via the TCP_ENO_PEER_NAME socket option. Assuming the authenticators are correct, applications can rely on the TCP-layer encryption for resistance against active network attackers.
Note that if the same cookie is used in other contexts besides session ID authentication, appropriate domain separation must be employed, such as prefixing local-name with a unique prefix to ensure authenticator cannot be used out of context.
In signature-based authentication, one or both endpoints of a connection possess a private signature key the public half of which is known to or verifiable by the other endpoint. To authenticate itself, the host with a private key computes the following signature:
authenticator = Sign(PrivKey, local-name)
The other end verifies this value using the corresponding public key. Whichever side validates an authenticator in this way knows that the other side belongs to a host that possesses the appropriate signature key.
Once again, if the same signature key is used in other contexts besides session ID authentication, appropriate domain separation should be employed, such as prefixing local-name with a unique prefix to ensure authenticator cannot be used out of context.
The TCP-ENO specification [I-D.ietf-tcpinc-tcpeno] discusses several important security considerations that this document incorporates by reference. The most important one, which bears reiterating, is that until and unless a session ID has been authenticated, TCP-ENO is vulnerable to an active network attacker, through either a downgrade or active man-in-the-middle attack.
Because of this vulnerability to active network attackers, it is critical that implementations return appropriate errors as suggested in this document for socket options when TCP-ENO is not enabled. An example of an API design with potentially catastrophic consequences would be to attempt to communicate TCP-ENO failure by successfully returning a zero-length or zero-valued session ID. Equally critical is that applications must never use these socket options without checking for errors.
Applications with high security requirements that rely on TCP-ENO for security must either fail or fall back to application-layer encryption if TCP-ENO fails or session ID authentication fails.
We are grateful for contributions, help, discussions, and feedback from the TCPINC working group, including Marcelo Bagnulo, David Black, Bob Briscoe, Jana Iyengar, Tero Kivinen, Mirja Kuhlewind, Yoav Nir, Christoph Paasch, Eric Rescorla, Kyle Rose, and Joe Touch. This work was partially funded by DARPA CRASH and the Stanford Secure Internet of Things Project.
[I-D.ietf-tcpinc-tcpcrypt] | Bittau, A., Giffin, D., Handley, M., Mazieres, D., Slack, Q. and E. Smith, "Cryptographic protection of TCP Streams (tcpcrypt)", Internet-Draft draft-ietf-tcpinc-tcpcrypt-06, March 2017. |
[I-D.ietf-tcpinc-tcpeno] | Bittau, A., Giffin, D., Handley, M., Mazieres, D. and E. Smith, "TCP-ENO: Encryption Negotiation Option", Internet-Draft draft-ietf-tcpinc-tcpeno-09, August 2017. |
[RFC0896] | Nagle, J., "Congestion Control in IP/TCP Internetworks", RFC 896, DOI 10.17487/RFC0896, January 1984. |
[RFC6234] | Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011. |