Re: TLS ALPN Proposal v2
I've just noticed the SSLParameters.setUseCipherSuitesOrder() method. I guess this can be used to enforce a higher priority for the h2 compatible ciphers on the server side. On the new API, I'm not sure about the SSLBase, SSLFunction construct either. I don't think it is very clear, and if its purpose is just to allow use of lambdas, then I think the original approach was better. Michael. On 05/06/15 05:11, Xuelei Fan wrote: Hi, See inlines, please. On 6/5/2015 5:30 AM, Simone Bordet wrote: Hi, On Thu, Jun 4, 2015 at 6:50 PM, Xuelei Fan xuelei@oracle.com wrote: Hm, I see your point now. But I may not agree with your ALPN MUST happen after protocol/cipher suite negotiation conclusion. I parse this section as, a H2 server must be strong enough(comply to RFC7540), and a H2 client must also be strong enough (comply to RFC7540). Otherwise, both side may terminated the connection, and cannot declare as complying to H2. It is not necessary for an application protocol selector to detect whether a H2 server/client comply to H2 or not. If H2 is requested, it means that the client supports H2. Otherwise, it's a client application bug. Not that simple, see below. If H2 is selected by a selected, it means that the selected server supports H2. Otherwise, it is a selector implementation bug. If something wrong in either client or server, it is expected to terminate the connection immediately, rather than downgrade to a not-strong enough level. From the points above, I think an application protocol selector may not need to know the negotiated protocol version and cipher suite. No. The client may send ciphers that are valid for http/1.1 (but invalid for h2), along with ciphers that are good for h2 (as well as http/1.1 of course), plus the list of protocols it supports. The client has no idea what the server supports. I think it should be true that if a client requests h2, the client MUST support H2 and the requested cipher suites MUST contains at least one H2 required cipher suite. Otherwise, it's bug in client side. When the server sees that the client supports h2, it MUST pick a cipher that is valid for h2. Alternatively, the ciphers on the server are sorted so that those valid for h2 have higher priority (they are attempted before all the others), so that there is a high chance that a h2 valid cipher is chosen (but no guarantee) before choosing the application protocol. When the application protocol selector callback is invoked, it can only pick h2 IFF the cipher is h2 valid, otherwise it has to fallback to http/1.1. I think it should be true that if a server can negotiate h2, the server MUST support H2 and the enabled cipher suites MUST contains at least one H2 required cipher suite. Otherwise, it's bug in server side. It's instinctive that if a server support h2, and then the application protocol selector would select h2. If the server declare to support h2, but no suitable cipher suites, it may be a server bug. The connection should be terminated rather than downgrade to HTTP/1.1, I think. Is it possible that client only request h2_valid_cipher_a, but server only support h2_valid_cipher_b, and as would result in that there is no common cipher suites between client and server for H2? It is possible, surely. Should the connection be terminated, or fall-back to HTTP/1.1? I think connection should be terminated immediately, rather than fall-back to HTTP/1.1. Per page 68, section 9.2.2, RFC 7540, there is an mandatory cipher suite (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) MUST be supported in both client and server. If there is no common cipher suites between client and server for H2, it is actually a bad deployments, and the connection should be terminated rather than fall-back to HTTP/1.1. Version downgrading is not a safe behavior, I think. With your reasoning, the client can send [h2_invalid_cipher, h2_valid_cipher], the server may pick h2_invalid_cipher, then the application protocol selector is invoked, which will only look at the protocols, pick h2 since it's supported by client and server, and now you have an invalid connection: the h2 protocol with h2_invalid_cipher. That's an interesting case. The question actually is: between requested application protocols and cipher suites, which preference should be respected at first. Because it is a application requirement that a certain cipher suite is not suitable to H2, I think requested application protocols should be respected at first. My scenarios look like: 1. client sends [h2_invalid_cipher, h2_valid_cipher] and h2/http/1.1 application protocol. 2. server selects h2 (we need an API for the selection). 3. server selects h2_valid_cipher because of h2 is selected previously (may need an API for the selection). In #1, if there is no h2_valid_cipher requested, it is a bug in client side. In #3, if there is no h2_valid_cipher that can be negotiated, it is a bug in server side, or the client does not enabled the
Re: TLS ALPN Proposal v2
See more inlines, please. Please help on one question I'm not sure of. Per HTTP/2 specification, Does H2 server allow fallback to HTTP/1.1 if client requests a HTTP/2 connection? I did not find the answer from RFC 7540. In TLS, if client requests to negotiate TLS v1.2, and server supports TLS 1.2, it is not allowed to fallback to TLS v1.1. If there is not suitable cipher suite to negotiate TLS 1.2, the connection would be terminated immediately. I'm not sure what's the spec for HTTP/2, HTTP/1.1 and HTTP/1.0. On 6/5/2015 4:05 PM, Simone Bordet wrote: Hi, On Fri, Jun 5, 2015 at 6:11 AM, Xuelei Fan xuelei@oracle.com wrote: I think it should be true that if a server can negotiate h2, the server MUST support H2 and the enabled cipher suites MUST contains at least one H2 required cipher suite. Otherwise, it's bug in server side. It's instinctive that if a server support h2, and then the application protocol selector would select h2. If the server declare to support h2, but no suitable cipher suites, it may be a server bug. The connection should be terminated rather than downgrade to HTTP/1.1, I think. The server may support h2, but there is no valid h2 cipher in common with the client, so it's not a server bug. Per RFC 7540, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 is a mandatory cipher suite for H2. The case is not expected that there is no cipher in common. It's a fatal error if there is no cipher in common. In that case, client and server cannot speak h2, but nothing forbids them to speak http/1.1. It would be really bad for the user experience if both client and server could speak http/1.1, but they don't just because they can't speak h2. They would appear like spoiled children :) The point of ALPN is to *negotiate* a protocol, not to give up on the first failure. I cannot agree, ALPN is not a mechanism to tolerant incorrect protocol implementation. If H2 is bad implemented or bad deployed, terminate the connection, rather than fallback to HTTP/1.1 is a better and safer user experience. Is it possible that client only request h2_valid_cipher_a, but server only support h2_valid_cipher_b, and as would result in that there is no common cipher suites between client and server for H2? It is possible, surely. Should the connection be terminated, or fall-back to HTTP/1.1? I think connection should be terminated immediately, rather than fall-back to HTTP/1.1. Per page 68, section 9.2.2, RFC 7540, there is an mandatory cipher suite (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) MUST be supported in both client and server. If there is no common cipher suites between client and server for H2, it is actually a bad deployments, and the connection should be terminated rather than fall-back to HTTP/1.1. Version downgrading is not a safe behavior, I think. That is not what the 7540 expert group thinks, certainly not what browsers do, and certainly not what servers do. The behavior is to speak http/1.1 (or the next protocol that fits). Hm, that what I want to know. Do you mean that RFC 7540 expect a H2 server fall-back to HTTP/1.1 from HTTP/2 request? See also my question in the beginning. Per my understanding, if server does not support H2, downgrade to use HTTP/1.1 is allowed. But if the server supports H2, is it still allowed to use HTTP/1.1? That may be the key for our discussion. That's an interesting case. The question actually is: between requested application protocols and cipher suites, which preference should be respected at first. Because it is a application requirement that a certain cipher suite is not suitable to H2, I think requested application protocols should be respected at first. My scenarios look like: 1. client sends [h2_invalid_cipher, h2_valid_cipher] and h2/http/1.1 application protocol. 2. server selects h2 (we need an API for the selection). 3. server selects h2_valid_cipher because of h2 is selected previously (may need an API for the selection). Does not work. How do you know that server has h2_valid_cipher available ? If it does not, you have picked h2, and an invalid cipher (breaks 7540), or you terminate the connection while instead you could speak http/1.1. TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 is a mandatory cipher suite for H2. Per RFC 7540, ... To avoid this problem causing TLS handshake failures, deployments of HTTP/2 that use TLS 1.2 MUST support TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] with the P-256 elliptic curve In #1, if there is no h2_valid_cipher requested, it is a bug in client side. In #3, if there is no h2_valid_cipher that can be negotiated, it is a bug in server side, or the client does not enabled the mandatory cipher suite (a bug in client). Does not work. The client may be using TLS 1.4, where that mandatory cipher suite (it's mandatory only for TLS 1.2 deployments) has been removed because insecure. There is no bug on either side, just no cipher in
Re: TLS ALPN Proposal v2
Hi, On Fri, Jun 5, 2015 at 2:36 PM, Xuelei Fan xuelei@oracle.com wrote: See more inlines, please. Please help on one question I'm not sure of. Per HTTP/2 specification, Does H2 server allow fallback to HTTP/1.1 if client requests a HTTP/2 connection? I did not find the answer from RFC 7540. Yes. The intended behavior is exactly to fall back to http/1.1 if h2 cannot be negotiated. This is implicitly explained in the ALPN spec, RFC 7301, see http://tools.ietf.org/html/rfc7301#section-3.2. In TLS, if client requests to negotiate TLS v1.2, and server supports TLS 1.2, it is not allowed to fallback to TLS v1.1. If there is not suitable cipher suite to negotiate TLS 1.2, the connection would be terminated immediately. I'm not sure what's the spec for HTTP/2, HTTP/1.1 and HTTP/1.0. HTTP/2 does not behave like TLS in this sense. ALPN is for *application* protocol selection. A client can send: [h2, spdy/3.1, http/1.1] Failing h2, spdy/3.1 is attempted, which is a completely different protocol, with different restrictions, etc. Per RFC 7540, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 is a mandatory cipher suite for H2. No. It's a mandatory cipher for *TLS 1.2 deployments only*. If the client uses TLS 1.4 does not have to have that cipher, and hence there can be an empty intersection of ciphers with the server. That cipher is only mentioned because all the mandatory TLS 1.2 ciphers have been blacklisted by HTTP/2. If TLS 1.3 was specified before HTTP/2, that cipher would not even be mentioned, and the HTTP/2 spec would have referenced only TLS 1.3 as mandatory: no black lists, no special cipher. The TLS and HTTP specifications will evolve independently, and there cannot be a requirement that whenever TLS changes, an update to HTTP/2 must be published. Hope this clarifies. Thanks ! -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
On 6/5/2015 11:16 PM, Simone Bordet wrote: Hi, On Fri, Jun 5, 2015 at 4:46 PM, Xuelei Fan xuelei@oracle.com wrote: If H2 is not supported, SPDY/3.1 would be attempted, of SPDY/3.1 is not supported HTTP/1.1 would be attempted. Correct. If H2 is supported in both side, but H2 does not work, it is a H2 problem that need to be addressed in H2 layer. If both client and server have h2 as a potentially supported protocol, but the cipher to use h2 is not valid, then h2 is not supported for that particular connection. At that point, like you said above, spdy/3.1 is attempted, and so on. ;-) That's the point we cannot agree with each other at present. No application protocol fallback in TLS layer if the application protocol is supported. Your interpretation of supported is not what browser and server implementors mean :) ;-) maybe. It's not my expertise. I understand your concerns now. I think we have different understanding of the ALPN protocols. It's a good thing to understand the actually requirements of the industry, I think. Thank you! So where does this leave us know ? ;-) I think Brad would consider our information for his design. By the way, while I have participated in the RFC 7540 discussions, and implemented HTTP/2 in Jetty to be interoperable with a variety of other clients and servers, feel free to ask clarifications to the RFC 7540 and RFC 7301 mailing lists, or even directly to the editors of those RFCs; they are typically open to answer questions, I guess especially so if they come from the OpenJDK team that is implementing those specification. Yes. It would be help to know the implementation of other SSL/TLS vendors, too. Thanks, Xuelei
Re: TLS ALPN Proposal v2
Hi, On Fri, Jun 5, 2015 at 4:46 PM, Xuelei Fan xuelei@oracle.com wrote: If H2 is not supported, SPDY/3.1 would be attempted, of SPDY/3.1 is not supported HTTP/1.1 would be attempted. Correct. If H2 is supported in both side, but H2 does not work, it is a H2 problem that need to be addressed in H2 layer. If both client and server have h2 as a potentially supported protocol, but the cipher to use h2 is not valid, then h2 is not supported for that particular connection. At that point, like you said above, spdy/3.1 is attempted, and so on. No application protocol fallback in TLS layer if the application protocol is supported. Your interpretation of supported is not what browser and server implementors mean :) I understand your concerns now. I think we have different understanding of the ALPN protocols. It's a good thing to understand the actually requirements of the industry, I think. Thank you! So where does this leave us know ? By the way, while I have participated in the RFC 7540 discussions, and implemented HTTP/2 in Jetty to be interoperable with a variety of other clients and servers, feel free to ask clarifications to the RFC 7540 and RFC 7301 mailing lists, or even directly to the editors of those RFCs; they are typically open to answer questions, I guess especially so if they come from the OpenJDK team that is implementing those specification. Thanks ! -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
On 6/5/2015 10:11 PM, Simone Bordet wrote: On Fri, Jun 5, 2015 at 2:36 PM, Xuelei Fan xuelei@oracle.com wrote: See more inlines, please. Please help on one question I'm not sure of. Per HTTP/2 specification, Does H2 server allow fallback to HTTP/1.1 if client requests a HTTP/2 connection? I did not find the answer from RFC 7540. Yes. The intended behavior is exactly to fall back to http/1.1 if h2 cannot be negotiated. This is implicitly explained in the ALPN spec, RFC 7301, see http://tools.ietf.org/html/rfc7301#section-3.2. This section says: It is expected that a server will have a list of protocols that it supports, in preference order, and will only select a protocol if the client supports it. I may have different understanding. If server support H2, H2 should be used. No fallback is expected. Support does not means the protocol must work in any cases. Fallback to use HTTP/1.1 should be a spec of HTTP/2, rather than TLS protocols. I would like to see an evidence in HTTP/2 spec that H2 server allow fallback to HTTP/1.1. In TLS, if client requests to negotiate TLS v1.2, and server supports TLS 1.2, it is not allowed to fallback to TLS v1.1. If there is not suitable cipher suite to negotiate TLS 1.2, the connection would be terminated immediately. I'm not sure what's the spec for HTTP/2, HTTP/1.1 and HTTP/1.0. HTTP/2 does not behave like TLS in this sense. ALPN is for *application* protocol selection. A client can send: [h2, spdy/3.1, http/1.1] Failing h2, spdy/3.1 is attempted, which is a completely different protocol, with different restrictions, etc. Failing is confusing. Support does not means the protocol must work in any cases. But failing means that. I would use support for the description as what RFC 7301 does. If H2 is not supported, SPDY/3.1 would be attempted, of SPDY/3.1 is not supported HTTP/1.1 would be attempted. If H2 is supported in both side, but H2 does not work, it is a H2 problem that need to be addressed in H2 layer. No application protocol fallback in TLS layer if the application protocol is supported. I understand your concerns now. I think we have different understanding of the ALPN protocols. It's a good thing to understand the actually requirements of the industry, I think. Thank you! Xuelei
Re: TLS ALPN Proposal v2
On 6/2/2015 11:23 PM, Xuelei Fan wrote: src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java = ListString getReceivedApplicationProtocols() -- C1. It might be useful to know the client requested application protocols in some circumstance. Better to set the application protocols in client side either. For ALPN, the client supplies the list, the server chooses. For NPN, the server supplies the list, the client chooses. So it's a list of received (requested) protocols. I've changed it for now, not a big deal to me. I'd like to use: - * Gets the application protocol value(s) received from the peer - * for this connection. + * Gets a {@link List} of requested application protocol value(s) + * for this connection. I've never seen a link inside an opening sentence. I have seen @code, but there's only 6 in the entire java namespace. The -public ListString getReceivedApplicationProtocols() { +public ListString getRequesedApplicationProtocols() { I'll assume that was supposed to be requested. :) C2. The return value would better to be immutable, and better to describe the preference per RFC 7301. Maybe looks like: -* @return the non-null list of application protocol names +* @return the non-null immutable list of application protocol +* names, in descending order of preference. The returned +* list may be empty if no application protocols were +* requested. Done. src/java.base/share/classes/javax/net/ssl/SSLParameters.java ListString getApplicationProtocols() -- C3. Better to indicate explicitly that this method only apply to client mode. See above. C4. The method description is not instinctive enough for an application developer. Can we use words to indicate the purpose of the setting? For example: - * Gets the list of application-level protocol names that could - * be sent to the SSL/TLS peer. + * Gets the {@link List} of application layer protocol names that + * can be negotiated over SSL/TLS/DTLS protocols. Changed, except for the @link. C5. Prefer to use immutable return value: - * @return a non-null list of application protocol names. + * @return a non-null immutable list of application protocol names. Changed. C6. Nice to have a link for the standard protocol names. I wasn't planning on having a list of standard protocol names. See below. void setApplicationProtocols(ListString protocols) C7. see C3. C8. see C4. Changed. s/getApplicationProtocolSelector() -- C9. The use of SSLFunctionSSLBase, String make the implementation of protocol selector and JSSE provider implementation complicated. From the spec, looks like the selector may want to know address/ports, SSL protocol versions or the negotiated cipher suit. As would require that before use this selector, the handshaking must negotiate the protocol version and the cipher suite. That's a specific JSSE implementation requirement. It does not sound like a reasonable behavior. The implement of the selector is not straightforward, I think. Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. And the connection may be rerouted (even to different machines) for further operation. The requested application protocols list should be the only information for the selection of a suitable application protocol. Based on that, I think it is more simple to use Simone's proposal: @FunctionalInterface interface ApplicationProtocolSelector { String select(ListString protocols) throws SSLException; } Hence, no need for a SSLBase any more. There's been a lot of discussion this morning, I'll return to this later when I've had a chance to parse it. public static final String AP_HTTP_1_1 = http/1.1; public static final String AP_H2 = h2; C10. I understand why the constants are defined here. However, usually, we don't define standard names in JSSE APIs. Instead, we normally use Oracle standard names documentation. This is not really a
Re: TLS ALPN Proposal v2
On 6/5/2015 8:37 AM, Bradford Wetmore wrote: I'd like to use: - * Gets the application protocol value(s) received from the peer - * for this connection. + * Gets a {@link List} of requested application protocol value(s) + * for this connection. I've never seen a link inside an opening sentence. I have seen @code, but there's only 6 in the entire java namespace. Better to use @code. Xuelei
Re: TLS ALPN Proposal v2
Hi, See inlines, please. On 6/5/2015 5:30 AM, Simone Bordet wrote: Hi, On Thu, Jun 4, 2015 at 6:50 PM, Xuelei Fan xuelei@oracle.com wrote: Hm, I see your point now. But I may not agree with your ALPN MUST happen after protocol/cipher suite negotiation conclusion. I parse this section as, a H2 server must be strong enough(comply to RFC7540), and a H2 client must also be strong enough (comply to RFC7540). Otherwise, both side may terminated the connection, and cannot declare as complying to H2. It is not necessary for an application protocol selector to detect whether a H2 server/client comply to H2 or not. If H2 is requested, it means that the client supports H2. Otherwise, it's a client application bug. Not that simple, see below. If H2 is selected by a selected, it means that the selected server supports H2. Otherwise, it is a selector implementation bug. If something wrong in either client or server, it is expected to terminate the connection immediately, rather than downgrade to a not-strong enough level. From the points above, I think an application protocol selector may not need to know the negotiated protocol version and cipher suite. No. The client may send ciphers that are valid for http/1.1 (but invalid for h2), along with ciphers that are good for h2 (as well as http/1.1 of course), plus the list of protocols it supports. The client has no idea what the server supports. I think it should be true that if a client requests h2, the client MUST support H2 and the requested cipher suites MUST contains at least one H2 required cipher suite. Otherwise, it's bug in client side. When the server sees that the client supports h2, it MUST pick a cipher that is valid for h2. Alternatively, the ciphers on the server are sorted so that those valid for h2 have higher priority (they are attempted before all the others), so that there is a high chance that a h2 valid cipher is chosen (but no guarantee) before choosing the application protocol. When the application protocol selector callback is invoked, it can only pick h2 IFF the cipher is h2 valid, otherwise it has to fallback to http/1.1. I think it should be true that if a server can negotiate h2, the server MUST support H2 and the enabled cipher suites MUST contains at least one H2 required cipher suite. Otherwise, it's bug in server side. It's instinctive that if a server support h2, and then the application protocol selector would select h2. If the server declare to support h2, but no suitable cipher suites, it may be a server bug. The connection should be terminated rather than downgrade to HTTP/1.1, I think. Is it possible that client only request h2_valid_cipher_a, but server only support h2_valid_cipher_b, and as would result in that there is no common cipher suites between client and server for H2? It is possible, surely. Should the connection be terminated, or fall-back to HTTP/1.1? I think connection should be terminated immediately, rather than fall-back to HTTP/1.1. Per page 68, section 9.2.2, RFC 7540, there is an mandatory cipher suite (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) MUST be supported in both client and server. If there is no common cipher suites between client and server for H2, it is actually a bad deployments, and the connection should be terminated rather than fall-back to HTTP/1.1. Version downgrading is not a safe behavior, I think. With your reasoning, the client can send [h2_invalid_cipher, h2_valid_cipher], the server may pick h2_invalid_cipher, then the application protocol selector is invoked, which will only look at the protocols, pick h2 since it's supported by client and server, and now you have an invalid connection: the h2 protocol with h2_invalid_cipher. That's an interesting case. The question actually is: between requested application protocols and cipher suites, which preference should be respected at first. Because it is a application requirement that a certain cipher suite is not suitable to H2, I think requested application protocols should be respected at first. My scenarios look like: 1. client sends [h2_invalid_cipher, h2_valid_cipher] and h2/http/1.1 application protocol. 2. server selects h2 (we need an API for the selection). 3. server selects h2_valid_cipher because of h2 is selected previously (may need an API for the selection). In #1, if there is no h2_valid_cipher requested, it is a bug in client side. In #3, if there is no h2_valid_cipher that can be negotiated, it is a bug in server side, or the client does not enabled the mandatory cipher suite (a bug in client). We have been through these issues for months in the RFC 7540 expert group, and the outcome is that protocol selection, for h2, depends on the cipher. We have also been through a number of scenarios where both the client and the server send h2 valid ciphers, but their intersection is empty (this may happen when a very old client talks to a very new
Re: TLS ALPN Proposal v2
Hi, On Thu, Jun 4, 2015 at 6:50 PM, Xuelei Fan xuelei@oracle.com wrote: Hm, I see your point now. But I may not agree with your ALPN MUST happen after protocol/cipher suite negotiation conclusion. I parse this section as, a H2 server must be strong enough(comply to RFC7540), and a H2 client must also be strong enough (comply to RFC7540). Otherwise, both side may terminated the connection, and cannot declare as complying to H2. It is not necessary for an application protocol selector to detect whether a H2 server/client comply to H2 or not. If H2 is requested, it means that the client supports H2. Otherwise, it's a client application bug. Not that simple, see below. If H2 is selected by a selected, it means that the selected server supports H2. Otherwise, it is a selector implementation bug. If something wrong in either client or server, it is expected to terminate the connection immediately, rather than downgrade to a not-strong enough level. From the points above, I think an application protocol selector may not need to know the negotiated protocol version and cipher suite. No. The client may send ciphers that are valid for http/1.1 (but invalid for h2), along with ciphers that are good for h2 (as well as http/1.1 of course), plus the list of protocols it supports. The client has no idea what the server supports. When the server sees that the client supports h2, it MUST pick a cipher that is valid for h2. Alternatively, the ciphers on the server are sorted so that those valid for h2 have higher priority (they are attempted before all the others), so that there is a high chance that a h2 valid cipher is chosen (but no guarantee) before choosing the application protocol. When the application protocol selector callback is invoked, it can only pick h2 IFF the cipher is h2 valid, otherwise it has to fallback to http/1.1. With your reasoning, the client can send [h2_invalid_cipher, h2_valid_cipher], the server may pick h2_invalid_cipher, then the application protocol selector is invoked, which will only look at the protocols, pick h2 since it's supported by client and server, and now you have an invalid connection: the h2 protocol with h2_invalid_cipher. We have been through these issues for months in the RFC 7540 expert group, and the outcome is that protocol selection, for h2, depends on the cipher. We have also been through a number of scenarios where both the client and the server send h2 valid ciphers, but their intersection is empty (this may happen when a very old client talks to a very new server, think TLS 1.2 vs TLS 1.4, or viceversa). Same outcome: to pick h2 you MUST have a h2 valid cipher in common between client and server, so application protocol selection, for h2, depends on the cipher. A bit of warning here: we are designing an API for ALPN, not for HTTP/2. The ALPN API should be flexible enough to implement *at least* HTTP/2, possibly even more complex scenarios (for example alias selection), but IMHO it should not be tied to HTTP/2. Again, I see 2 cases: either the JDK implementation picks the TLS protocol, the cipher and the alias like it does now, and then invokes the callback to pick the application protocol (current Jetty ALPN behavior), or the implementation must be reviewed to perform TLS protocol, cipher, alias and application protocol selection at once, with a callback that will be invoked possibly multiple times until it can find the right tuple to return. The latter would be the optimal solution, the former has certainly working implementations. Hope this clarified. Thanks ! -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
Hi, On Thu, Jun 4, 2015 at 5:53 PM, Xuelei Fan xuelei@oracle.com wrote: On 6/4/2015 8:19 PM, Simone Bordet wrote: This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. Why? Is it a spec of HTTP/2? It is a point I don't understand now. Please help with more details. http://tools.ietf.org/html/rfc7540#section-9.2 You can only speak h2 if the cipher is strong enough as defined by RFC 7540. -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
On 6/5/2015 12:12 AM, Simone Bordet wrote: Hi, On Thu, Jun 4, 2015 at 5:53 PM, Xuelei Fan xuelei@oracle.com wrote: On 6/4/2015 8:19 PM, Simone Bordet wrote: This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. Why? Is it a spec of HTTP/2? It is a point I don't understand now. Please help with more details. http://tools.ietf.org/html/rfc7540#section-9.2 You can only speak h2 if the cipher is strong enough as defined by RFC 7540. Hm, I see your point now. But I may not agree with your ALPN MUST happen after protocol/cipher suite negotiation conclusion. I parse this section as, a H2 server must be strong enough(comply to RFC7540), and a H2 client must also be strong enough (comply to RFC7540). Otherwise, both side may terminated the connection, and cannot declare as complying to H2. It is not necessary for an application protocol selector to detect whether a H2 server/client comply to H2 or not. If H2 is requested, it means that the client supports H2. Otherwise, it's a client application bug. If H2 is selected by a selected, it means that the selected server supports H2. Otherwise, it is a selector implementation bug. If something wrong in either client or server, it is expected to terminate the connection immediately, rather than downgrade to a not-strong enough level. From the points above, I think an application protocol selector may not need to know the negotiated protocol version and cipher suite. Thanks, Xuelei
Re: TLS ALPN Proposal v2
On 04/06/15 15:18, Simone Bordet wrote: Hi, On Thu, Jun 4, 2015 at 3:08 PM, Michael McMahon michael.x.mcma...@oracle.com wrote: On 04/06/15 13:19, Simone Bordet wrote: Hi, On Wed, Jun 3, 2015 at 8:23 AM, Xuelei Fan xuelei@oracle.com wrote: Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. What do you mean by after? As far as TLS is concerned, all of this negotiation happens in one negotiation. The client proposes a list of ciphers and application protocols. The server chooses a cipher and application protocol and sends back its choices. Currently, IIUC, the cipher selection is an iterative process where a cipher is attempted until one is negotiated. In this process, there is no looking at the application protocol. Here we're trying to find a solution for ALPN, and either we 1) look the application protocol in this iterative process (and therefore the SSLFunction is invoked multiple times), so that TLS protocol, cipher (possibly the alias too) and application protocol are chosen together, at once (for each iteration); or 2) we separate the TLS protocol and cipher negotiation (and alias) in one step, and we perform application protocol selection afterwards. The latter is how Jetty's ALPN works, and that's what I mean with *after*. For HTTP/2 it won't work to pick the application protocol before the cipher. Either at the same time, or after. That is why I asked to specify how the mechanism worked. Okay. I've been looking at it from the client point of view, and as far as I understand it, all of the information is available to the client at the right time. The HTTP/2 RFC specifically warns against splitting this negotiation with the example that a client could propose a mandatory TLS 1.2 cipher, but which is black-listed by HTTP/2. If (internally) the server chooses that cipher first, without knowing the application protocol is going to be HTTP/2 then you end up with a non-compliant connection that will probably have to be closed for reason of insufficient security. If the server chooses a blacklisted cipher, and then h2 as protocol, it's a non compliant server. Communication of clients with compliant (and properly configured) servers is guaranteed if the application protocol is chosen after (or at the same time of) the cipher. If I understand you correctly, you are proposing to rework the internal JDK code to perform TLS protocol, cipher, alias and application protocol in one point, which is then possibly iterated multiple times until a satisfactory tuple is selected ? I am fine with this approach too, but I guess the API will be very different from Jetty's ALPN and this current proposal (which is fine as well - does not have to be similar to Jetty's). I don't know enough about the TLS implementation to say how much work it is. Thanks ! Actually, I'm not proposing anything at this stage. But, I wonder if it might be simpler to just make all relevant information available to the existing negotiation API, rather than splitting it into separate calls - Michael.
Re: TLS ALPN Proposal v2
On 6/4/2015 8:19 PM, Simone Bordet wrote: Hi, On Wed, Jun 3, 2015 at 8:23 AM, Xuelei Fan xuelei@oracle.com wrote: Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. Why? Is it a spec of HTTP/2? It is a point I don't understand now. Please help with more details. And the connection may be rerouted (even to different machines) for further operation. The requested application protocols list should be the only information for the selection of a suitable application protocol. Not sure what you exactly mean here, Here is an example to explain the rerouting. For example, there a four entities, an TLS client, a router, an http/2 over TLS server, and an http/1.1 over TLS server. 1. the client request a connection to the http/2 server, the TCP connection is established between the client the router at first. 2. the router analysis the ClientHello message, and reroute the connection to the http/2 server. 3. the client and http/2 server negotiate the TLS connection, including the SSL protocol and cipher suite. The router should not be able to play man-in-the-middle negotiation if it does not know the server credentials. but you can't pick the HTTP/2 protocol unless you have the TLS protocol and TLS cipher available. So *only* the list of protocol sent by the client is not enough for HTTP/2, we would need additional contextual information. See my question above. What a HTTP/2 aware load balancer written in Java that offloads TLS would need to do is to negotiate the TLS protocol, negotiate the TLS cipher, *then* negotiate the application protocol (whether h2 or http/1.1), and with the last information pick a backend server, typically forwarding clear text bytes to the backend. See my question above. Thanks, Xuelei
Re: TLS ALPN Proposal v2
Hi, On Thu, Jun 4, 2015 at 3:08 PM, Michael McMahon michael.x.mcma...@oracle.com wrote: On 04/06/15 13:19, Simone Bordet wrote: Hi, On Wed, Jun 3, 2015 at 8:23 AM, Xuelei Fan xuelei@oracle.com wrote: Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. What do you mean by after? As far as TLS is concerned, all of this negotiation happens in one negotiation. The client proposes a list of ciphers and application protocols. The server chooses a cipher and application protocol and sends back its choices. Currently, IIUC, the cipher selection is an iterative process where a cipher is attempted until one is negotiated. In this process, there is no looking at the application protocol. Here we're trying to find a solution for ALPN, and either we 1) look the application protocol in this iterative process (and therefore the SSLFunction is invoked multiple times), so that TLS protocol, cipher (possibly the alias too) and application protocol are chosen together, at once (for each iteration); or 2) we separate the TLS protocol and cipher negotiation (and alias) in one step, and we perform application protocol selection afterwards. The latter is how Jetty's ALPN works, and that's what I mean with *after*. For HTTP/2 it won't work to pick the application protocol before the cipher. Either at the same time, or after. That is why I asked to specify how the mechanism worked. The HTTP/2 RFC specifically warns against splitting this negotiation with the example that a client could propose a mandatory TLS 1.2 cipher, but which is black-listed by HTTP/2. If (internally) the server chooses that cipher first, without knowing the application protocol is going to be HTTP/2 then you end up with a non-compliant connection that will probably have to be closed for reason of insufficient security. If the server chooses a blacklisted cipher, and then h2 as protocol, it's a non compliant server. Communication of clients with compliant (and properly configured) servers is guaranteed if the application protocol is chosen after (or at the same time of) the cipher. If I understand you correctly, you are proposing to rework the internal JDK code to perform TLS protocol, cipher, alias and application protocol in one point, which is then possibly iterated multiple times until a satisfactory tuple is selected ? I am fine with this approach too, but I guess the API will be very different from Jetty's ALPN and this current proposal (which is fine as well - does not have to be similar to Jetty's). I don't know enough about the TLS implementation to say how much work it is. Thanks ! -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
Hi, On Wed, Jun 3, 2015 at 2:56 AM, Bradford Wetmore bradford.wetm...@oracle.com wrote: Hi, I have just posted the second iteration of the ALPN proposal which hopefully addresses all of the comments raised here. It is in javadoc format, but things can certainly be adjusted: http://cr.openjdk.java.net/~wetmore/8051498/webrev.00/ Please see the archive [1] for previous design discussion. I will be writing up usage examples in the next few days. The significant changes: ExtendedSSLSession public ListString getReceivedApplicationProtocols() { This will allow applications to examine which protocol names were sent. This is a constant once the application protocols are received, so it can be surely retrieved from SSLParameters. I don't understand why it is replicated here ? SSLParameters mentions both ALPN/NPN as possible protocols. I removed the discussion about server and client since ALPN/NPN essentially reverse the roles. mentions appropriate character sets for String-byte[] conversions such as UTF-8 for ALPN. The application protocol selector is now a @FunctionalInterface (i.e. lambda-ready) called SSLFunction. It is to throw an SSLException if no values are supported, or null if you want to treat as an unknown extension. Defined constants for HTTP/1.1 and HTTP/2. SSLSession Called out that getHandshakeSession's ciphersuite may vary until selected. SSLBase A new marker interface that SSLEngine/SSLSocket will implement. This will allow for a single SSLFunction instead of having SSLFunctionSSLEngine and SSLFunctionSSLSocket. It does require that the lambda do a instanceof, unless we were to move the common Socket/Engine APIs into this class. I'm not sure about this one being a marker interface. I could understand if it extracted the common functionality of SSLEngine and SSLSocket, but a marker interface does not really add much, and perhaps I would prefer it entirely gone. On the same note, why is SSLFunction generic at all ? Also, it is critical to detail how the mechanism work. Will SSLFunction be invoked multiple times, or only once ? When, exactly, with respect to cipher selection and alias selection ? Example implementations for SSLFunction would be great to have: the typical HTTP/2 case is to select the application protocol based on the TLS protocol and the already negotiated cipher. Thanks ! -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
Hi, On Wed, Jun 3, 2015 at 8:23 AM, Xuelei Fan xuelei@oracle.com wrote: Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. And the connection may be rerouted (even to different machines) for further operation. The requested application protocols list should be the only information for the selection of a suitable application protocol. Not sure what you exactly mean here, but you can't pick the HTTP/2 protocol unless you have the TLS protocol and TLS cipher available. So *only* the list of protocol sent by the client is not enough for HTTP/2, we would need additional contextual information. What a HTTP/2 aware load balancer written in Java that offloads TLS would need to do is to negotiate the TLS protocol, negotiate the TLS cipher, *then* negotiate the application protocol (whether h2 or http/1.1), and with the last information pick a backend server, typically forwarding clear text bytes to the backend. Thanks ! -- Simone Bordet http://bordet.blogspot.com --- Finally, no matter how good the architecture and design are, to deliver bug-free software with optimal performance and reliability, the implementation technique must be flawless. Victoria Livschitz
Re: TLS ALPN Proposal v2
On 04/06/15 13:19, Simone Bordet wrote: Hi, On Wed, Jun 3, 2015 at 8:23 AM, Xuelei Fan xuelei@oracle.com wrote: Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. This is not possible for HTTP/2. Application protocol negotiation MUST happen *after* the TLS protocol and the TLS cipher are negotiated. What do you mean by after? As far as TLS is concerned, all of this negotiation happens in one negotiation. The client proposes a list of ciphers and application protocols. The server chooses a cipher and application protocol and sends back its choices. The HTTP/2 RFC specifically warns against splitting this negotiation with the example that a client could propose a mandatory TLS 1.2 cipher, but which is black-listed by HTTP/2. If (internally) the server chooses that cipher first, without knowing the application protocol is going to be HTTP/2 then you end up with a non-compliant connection that will probably have to be closed for reason of insufficient security. - Michael And the connection may be rerouted (even to different machines) for further operation. The requested application protocols list should be the only information for the selection of a suitable application protocol. Not sure what you exactly mean here, but you can't pick the HTTP/2 protocol unless you have the TLS protocol and TLS cipher available. So *only* the list of protocol sent by the client is not enough for HTTP/2, we would need additional contextual information. What a HTTP/2 aware load balancer written in Java that offloads TLS would need to do is to negotiate the TLS protocol, negotiate the TLS cipher, *then* negotiate the application protocol (whether h2 or http/1.1), and with the last information pick a backend server, typically forwarding clear text bytes to the backend. Thanks !
Re: TLS ALPN Proposal v2
src/java.base/share/classes/javax/net/ssl/ExtendedSSLSession.java = ListString getReceivedApplicationProtocols() -- C1. It might be useful to know the client requested application protocols in some circumstance. Better to set the application protocols in client side either. I'd like to use: - * Gets the application protocol value(s) received from the peer - * for this connection. + * Gets a {@link List} of requested application protocol value(s) + * for this connection. -public ListString getReceivedApplicationProtocols() { +public ListString getRequesedApplicationProtocols() { C2. The return value would better to be immutable, and better to describe the preference per RFC 7301. Maybe looks like: -* @return the non-null list of application protocol names +* @return the non-null immutable list of application protocol +* names, in descending order of preference. The returned +* list may be empty if no application protocols were +* requested. src/java.base/share/classes/javax/net/ssl/SSLParameters.java ListString getApplicationProtocols() -- C3. Better to indicate explicitly that this method only apply to client mode. C4. The method description is not instinctive enough for an application developer. Can we use words to indicate the purpose of the setting? For example: - * Gets the list of application-level protocol names that could - * be sent to the SSL/TLS peer. + * Gets the {@link List} of application layer protocol names that + * can be negotiated over SSL/TLS/DTLS protocols. C5. Prefer to use immutable return value: - * @return a non-null list of application protocol names. + * @return a non-null immutable list of application protocol names. C6. Nice to have a link for the standard protocol names. void setApplicationProtocols(ListString protocols) C7. see C3. C8. see C4. s/getApplicationProtocolSelector() -- C9. The use of SSLFunctionSSLBase, String make the implementation of protocol selector and JSSE provider implementation complicated. From the spec, looks like the selector may want to know address/ports, SSL protocol versions or the negotiated cipher suit. As would require that before use this selector, the handshaking must negotiate the protocol version and the cipher suite. That's a specific JSSE implementation requirement. It does not sound like a reasonable behavior. The implement of the selector is not straightforward, I think. Per section 4, RFC 7301: ... The application_layer_protocol_negotiation ServerHello extension is intended to be definitive for the connection (until the connection is renegotiated) and is sent in plaintext to permit network elements to provide differentiated service for the connection when the TCP or UDP port number is not definitive for the application-layer protocol to be used in the connection. By placing ownership of protocol selection on the server, ALPN facilitates scenarios in which certificate selection or connection rerouting may be based on the negotiated protocol. Per my understanding, application protocol should be negotiated before cipher suite and protocol version negotiated. And the connection may be rerouted (even to different machines) for further operation. The requested application protocols list should be the only information for the selection of a suitable application protocol. Based on that, I think it is more simple to use Simone's proposal: @FunctionalInterface interface ApplicationProtocolSelector { String select(ListString protocols) throws SSLException; } Hence, no need for a SSLBase any more. public static final String AP_HTTP_1_1 = http/1.1; public static final String AP_H2 = h2; C10. I understand why the constants are defined here. However, usually, we don't define standard names in JSSE APIs. Instead, we normally use Oracle standard names documentation. src/java.base/share/classes/javax/net/ssl/SSLSession.java = String getCipherSuite() --- Pretty hard to use this method with the new specification. It's not a necessary update, see #C9. Hope it helps! Xuelei On 6/3/2015 8:56 AM, Bradford Wetmore wrote: Hi, I have just posted the second iteration of the ALPN proposal which hopefully addresses all of the comments raised here. It is in javadoc format, but things can certainly be adjusted: http://cr.openjdk.java.net/~wetmore/8051498/webrev.00/ Please see the archive [1] for previous design discussion. I will be writing up usage examples in the next few days. The significant changes: ExtendedSSLSession