Re: TLS ALPN Proposal v7

2015-10-08 Thread Simone Bordet
Bradford,

On Sat, Oct 3, 2015 at 2:19 AM, Bradford Wetmore
 wrote:
> Thanks for the comments everyone.  I'm submitting the following to the CCC
> (internal review board):
>
> http://cr.openjdk.java.net/~wetmore/8051498/webrev.17/
>
> Changes:
>
> 1.  No H2 Blacklist/Comparator
>
> 2.  set/getApplicationProtocols() back to SSLParameters.

Have you implemented this solution already ? Also for clients ?
Do you have feedback on actually implementing ALPN in this way ?

-- 
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 v7

2015-10-08 Thread Bradford Wetmore



On Sat, Oct 3, 2015 at 2:19 AM, Bradford Wetmore
 wrote:

Thanks for the comments everyone.  I'm submitting the following to the CCC
(internal review board):

 http://cr.openjdk.java.net/~wetmore/8051498/webrev.17/

Changes:

1.  No H2 Blacklist/Comparator

2.  set/getApplicationProtocols() back to SSLParameters.


Have you implemented this solution already ?


It is underway.  The guts was already done based on previous API 
versions.  The new API is less involved, so it should be simpler to do 
as it's just cutting out the existing ciphersuite/ALPN selection stuff.



Also for clients ?


Client/server are both externally(API)/internally essentially the same. 
 The big difference is that for clients you send all the values passed 
in, for servers you only consult the first which is the selected ALPN value.



Do you have feedback on actually implementing ALPN in this way ?


Based on what I saw previously, it should be pretty straighforward.

Brad


Re: TLS ALPN Proposal v7

2015-10-06 Thread David M. Lloyd

I didn't reply on this last week, but this looks workable to me.  Thanks!

On 10/02/2015 07:19 PM, Bradford Wetmore wrote:



On 10/1/2015 7:35 PM, Xuelei Fan wrote:

On 10/2/2015 9:03 AM, Bradford Wetmore wrote:

Major changes:

1.  ApplicationProtocols is gone.  The H2 black list and comparator were
moved to StandardConstants.

2.  StandardConstants.  Strings for "h2" and "http/1.1" are back.  And
now that you are parsing the raw network bytes, I added a convenience
mapping between the two byte ciphersuite IANA-assigned value and the
Java Standard Name.


There is no SSLExplorer in OpenJDK. I think, maybe, the map is not
belong to OpenJDK either.

I think, the constants for HTTP2 is also belong to application protocol
(HTTP2) layer.  Application (HTTP2) implementation would take care of
them.  Maybe, they are not a part of JSSE framework either.


Ok, I've removed all of the H2 constants from StandardConstants.  I've
mentioned to the the H2/network team that this is something they will
need to handle/include (e.g. Blacklist/Comparator) in their code, and
they might want to consider APIs similar to what I had.

I personally found it very useful to have a proper mapping to get the
SSL_ vs. TLS_ prefix correct in the blacklist.


I would like to have "h2" and "http/1.1" defined as Standard Algorithms
Docs as we usually did for other standard constants.


Of course, they will be added as Standard Algorithm names.


3.  SSLParameter (set/get) are moved to SSLSocket/SSLEngine.  Even
though these could go into SSLParameters, this change makes backporting
much easier.  The helper code simply has to reflectively look for the
four methods in the implementation classes, and call if they are there.

Otherwise, there would have to be reflection both in the user code
(above) and implementation (to see if the passed SSLParameters had the
new methods via a subclass).

But, looking forward, per JSSE framework, SSLParameters should be the
central place to define SSL/TLS configuration parameters. We'd better
follow the conventions so that application developers won't get confused
about where SSL/TLS parameters should be configured.


I went back and forth on this many, many times yesterday.


Maybe, we cannot add public APIs for backporting.


I figured  we'd have to use reflection on user-derived classes to see if
the methods were there, but apparently implementation-specifc APIs can
be added in an update release, just not Java APIs. So if we really can
do that, then we can add a jdk.SSLParameters/
org.openjdk.jsse.SSLParameters extends SSLParameters, and in the
implementation, look for instanceof.


I think backporting is
another history, and would better not impact too much of the design for
JDK 9 and future releases.


Ok, so get/setApplicationProtocols() is back in SSLParameters.

Thanks for the comments everyone.  I'm submitting the following to the
CCC (internal review board):

 http://cr.openjdk.java.net/~wetmore/8051498/webrev.17/

Changes:

1.  No H2 Blacklist/Comparator

2.  set/getApplicationProtocols() back to SSLParameters.

Thanks,

Brad



--
- DML


Re: TLS ALPN Proposal v7

2015-10-02 Thread Xuelei Fan
Thanks!

Xuelei

On 10/3/2015 8:19 AM, Bradford Wetmore wrote:
> 
> 
> On 10/1/2015 7:35 PM, Xuelei Fan wrote:
>> On 10/2/2015 9:03 AM, Bradford Wetmore wrote:
>>> Major changes:
>>>
>>> 1.  ApplicationProtocols is gone.  The H2 black list and comparator were
>>> moved to StandardConstants.
>>>
>>> 2.  StandardConstants.  Strings for "h2" and "http/1.1" are back.  And
>>> now that you are parsing the raw network bytes, I added a convenience
>>> mapping between the two byte ciphersuite IANA-assigned value and the
>>> Java Standard Name.
>>>
>> There is no SSLExplorer in OpenJDK. I think, maybe, the map is not
>> belong to OpenJDK either.
>>
>> I think, the constants for HTTP2 is also belong to application protocol
>> (HTTP2) layer.  Application (HTTP2) implementation would take care of
>> them.  Maybe, they are not a part of JSSE framework either.
> 
> Ok, I've removed all of the H2 constants from StandardConstants.  I've
> mentioned to the the H2/network team that this is something they will
> need to handle/include (e.g. Blacklist/Comparator) in their code, and
> they might want to consider APIs similar to what I had.
> 
> I personally found it very useful to have a proper mapping to get the
> SSL_ vs. TLS_ prefix correct in the blacklist.
> 
>> I would like to have "h2" and "http/1.1" defined as Standard Algorithms
>> Docs as we usually did for other standard constants.
> 
> Of course, they will be added as Standard Algorithm names.
> 
>>> 3.  SSLParameter (set/get) are moved to SSLSocket/SSLEngine.  Even
>>> though these could go into SSLParameters, this change makes backporting
>>> much easier.  The helper code simply has to reflectively look for the
>>> four methods in the implementation classes, and call if they are there.
>>>
>>> Otherwise, there would have to be reflection both in the user code
>>> (above) and implementation (to see if the passed SSLParameters had the
>>> new methods via a subclass).
>> But, looking forward, per JSSE framework, SSLParameters should be the
>> central place to define SSL/TLS configuration parameters. We'd better
>> follow the conventions so that application developers won't get confused
>> about where SSL/TLS parameters should be configured.
> 
> I went back and forth on this many, many times yesterday.
> 
>> Maybe, we cannot add public APIs for backporting.
> 
> I figured  we'd have to use reflection on user-derived classes to see if
> the methods were there, but apparently implementation-specifc APIs can
> be added in an update release, just not Java APIs. So if we really can
> do that, then we can add a jdk.SSLParameters/
> org.openjdk.jsse.SSLParameters extends SSLParameters, and in the
> implementation, look for instanceof.
> 
>> I think backporting is
>> another history, and would better not impact too much of the design for
>> JDK 9 and future releases.
> 
> Ok, so get/setApplicationProtocols() is back in SSLParameters.
> 
> Thanks for the comments everyone.  I'm submitting the following to the
> CCC (internal review board):
> 
> http://cr.openjdk.java.net/~wetmore/8051498/webrev.17/
> 
> Changes:
> 
> 1.  No H2 Blacklist/Comparator
> 
> 2.  set/getApplicationProtocols() back to SSLParameters.
> 
> Thanks,
> 
> Brad
> 



TLS ALPN Proposal v6

2015-10-01 Thread Bradford Wetmore


You guys (David/Simone/Bernd/Jason) are more on the front lines in 
server development and how functional this API will be, so I'll trust 
your judgement here.  If you are ok with:


1. potentially being blind during renegotiations in the existing 
TLSv1/v1.1/v1.2, and,


2. not having an SSLExplorer as part of the JDK (i.e. you parsing the 
ClientHellos ala SSLExplorer),


3. requiring all ALPN logic be in the application and none in the JDK,

I'm willing to go with this approach. It doesn't seem optimal for what I 
would call casual users, but it does solve the ugly issues with the 
matches() API.


(BTW, I did consider adding a 
ClientHelloCallback/ClientHello/ServerHelloCallback/ServerHello class 
that would handle callbacks, but that was getting complicated also.)


For current renegotiations, the big use case is adding client 
authentication, so it seems likely that the same ciphersuite will be 
offered/chosen, so it's likely moot.



For the existing URL code, do you think we need:

1. to provide a "https.alpn" System Property for the existing 
URLConnections?


2. a getApplicationProtocol() for HttpsURLConnection?

Michael (net-dev) says H2 will not be backported into the URL mechanism 
and doesn't see a need for it yet, so I'm inclined to say no.


More inline:

On 9/29/2015 8:07 AM, David M. Lloyd wrote:

Hi Brad, thanks for replying; comments are inline:
On 09/28/2015 08:40 PM, Bradford Wetmore wrote:

1. Only the initial ClientHellos are parsable.
===
The biggest problem I have with an Explorer-based design is that only
the initial ClientHello on a connection is passed in the clear.
Subsequent negotiations on this connection will be completely missed, as
the ClientHellos are now encrypted.

This seems like a deal breaker for me.


You are right, I cannot come up with a good solution for this, so that
might mean the idea is shot - *however* - I would point out that the
latest draft of TLS 1.3 [1] completely kills off the capability of the
client to renegotiate a connection, meaning that this will no longer be
possible anyway, and given it's a 1% kind of use case, that might be
enough to let it slide.  Combine this with what I consider to be the
unlikelihood of this working with HTTP/2.0, and I would feel very safe
assuming that nobody will ever actually do this.


Thanks for pointing this out, I thought PSK+tickets were a replacement 
for a renegotiation (Section 6.2.3), but it's apparently only for 
session resumption.


BTW, the WG is up to a Sept 29, 2015 version (draft-09).

[1] https://tlswg.github.io/tls13-spec/


I would also note that, as you state later on, it would be possible to
combine this solution with any other solution (including the proposed
one) to cover both cases.  And given that this is still (in my
estimation) a "99%" solution, in my opinion it is still a viable
candidate for adding this functionality to Java 8 as a first pass or
stopgap as I described in my emails, particularly if the method(s) to
establish/query the protocol names are a strict subset of the proposed
Java 9 API (given that we cannot really overhaul the Java SE 8 API at
this point).


[...]
2.  "SSLExplorer" or something similar is needed.
=
This approach depends on "examining SSLClientHello"s, but there isn't a
class for this other than some sample code from a previous attempt.  I
am assuming that this approach would make such an external API a
necessity?  Being able to parse possible ClientHello formats is not a
straightforward/easy job.  This will add a fair amount of complexity,
and likely not an easy job in the remaining few weeks.  It could be
added later for JDK 10 but that means apps would likely need to roll
their own for 9.


And 8, yes, you definitely would need to roll your own, though Xuelei
Fan already has a nice example up on his blog that was built for SNI
(but uses the same principle).


If you are referring to:


http://simsmi.blogspot.com/2014/01/jep-114-tls-sni-extension-virtual.html

This is just describing the general approach for the sample 
SSLExplorer/SSLCapabilities code in the JSSE Reference Guide.  The 
actual code can be found here:



http://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#CodeExamples

My hope is to expand it to include parsing the ciphersuites and ALPN 
extensions.  I've moved/added some helper functions from 
ApplicationProtocol to StandardConstants.



 If it were me, I wouldn't even bother
adding it even in JDK 10, since (a) it applies only to the server side
and (b) there are a plethora of third-party server-side network I/O and
security libraries which are natural candidates to host this type of logic.


Ok.


3.  "no_application_protocol"
=
If the server doesn't support the protocols that the client advertises,
the "no_application_protocol" must be thrown.   We could add a
"no_application_protocol" 

Re: TLS ALPN Proposal v5

2015-09-29 Thread David M. Lloyd

Hi Brad, thanks for replying; comments are inline:

On 09/28/2015 08:40 PM, Bradford Wetmore wrote:


Several comments about David's proposal:


1. Only the initial ClientHellos are parsable.
===
The biggest problem I have with an Explorer-based design is that only
the initial ClientHello on a connection is passed in the clear.
Subsequent negotiations on this connection will be completely missed, as
the ClientHellos are now encrypted.

This seems like a deal breaker for me.


You are right, I cannot come up with a good solution for this, so that 
might mean the idea is shot - *however* - I would point out that the 
latest draft of TLS 1.3 [1] completely kills off the capability of the 
client to renegotiate a connection, meaning that this will no longer be 
possible anyway, and given it's a 1% kind of use case, that might be 
enough to let it slide.  Combine this with what I consider to be the 
unlikelihood of this working with HTTP/2.0, and I would feel very safe 
assuming that nobody will ever actually do this.


I would also note that, as you state later on, it would be possible to 
combine this solution with any other solution (including the proposed 
one) to cover both cases.  And given that this is still (in my 
estimation) a "99%" solution, in my opinion it is still a viable 
candidate for adding this functionality to Java 8 as a first pass or 
stopgap as I described in my emails, particularly if the method(s) to 
establish/query the protocol names are a strict subset of the proposed 
Java 9 API (given that we cannot really overhaul the Java SE 8 API at 
this point).



[...]
2.  "SSLExplorer" or something similar is needed.
=
This approach depends on "examining SSLClientHello"s, but there isn't a
class for this other than some sample code from a previous attempt.  I
am assuming that this approach would make such an external API a
necessity?  Being able to parse possible ClientHello formats is not a
straightforward/easy job.  This will add a fair amount of complexity,
and likely not an easy job in the remaining few weeks.  It could be
added later for JDK 10 but that means apps would likely need to roll
their own for 9.


And 8, yes, you definitely would need to roll your own, though Xuelei 
Fan already has a nice example up on his blog that was built for SNI 
(but uses the same principle).  If it were me, I wouldn't even bother 
adding it even in JDK 10, since (a) it applies only to the server side 
and (b) there are a plethora of third-party server-side network I/O and 
security libraries which are natural candidates to host this type of logic.



3.  "no_application_protocol"
=
If the server doesn't support the protocols that the client advertises,
the "no_application_protocol" must be thrown.   We could add a
"no_application_protocol" protocol String that would flag such a
condition internally.


Sure, though if you use the same method on both the client and server to 
specify the matched protocol, then the method necessarily accepts an 
array, in which case a null/unset could mean "no ALPN response" and an 
empty array could mean "no acceptable protocols".  But yeah I agree 
otherwise.



4.  Much of this is already possible.
=
If we were to go with the current API/internal and apps provided their
own ClientHello scanner, many of the benefits of what was proposed are
already available.  Apps can ask for the desired SSLContext, get the
SSLSocket/SSLengine, check the SNI/ALPN values, order/set the enabled
protocols/ciphers/etc + single ALPN value, then wrap the raw socket
using SSLSocketFactory.createSocket(Socket s, InputStream consumed,
boolean autoClose), and start the handshake.  The internal code would
still call matches() but only once.  If you want to be sure the
internals select the ApplicationProtocol, just put in a permissive
ApplicationProtocol.

The API is still more complicated unfortunately as ApplicationProtocol
is still present, but the overall behavior is quite similar.


+1 yep exactly.  I would however turn it around and also say, a more 
complex API could later be added on top of this simpler proposed 
solution, especially after more real world data is acquired, which might 
lower the overall risk as well.



5.  Other failure mode/fallback.

In the new proposal, suppose you do set a single ALPN value in the
application level, and the ServerHandshaker finds some other aspect of
the handshake wasn't appropriate (creds were mentioned several times,
but maybe a ciphersuite went dark due to new AlgorithmConstraints). This
would cause the ServerHandshaker to fail and there's no way to go back
to a different version unless you add a "for ALPN" loop into application.


Yeah all that validation would have to be done up front or manually in 
whatever server configuration is relevant.  If a cipher 

Re: TLS ALPN Proposal v5

2015-09-28 Thread Jason Greene

> On Sep 25, 2015, at 3:22 PM, David M. Lloyd  wrote:
> 
> On 09/25/2015 02:11 PM, Simone Bordet wrote:
>> Hi,
>> 
>> On Fri, Sep 25, 2015 at 7:23 PM, David M. Lloyd  
>> wrote:
>>> The application protocol implementation chooses only valid cipher suites for
>>> the protocol.  Why would it choose one that is not valid, considering that
>>> the protocol implementation itself is the only thing that "knows" what is
>>> valid or not?
>> 
>> The cipher could fail for the number of reasons it fails in
>> trySetCipherSuite(), even if the application has chosen the right
>> combination of (application protocol, cipher, whatever else).
>> At that point you have to try another application protocol.
> 
> From my reading of that code, it can only fail if you specifically set up 
> invalid combinations of cipher suite, protocol, and credentials.  The 
> application code should have all the information it needs to set up a correct 
> configuration though.

One example approach for a server-side H1 fallback scenario can be achieved 
using this approach, is to take the desired enabled portion of the supported 
cipher suite list for TLS 1.2+ (e.g. getSupportedCipherSuites, 
getSupportedSSLParameters, etc), which in simple scenarios is just the default 
suites (e.g. getDefaultSSLParameters, etc). Remove the H2 black-list from that 
and you have the h2 possible cipher-suite list. This list can then be further 
paired down based on key material (e.g disable ECDSA ciphers if only an RSA 
cert is present in the keystore). Finally the cipher list in client hello can 
be compared to find a possible intersection. If there is no intersection then 
use h1, otherwise configure h2.

One additional topic that I see came up on this list is the notion that cipher 
suite selection using ALPN is a temporary use-case, since H2 loses this problem 
with TLS 1.3. I think this viewpoint is too limiting. Fundamentally, the key 
use case that ALPN is achieving, is multiplexing two TLS ports over one. Any 
TLS policy that was required for a single protocol over a single port is likely 
to still be needed in a mixed protocol setup. Once you have non-overlapping 
policies then you need the ability to have logic which is distinguished by 
ALPN. We shouldn’t just look at H2 here, but think of it more generically.

Absent a non-limited TLS stack that does all the heavy lifting, deferring to 
the application is the next best thing. In some ways it can actually be better, 
since the portion of the logic on top of the JVM can evolve independently and 
more expediently than SE schedule allows. I also like David’s point that a 
simple solution is easier to backport to SE8, which is very important since EE8 
is planned to require http2 and SE8 support.

--
Jason T. Greene
WildFly Lead / JBoss EAP Platform Architect
JBoss, a division of Red Hat



Re: TLS ALPN Proposal v5

2015-09-26 Thread ecki
It is obvious, but I thought I might mention it: it does absolutely not help 
the user if a server refuses to negotiate a "MAY not use" cipher only to 
fallback to http/1.1 with exactly that cipher. I can see the motivation for 
deprecating those ciphers in modern servers (although I am note sure why CBC 
with TLS 1.2 is such a biggie), but then you must stick to the decision and not 
fall back and use them anyway. Feels much like overstepping a border in 
protocol design which causes a lot of interop problems and API grief. Given 
that it might be a good idea to not do anything special in JSSE and give the 
client and server developers full control over the use of ciphers.

Gruss
Bernd

-- 
http://bernd.eckenfels.net

-Original Message-
From: Xuelei Fan <xuelei@oracle.com>
To: "David M. Lloyd" <david.ll...@redhat.com>, Simone Bordet 
<simone.bor...@gmail.com>
Cc: OpenJDK <security-dev@openjdk.java.net>, "net-...@openjdk.java.net >>
 OpenJDK Network Dev list" <net-...@openjdk.java.net>
Sent: Sa., 26 Sep. 2015 3:19
Subject: Re: TLS ALPN Proposal v5

I would second David's proposal based on the #1/#A ideas.

Here are some background and options.

1. a HTTP2 server should support HTTP2
If a HTTP2 server declare to support HTTP2, it should support HTTP2
protocol. What happens if corner cases happen that the security is not
sufficient (client requested cipher suites are all blacklisted)? Two
approaches, refuse the connection or complete the connection.

It is easy to understand if refusing the connection for corner cases.

But why complete the connection with insufficient cipher suite? It's
because for HTTP2, the client side need to check the security strength
outside of SSL/TLS layer in case the SSL/TLS server uses insufficient
security parameters. If the security is insufficient, the client side
can request abbreviate handshaking (Section 3.1, RFC 7301) for a low
level application protocols (application protocol downgrade), or close
the connection.

Here is the scenarios:
A.1. client requests {HTTP2, HTTP1.1)
A.2. server negotiates HTTP2 and HTTP2 blacklisted cipher suite.
A.3. client checks the security sufficiency. The negotiated cipher suite
is insufficient.
A.4. client requests an abbreviated handshaking for {HTTP 1.1}
A.5. server negotiates HTTP1.1
A.6. client checks the security sufficiency. The negotiated cipher suite
is sufficient for HTTP 1.1.

There are might be one question? Should client check the security
sufficiency even if OpenJDK can do it pretty well. I would think client
need to do so because the client may also want to connect to other TLS
vendors, known or unknown. Client need to make sure the negotiated TLS
strength is sufficient for the specified application protocol.

If the story happens in this way, everything get more simple.

2. a HTTP2 server should support both HTTP2 and HTTP1.1
If an HTTP2 server support both HTTP2 and HTTP1.1, AND it is expected to
do HTTP protocol version negotiated by itself internally (fail-over to
HTTP 1.1) (I did not find the spec in HTTP2 RFC, but HTTP experts said a
server may support both HTTP2 and HTTP1.1), what happens if corner cases
happen that the security is not sufficient for HTTP 2? Three approaches:
refuse the connection, complete the connection with HTTP2, fail-over to
HTTP1.1 in server side.

The first two approaches are the same as #1. For the 3rd approach, the
server implementation and APIs design get much more complicated.

For the 2nd approach, the scenarios is similar to #1.1. The server
implementation part may looks like:
B.1. receive a ClientHello message.
B.2. negotiate the TLS protocol version, independently
B.3. negotiate the TLS cipher suite, independently
B.4. negotiate the application protocols, independently
B.5. sending the ServerHello message.

For the 3rd approach, the server implementation may looks like:
C.1. receive a ClientHello message.
C.2. negotiate the TLS protocol version, independently, get
negotiated_protocol
C.3. try to negotiate an TLS cipher suite, candidate_cipher_suite
C.4. try to negotiate an application protocol with negotiated_protocol
and candidate_cipher_suite. If the application protocol does not work
for the TLS protocol and cipher suites, goto #3.3 and try again.
Otherwise, move forward.
C.5. if application protocol can be negotiated, sending the ServerHello
message; otherwise, terminated the connection immediately.

For the case above, looks like client may not need to do application
protocol renegotiation. But actually, it may be able to avoid the coding
job because the client may not know whether the server would behavior
like #B, or #C.

#1/#A do the application protocol version negotiation in client side,
and #2/#C do the application protocol version negotiation in server
side. And there is no spec about which behavior should be expected as
far as I know. #1/#A is simple and straightforward, and #2/#C makes a
smart (

Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
CC security-dev.

On 9/25/2015 9:14 PM, Simone Bordet wrote:
> Hi,
> 
> On Fri, Sep 25, 2015 at 2:46 PM, David M. Lloyd  
> wrote:
>> Well, SNI already basically works this way, so it's not so great a stretch.
> 
> I don't follow ?
> SNI has APIs in JDK 8, you don't use SSLExplorer at all.
> 
> Also, SNI is a client-to-server information only, while with ALPN you
> have to reply to the client, so you have to modify the ServerHello.
> I don't see how you can do this without support from the JDK via APIs ?
> 
>> I imagine the client code simply specifying a list of protocols along with
>> today's list of cipher suites.
>>
>> The user-space server side logic would go like this:
>>
>> * Receive SSL ServerHello
>> * Examine the packet for ALPN and SNI information
>> * Read the list of cipher suites
>> * Evaluate
>> * Select an SSLContext based on protocol and/or server name
>> * Construct an SSLSocket or SSLEngine as appropriate
>> * Set a property on the SSLSocket/SSLEngine to indicate ALPN protocol name
>> * (optional) Change/sort the cipher suite list on the SSLSocket/SSLEngine as
>> appropriate
>> * Resume negotation by passing the ServerHello in to the SSLSocket/SSLEngine
>> as initial data
>>
>> It's not super elegant but it should work just as well as SNI works, and it
>> would cover 100% of use cases since the user has complete flexibility to
>> make a decision based on any combination of cipher suite selection, protocol
>> name, and host name, even potentially with the option to pretend that ALPN
>> wasn't recognized.
> 
> Are you saying that every application has to write its own TLS parser ?
> Would not that be overkill and full of potential security issues if
> one does not get the implementation strictly correct ?
> 
> Also, what if the JDK implementation refuses to use the cipher you
> chose along with the application protocol, for whatever reason ?
> 
> Thanks !
> 



Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
On 9/25/2015 10:20 PM, Simone Bordet wrote:
> Hi,
> 
> On Fri, Sep 25, 2015 at 3:20 PM, Xuelei Fan  wrote:
>> For the complication, I posted the comments in previous mail here:
>>
>> -
>>> In case you have [HTTP/2, AP_NEW, HTTP/1.1], then you can simply
>>> compose the comparators to sort first with the H2.CIPHER_COMPARATOR,
>>> then with AP_NEW.CIPHER_COMPARATOR.
>>>
>>> cipherSuites = Arrays.sort(cipherSuites,
>>>ApplicationProtocol.H2.CIPHER_COMPARATOR.
>>>thenComparing(AP_NEW.CIPHER_COMPARATOR));
>>>
>> Let's look at an example.  application_protocol_1 prefer cipher_suite_1,
>> and application_protocol_1 prefer cipher_suite_2.
>>
>> The comparator for application_protocol_1 would set the preference as
>> {cipher_suite_1, cipher_suite_2}.  and the comparator for
>> application_protocol_2} would set the preference as {cipher_suite_2,
>> cipher_suite_1}.
>>
>> The result to sort 1 and then 2, and the result to sort 2 and then 1 are
>> different.
>>
>> The call sequence to the comparators, and the call to each comparator
>> would result in difference result.  That's may be not the expected behavior.
> 
> The example is malformed, since it does not specify which ciphers are
> good for which application protocol, and neither the order of the
> application protocols.
> 
> Let me rewrite it:
> 
> application protocols: [ap1, ap2]
> ciphers: [c1, c2]
> 
> ap1 requires c1, does not work with c2
> ap2 requires c2, does not work with c1
> 
OK, as make the case more simple.

> Now the question is: you have to configure your system, what you want to do ?
> 
> If you want to favor ap1, then you sort [c1, c2]
> If you want to favor ap2, then you sort [c2, c1]
> If you want to favor c1, then you sort [c1, c2]
> If you want to favor c2, then you sort [c2, c1]
> 
> If you want to favor ap1 *and* c2, you have to decide what is more
> important between the two, because you cannot have both.
> 
> I don't see any problem, really.
> 
If "you" as the customer, I don't see any problem.  If "you" as OpenJDK,
the problem is that OpenJDK know nothing about the conditions (if you
want to favor ...), and therefore cannot make the decision (sort)
internally.

I think we should be on the same page: customers can make any sort as
they want.  SSLParameters.setCipherSuite() and
SSLParameters.setAppliationProtocols() can be used for any decision they
made.

> That the results are different, sure, but they are predictable.
> When the configuration uses one comparator, it will always be that
> result, and same for the other comparator.
> 
> But you configure the comparators in base of what you want to do.
> 
Need a confirmation.  I think you agree that the sort happens before the
calls to SSLParameters.setCipherSuite() and
SSLParameters.setAppliationProtocols(),  right?  As the case I commented
in previous mail:


// the customers' decision  // (1)
String[] cipherSuites = {}; // customer preference
List appProtocols =
{...};  // customer preference
+
+   // reorde the cipher suites // (1.1)
+   cipherSuites = ...   // the actual customer preference
+
+   // reorder application protocols preference
+   appProtocols = ...   // the actual customer preference

// configure the parameters // (2)
//
// customer preferences should be respected.
sslParameters.setCipherSuites(cipherSuites);
sslParameters.setApplicationProtocols(appProtocols);


Xuelei


Re: TLS ALPN Proposal v5

2015-09-25 Thread David M. Lloyd

On 09/25/2015 06:42 AM, Simone Bordet wrote:

Hi,

On Fri, Sep 25, 2015 at 11:47 AM, Xuelei Fan  wrote:

Here is the question to answer, which preference should be respected
firstly between cipher suite and application protocol?  If application
protocol are preferred at first, of course, application preference
should be respected at first; otherwise, cipher suite preference should
be respected at first.


The answer to this question has been decided when the algorithm has
been chosen to be:

for each cipher
   for each application protocol
   end
end

All the rest being equal, ciphers dominate application protocol selection.

Are you suggesting to change this to:

for each application protocol
   for each cipher
   end
end

?

It's in the hands of the role that configures application protocols
and ciphers to decide whether it's more important to prefer a protocol
or a cipher.


I agree with this, but...


Put it in a different way:

If the role prefers application protocols, it has to sort the ciphers
to influence that.
If the role prefers ciphers, it has to sort the ciphers.

No matter what, it has to sort the ciphers.


...why does sorting even matter?  Why should selection not be 
implemented 100% in user code, based on both the cipher suites list and 
application protocol, rendering this whole discussion pointless?  It's 
clearly a complex enough process (which is highly protocol-specific) 
that it seems to me quite unlikely that the JDK can possibly implement 
this in a way that will work for all use cases.



Therefore, personally, I think application may want a handy tool to sort
the cipher suite for the strength for general purpose, but not for
application protocol.


Because HTTP/2 would probably be popular given the success of its
predecessor, it would be handy to have a HTTP/2 comparator to
influence the selection of the HTTP/2 protocol.

Nothing forbids to offer a comparator by cipher strength too.


Ugh, why not just let the user decide *if* they want to sort (and 
filter) ciphers, and if so, they can do it themselves using 
Arrays.sort() on the ciphers array which already should be more than 
adequate.


In fact, why not just use the SSLExplorer approach and be done with this 
already?

--
- DML


Re: TLS ALPN Proposal v5

2015-09-25 Thread David M. Lloyd

On 09/25/2015 10:13 AM, Simone Bordet wrote:

Hi,

On Fri, Sep 25, 2015 at 4:48 PM, David M. Lloyd  wrote:

Yes, you would have to add a method - *one* method - to SSLSocket/SSLEngine
to specify the selected protocol; this would be done during setup before you
initiate handshake (which is why you need to explore the Hello packet in the
first place).


You also need to add another method to specify the cipher suite that
goes along with the application protocol.


No you wouldn't, because there already is a method for that: 
setEnabledCipherSuites().  You can only send one protocol back in the 
response, so there's nothing else to do.  Matching suites to protocols 
is the responsibility of the application protocol developer and must be 
done before handshake.



We have already discussed this approach: it's the "tuple" approach
where the application is given the list of TLS protocols, the list of
ciphers, the list of application protocols, the list of aliases and
decides what is the right tuple, and return that to the JDK.


Also, what if the JDK implementation refuses to use the cipher you
chose along with the application protocol, for whatever reason ?


Then you'd get an alert, I'd expect.


That would be wrong, because you could actually speak another protocol.


If you could, then the server would have chosen another protocol before 
handshake even begins.



But my point is that it's not the
JDK's business to introspect the application protocol!  The JDK should only
be looking at (TLS) protocol and cipher suite as it does today. It's up to
the application protocol to determine if there are unacceptable cipher
suites for that protocol.  Any other approach is inherently broken!  What if
I add a new application protocol, and some cipher suites are unacceptable
for it?  Should I just rely on the JDK for half the time?  Definitely not -
the protocol implementation *must* be fully responsible for its own security
policy.


I don't understand where you got the impression that the JDK has to
inspect the application protocol.

We are discussing an API exposed by the JDK to applications, exactly
because the application decides whether to accept or not the
combination of application protocol, cipher, etc.


Yes, but doing so by SSLContext is already too late in many cases. 
Trying to make a hook into handshaking is the wrong way of looking at 
this.  The user needs to make decisions *before* handshaking is even 
initiated on the server.


--
- DML


Re: TLS ALPN Proposal v5

2015-09-25 Thread David M. Lloyd

On 09/25/2015 12:13 PM, Simone Bordet wrote:

Hi,

On Fri, Sep 25, 2015 at 6:49 PM, David M. Lloyd  wrote:

A: receive raw SSL packet on Socket or SocketChannel
A: examine SSL ClientHello, extract SNI, ALPN, cipher suite info


This requires the application to write a TLS parser. This is currently
not necessary, nor provided.


It is already necessary to make many non-trivial SNI decisions.  I don't 
see ALPN as deserving higher treatment than SNI.



You think this could be provided via a JDK utility class ?
And if so, how can it be extended in the future when more TLS
Extensions are defined ?


I don't think it's necessary, no.




A: use whatever algorithm(s) you want to analyze SNI/ALPN/cipher suite info


The application must intersect the ciphers, application protocols...
perhaps again this can be done by some JDK utility class.


The point of the approach is that it is unlikely that any JDK-driven 
logic will be adequate for all use cases.  It's better to let the 
application be a black box: ALPN+SNI+Ciphers -> app logic -> one ALPN 
protocol, one SNI name, only valid ciphers.



A: either proxy the connection, or obtain or create the relevant SSLContext
from the desired provider
A: construct server-side SSLSocket/SSLEngine from SSLContext
A: setApplicationProtocol(H2)
A: setEnabledCipherSuites(only allowed suites in desired order)
A: start handshake
J: receive ClientHello (buffered from A)
J: verify SNI is matched, fail otherwise (as today)
J: verify ALPN is matched, fail otherwise (new)


There is a missing step here which is to verify the cipher
(trySetCipherSuite() logic).


The application protocol implementation chooses only valid cipher suites 
for the protocol.  Why would it choose one that is not valid, 
considering that the protocol implementation itself is the only thing 
that "knows" what is valid or not?



If that fails then we must try another application protocol.
We cannot just fail the connection.
How do we go from here to the top again to choose another protocol ?


J: send ServerHello (with the single, user-selected protocol)
...

This is very simple from the JDK perspective, and also much more flexible.


Well, I kinda like it, but I have strong reservations that it cannot
really "negotiate" the application protocol, meaning that if one
application protocol fails, try the next, and then the next and so
forth until one succeeds (or they all fail).


This validation should have happened before the JDK ever has a chance to 
be involved.

--
- DML


Re: TLS ALPN Proposal v5

2015-09-25 Thread Simone Bordet
David,

sorry, but I don't understand your proposal.

Can you please write it down in pseudo code what a server application
should do and what the JDK should do to negotiate HTTP/2 with a client
?

I don't see how it is even possible for a user to decide anything
*before* the handshaking is even initiated, like you say.
It obviously does not have enough information.

This is the current algorithm (A=app code, J=JDK code):

A: sslParameters.setApplicationProtocols(H2, H1);
A: (optional, only needed for H2) sort ciphers to favor H2
A: start handshake
J: receive ClientHello
J: ciphers = intersect client/server ciphers
J: aps = intersect client/server application protocols
J: for each cipher in ciphers
J:for each ap in aps
J:if (ap.matches(cipher & other info)) break
J end // aps
[A: ap.matches() calls into application code to return whether ap is
good for the given info]
J:if (ap was not selected) continue; // to next cipher
J:if (trySetCipherSuite(cipher)) break; // success
J: end // ciphers
J: send ServerHello
J: terminate handshake
A: sslEngine/sslSocket.getApplicationProtocol()

Note that the JDK provides default implementations for H1 and H2 for
ap.matches(), but in general these will be implemented by application
code.

For an application that wants to support H2, this boils down to the
first 2 lines, the rest is in the JDK.

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 v5

2015-09-25 Thread David M. Lloyd

Here are some solid reasons that this is the best possible approach:

* It will work for 100% of foreseeable use cases - i.e. there is 0% risk 
of permanently baking in flawed logic into the API
* It is dead simple - only one new method on SSLSocket/SSLEngine to set 
the protocol list (client) or selected single protocol (server)

* Because it is dead simple, it should be very easy to backport to Java 8
   *Example 1*: Add a static 
org.openjdk.jsse.ALPN#setApplicationProtocol(SSLEngine | SSLSocket s, 
String[] protocols) method, which calls (maybe even reflectively?) the 
setApplicationProtocol() method on the SSLEngine/SSLSocket 
implementation if it is present & public
   *Example 2*: Add an org.openjdk.jsse.ALPNAware interface with the 
setApplicationProtocol(String[]) method, which is implemented by JSSE 
providers
* Now Java EE 8 can trivially achieve HTTP/2.0 support with very low 
risk to either the JDK/SE timeline or the EE timeline
* Since most or all of the "hard" logic is on the server side, the 
majority of API consumers will have an easy time using the API

* We server developers can handle the rest!

On 09/25/2015 12:23 PM, David M. Lloyd wrote:

On 09/25/2015 12:13 PM, Simone Bordet wrote:

Hi,

On Fri, Sep 25, 2015 at 6:49 PM, David M. Lloyd
 wrote:

A: receive raw SSL packet on Socket or SocketChannel
A: examine SSL ClientHello, extract SNI, ALPN, cipher suite info


This requires the application to write a TLS parser. This is currently
not necessary, nor provided.


It is already necessary to make many non-trivial SNI decisions.  I don't
see ALPN as deserving higher treatment than SNI.


You think this could be provided via a JDK utility class ?
And if so, how can it be extended in the future when more TLS
Extensions are defined ?


I don't think it's necessary, no.




A: use whatever algorithm(s) you want to analyze SNI/ALPN/cipher
suite info


The application must intersect the ciphers, application protocols...
perhaps again this can be done by some JDK utility class.


The point of the approach is that it is unlikely that any JDK-driven
logic will be adequate for all use cases.  It's better to let the
application be a black box: ALPN+SNI+Ciphers -> app logic -> one ALPN
protocol, one SNI name, only valid ciphers.


A: either proxy the connection, or obtain or create the relevant
SSLContext
from the desired provider
A: construct server-side SSLSocket/SSLEngine from SSLContext
A: setApplicationProtocol(H2)
A: setEnabledCipherSuites(only allowed suites in desired order)
A: start handshake
J: receive ClientHello (buffered from A)
J: verify SNI is matched, fail otherwise (as today)
J: verify ALPN is matched, fail otherwise (new)


There is a missing step here which is to verify the cipher
(trySetCipherSuite() logic).


The application protocol implementation chooses only valid cipher suites
for the protocol.  Why would it choose one that is not valid,
considering that the protocol implementation itself is the only thing
that "knows" what is valid or not?


If that fails then we must try another application protocol.
We cannot just fail the connection.
How do we go from here to the top again to choose another protocol ?


J: send ServerHello (with the single, user-selected protocol)
...

This is very simple from the JDK perspective, and also much more
flexible.


Well, I kinda like it, but I have strong reservations that it cannot
really "negotiate" the application protocol, meaning that if one
application protocol fails, try the next, and then the next and so
forth until one succeeds (or they all fail).


This validation should have happened before the JDK ever has a chance to
be involved.


--
- DML


Re: TLS ALPN Proposal v5

2015-09-25 Thread David M. Lloyd

On 09/25/2015 11:37 AM, Simone Bordet wrote:

David,

sorry, but I don't understand your proposal.

Can you please write it down in pseudo code what a server application
should do and what the JDK should do to negotiate HTTP/2 with a client
?


Sure.

A: receive raw SSL packet on Socket or SocketChannel
A: examine SSL ClientHello, extract SNI, ALPN, cipher suite info
A: use whatever algorithm(s) you want to analyze SNI/ALPN/cipher suite info
A: either proxy the connection, or obtain or create the relevant 
SSLContext from the desired provider

A: construct server-side SSLSocket/SSLEngine from SSLContext
A: setApplicationProtocol(H2)
A: setEnabledCipherSuites(only allowed suites in desired order)
A: start handshake
J: receive ClientHello (buffered from A)
J: verify SNI is matched, fail otherwise (as today)
J: verify ALPN is matched, fail otherwise (new)
J: send ServerHello (with the single, user-selected protocol)
...

This is very simple from the JDK perspective, and also much more flexible.


I don't see how it is even possible for a user to decide anything
*before* the handshaking is even initiated, like you say.
It obviously does not have enough information.


It has the ClientHello, which should be more than enough.


This is the current algorithm (A=app code, J=JDK code):

A: sslParameters.setApplicationProtocols(H2, H1);
A: (optional, only needed for H2) sort ciphers to favor H2
A: start handshake
J: receive ClientHello
J: ciphers = intersect client/server ciphers
J: aps = intersect client/server application protocols
J: for each cipher in ciphers
J:for each ap in aps
J:if (ap.matches(cipher & other info)) break
J end // aps
[A: ap.matches() calls into application code to return whether ap is
good for the given info]
J:if (ap was not selected) continue; // to next cipher
J:if (trySetCipherSuite(cipher)) break; // success
J: end // ciphers
J: send ServerHello
J: terminate handshake
A: sslEngine/sslSocket.getApplicationProtocol()


So complex!  What if this algorithm is not adequate for new protocols? 
Is there not a danger associated with assuming HTTP/2 is your only use 
case?  What if the application wants to make a decision that this scheme 
cannot support?



Note that the JDK provides default implementations for H1 and H2 for
ap.matches(), but in general these will be implemented by application
code.

For an application that wants to support H2, this boils down to the
first 2 lines, the rest is in the JDK.


--
- DML


Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
I would second David's proposal based on the #1/#A ideas.

Here are some background and options.

1. a HTTP2 server should support HTTP2
If a HTTP2 server declare to support HTTP2, it should support HTTP2
protocol. What happens if corner cases happen that the security is not
sufficient (client requested cipher suites are all blacklisted)? Two
approaches, refuse the connection or complete the connection.

It is easy to understand if refusing the connection for corner cases.

But why complete the connection with insufficient cipher suite? It's
because for HTTP2, the client side need to check the security strength
outside of SSL/TLS layer in case the SSL/TLS server uses insufficient
security parameters. If the security is insufficient, the client side
can request abbreviate handshaking (Section 3.1, RFC 7301) for a low
level application protocols (application protocol downgrade), or close
the connection.

Here is the scenarios:
A.1. client requests {HTTP2, HTTP1.1)
A.2. server negotiates HTTP2 and HTTP2 blacklisted cipher suite.
A.3. client checks the security sufficiency. The negotiated cipher suite
is insufficient.
A.4. client requests an abbreviated handshaking for {HTTP 1.1}
A.5. server negotiates HTTP1.1
A.6. client checks the security sufficiency. The negotiated cipher suite
is sufficient for HTTP 1.1.

There are might be one question? Should client check the security
sufficiency even if OpenJDK can do it pretty well. I would think client
need to do so because the client may also want to connect to other TLS
vendors, known or unknown. Client need to make sure the negotiated TLS
strength is sufficient for the specified application protocol.

If the story happens in this way, everything get more simple.

2. a HTTP2 server should support both HTTP2 and HTTP1.1
If an HTTP2 server support both HTTP2 and HTTP1.1, AND it is expected to
do HTTP protocol version negotiated by itself internally (fail-over to
HTTP 1.1) (I did not find the spec in HTTP2 RFC, but HTTP experts said a
server may support both HTTP2 and HTTP1.1), what happens if corner cases
happen that the security is not sufficient for HTTP 2? Three approaches:
refuse the connection, complete the connection with HTTP2, fail-over to
HTTP1.1 in server side.

The first two approaches are the same as #1. For the 3rd approach, the
server implementation and APIs design get much more complicated.

For the 2nd approach, the scenarios is similar to #1.1. The server
implementation part may looks like:
B.1. receive a ClientHello message.
B.2. negotiate the TLS protocol version, independently
B.3. negotiate the TLS cipher suite, independently
B.4. negotiate the application protocols, independently
B.5. sending the ServerHello message.

For the 3rd approach, the server implementation may looks like:
C.1. receive a ClientHello message.
C.2. negotiate the TLS protocol version, independently, get
negotiated_protocol
C.3. try to negotiate an TLS cipher suite, candidate_cipher_suite
C.4. try to negotiate an application protocol with negotiated_protocol
and candidate_cipher_suite. If the application protocol does not work
for the TLS protocol and cipher suites, goto #3.3 and try again.
Otherwise, move forward.
C.5. if application protocol can be negotiated, sending the ServerHello
message; otherwise, terminated the connection immediately.

For the case above, looks like client may not need to do application
protocol renegotiation. But actually, it may be able to avoid the coding
job because the client may not know whether the server would behavior
like #B, or #C.

#1/#A do the application protocol version negotiation in client side,
and #2/#C do the application protocol version negotiation in server
side. And there is no spec about which behavior should be expected as
far as I know. #1/#A is simple and straightforward, and #2/#C makes a
smart (and complicated) server.

OpenJDK now is trying to support both #1 and #2.

Thanks,
Xuelei

On 9/26/2015 4:22 AM, David M. Lloyd wrote:
> On 09/25/2015 02:11 PM, Simone Bordet wrote:
>> Hi,
>>
>> On Fri, Sep 25, 2015 at 7:23 PM, David M. Lloyd
>>  wrote:
>>> The application protocol implementation chooses only valid cipher
>>> suites for
>>> the protocol.  Why would it choose one that is not valid, considering
>>> that
>>> the protocol implementation itself is the only thing that "knows"
>>> what is
>>> valid or not?
>>
>> The cipher could fail for the number of reasons it fails in
>> trySetCipherSuite(), even if the application has chosen the right
>> combination of (application protocol, cipher, whatever else).
>> At that point you have to try another application protocol.
> 
> From my reading of that code, it can only fail if you specifically set
> up invalid combinations of cipher suite, protocol, and credentials.  The
> application code should have all the information it needs to set up a
> correct configuration though.
> 
>>> This validation should have happened before the JDK ever has a chance
>>> 

Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
On 9/26/2015 8:47 AM, Bradford Wetmore wrote:
>> {TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}
> 
> BTW, in case anyone was wondering, both of these suites are on the RFC
> 7540 blacklist.

Ooops, I meant to use "TLS_ECDHE_" as HTTP2 non-blacklisted cipher suite.

Xuelei


Re: TLS ALPN Proposal v5

2015-09-25 Thread Bradford Wetmore


You guys certainly were prolific in your discussions last night.  ;) 
Many comments to touch on, and I definitely won't have time today to 
respond to everything.


Xuelei wrote:
> I don't think we really need to re-order the cipher suites.

Simone wrote:
> Of course you need to re-order in this case.

In an iterative implementation like SunJSSE is currently, if you want to 
have the preference order of H2/H1, you need to try all of the 
H2-compatible ciphersuites first. Once you try a non-H2-compatible 
suite, the H2 matcher will fail, and it will then go to the H1 matcher, 
which will succeed.  This particular situation was discussed in RFC 7540.


> It might be not customers expected behavior to re-order/sort their
> preference of cipher suites or preference.

Are we are clear that the intention was never for the JDK to internally 
resort the ciphersuites, but rather to provide an external helper 
function (H2BLACKLISTCOMPARATOR) with which applications can do their 
own sorting and pass the results to setEnabledCiphersuite()?  I think 
maybe the confusion came from the 3 roles you describe later.


> If there are three roles, OpenJDK, application, customers, there are
> three result:

For JDK developers, the line between application/customer is quite 
blurry.  You/I are concerned about the interface between the OpenJDK and 
(application+customers).  The application folks will mainly be handling 
the customer configuration.


> {TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}

BTW, in case anyone was wondering, both of these suites are on the RFC 
7540 blacklist.


Simone wrote:

> for each cipher
>   for each application protocol
>   end
> end
>
> All the rest being equal, ciphers dominate application protocol
> selection.

Correct.  That's the current proposal.  It's a chicken/egg problem.  The 
KeyManager is part of the ciphersuite selection mechanims, and should 
have a proposed ALPN value value to use (ala RFC 7301), but the ALPN 
mechanism needs to have a ciphersuite in mind for it's calculation.



I will think over David's proposal over the weekend.  Much of the I/O 
required is already there using the JDK 1.8 method 
SSLSocketFactory.createSocket(Socket s, InputStream consumed, boolean 
autoClose), which was added for this very purpose.  There's nothing to 
do for SSLEngine.


Just a bit of history, we did consider a ClientHello parser when working 
on SNI. I don't remember the details as to why we didn't add it, but the 
SSLCapabilities/SSLExplorer classes in the JSSE sample code came from 
that attempt.  I have a vague recollection that the API was getting too 
complicated in the time we had.


More next week.

Have a good weekend, all.

Brad



Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
On 9/26/2015 8:47 AM, Bradford Wetmore wrote:
>> It might be not customers expected behavior to re-order/sort their
>> preference of cipher suites or preference.
> 
> Are we are clear that the intention was never for the JDK to internally
> resort the ciphersuites, but rather to provide an external helper
> function (H2BLACKLISTCOMPARATOR) with which applications can do their
> own sorting and pass the results to setEnabledCiphersuite()?

My points:
1. OpenJDK should not do the re-sort internally. The preference decision
should be made before the call to setEnabledCiphersuite().

I think Simone agreed with this point.

2. A handy function to resort the cipher suite is useful. But it is out
of the scope of ALPN, or even out of the scope of OpenJDK. Application
can do whatever resorting, H2BLACKLISTCOMPARATOR does not belong to OpenJDK.

Xuelei


Re: TLS ALPN Proposal v5

2015-09-25 Thread Simone Bordet
Hi,

On Fri, Sep 25, 2015 at 3:44 AM, Xuelei Fan  wrote:
> For example, a client wants to negotiate  {HTTP2,  HTTP1.1} or {HTTP1.1,
> HTTP2} and {TLS_RSA_WITH_AES_128_CBC_SHA,
> TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}.
> HTTP1.1/TLS_RSA_WITH_AES_128_CBC_SHA should be negotiated per the TLS
> and HTTP2 specification.  If the cipher suites are sorted,
> TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 would be negotiated, this is not
> what the customer really expected.  The customer preference should be
> respected.
>
> I don't think we really need to re-order the cipher suites.

"We" as in the OpenJDK implementation *must not* reorder the cipher suites.
"We" as in an application that wants to use HTTP/2 *must* reorder the
cipher suites.
The comparator provided is only a help to the application to perform
this reordering.

> Let's consider the following client requests (prefer cipher suite more
> than application protocol; blacklisted_CS are HTTP2 blacklisted cipher
> suite):
>
> 1. {HTTP2, HTTP1.1} {strong_cipher_site, blacklisted_CS}
> HTTP2 and strong_cipher_site should be negotiated.  Need not to re-order
> cipher suites.
>
> 2. {HTTP1.1, HTTP2} {strong_cipher_site, blacklisted_CS}
> HTTP1.1 and strong_cipher_site should be negotiated. Need not to
> re-order cipher suites.
>
> 3. {HTTP2, HTTP1.1} {blacklisted_CS, strong_cipher_site}
> HTTP1.1 and blacklisted_CS should be negotiated. Need not to re-order
> cipher suites.

Of course you need to re-order in this case.
The application has just provided a preference for HTTP/2 in the
application protocol list, it actually happens that HTTP/2 could be
negotiated because strong ciphers are present, but instead HTTP/1.1 is
chosen.

> 4. {HTTP1.1, HTTP2} {blacklisted_CS, strong_cipher_site}
> HTTP1.1 and blacklisted_CS should be negotiated. Need not to re-order
> cipher suites.
>
> 5. {HTTP2} {strong_cipher_site, blacklisted_CS}
> HTTP2 and strong_cipher_site should be negotiated. Need not to re-order
> cipher suites.
>
> 6. {HTTP1.1} {strong_cipher_site, blacklisted_CS}
> HTTP1.1 and strong_cipher_site should be negotiated. Need not to
> re-order cipher suites.
>
> 7. {HTTP2} {blacklisted_CS, strong_cipher_site}
> blacklisted_CS would be filtered out as it does not appy to HTTP2.  Only
> strong_cipher_site presents in ClientHello message.
>
> HTTP2 and strong_cipher_site should be negotiated. Need not to re-order
> cipher suites.
>
> 8. {HTTP1.1} {blacklisted_CS, strong_cipher_site}
> HTTP1.1 and blacklisted_CS should be negotiated. Need not to re-order
> cipher suites.
>
> One concern may be that, the customer is not intent to negotiate HTTP2
> blacklisted cipher suite.  The customer just don't know which are the
> strong cipher suites among many cipher suites.  I think we may need a
> handy tool to order the cipher suites before configuration.
>
> // there are a few cipher suites are available
> String[] cipherSuites = ...  // a array of cipher suites.
>
> // Q: Don't know the strength of them
> // A: OK, there is a handy tool
> cipherSuites = cipherSuiteReorder.sort(cipherSuites);

Or, with the comparator:

cipherSuites = Arrays.sort(cipherSuites,
ApplicationProtocol.H2.CIPHER_COMPARATOR);

The comparator is the handy tool.

> // configure the cipher suites
> SSLParameters.setCipherSuites(cipherSuites);
>
> The order also apply to the normally cipher suites configuration, not
> only to application protocols.  The re-order should be called by
> customers explicitly.  JSSE would better not sort them automatically.
>
> I think, the handy sort tool cannot be simply bind to application
> protocol.  For example, HTTP2 has a blacklisted cipher suites.  OK,
> ApplicationProtocol.H2BLACKLISTCOMPARATOR is expected to make the sort.
>  If, in the future, a new application protocol (AP_NEW) has a different
> blacklist cipher suites, a new
> ApplicationProtocol.APNEWBLACKLISTCOMPARATOR would be defined.  If both
> {HTTP2, AP_NEW} would be requested, which comparator for the sorting
> would be used?  None of them can sort the cipher suite properly.  The
> comparator design will not work any more.

Sure it does.

Because you explicitly set a preference in the order of the
application protocol, you only sort to favour the best protocol.

In case you have [HTTP/2, AP_NEW, HTTP/1.1], then you can simply
compose the comparators to sort first with the H2.CIPHER_COMPARATOR,
then with AP_NEW.CIPHER_COMPARATOR.

cipherSuites = Arrays.sort(cipherSuites,
ApplicationProtocol.H2.CIPHER_COMPARATOR.thenComparing(AP_NEW.CIPHER_COMPARATOR));

> We may need a handy tool for the sorting for stronger cipher suites.
> But, AFAIU, the tool does not belong to ALPN.

Indeed, it belongs to ApplicationProtocol.H2, not to ApplicationProtocol.

-- 
Simone Bordet

http://cometd.org
http://webtide.com
Developer advice, training, services and support
from the Jetty & CometD experts.


Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
On 9/25/2015 7:42 PM, Simone Bordet wrote:
> Hi,
> 
> On Fri, Sep 25, 2015 at 11:47 AM, Xuelei Fan  wrote:
>> Here is the question to answer, which preference should be respected
>> firstly between cipher suite and application protocol?  If application
>> protocol are preferred at first, of course, application preference
>> should be respected at first; otherwise, cipher suite preference should
>> be respected at first.
> 
> The answer to this question has been decided when the algorithm has
> been chosen to be:
> 
> for each cipher
>   for each application protocol
>   end
> end
> 
> All the rest being equal, ciphers dominate application protocol selection.
> 
> Are you suggesting to change this to:
> 
> for each application protocol
>   for each cipher
>   end
> end
> 
> ?
> 
No, I would prefer the first approach.  Good, we are at the same page at
this point, I think.

> It's in the hands of the role that configures application protocols
> and ciphers to decide whether it's more important to prefer a protocol
> or a cipher.
> 
> Put it in a different way:
> 
> If the role prefers application protocols, it has to sort the ciphers
> to influence that.
> If the role prefers ciphers, it has to sort the ciphers.
> 
I did not catch the idea.  if the tole prefers ciphers, why still need
to sort the ciphers?  Sort for what?

> No matter what, it has to sort the ciphers.
> 
I did not get your ideas.  Who would sort the preferences? and when the
preferences should be sorted?

Maybe, we are not on the same page, I think.

>From the viewpoint of application or library, if an administrator had
made his decision about the preference of application protocols and
cipher suites, applications and OpenJDK may be better to respect the
decision.

// the customers' decision//(1)
String[] cipherSuites = {};   // customer preference, sorted.
List appProtocols =
  {...};  // customer preference, sorted.

// configure the parameters   // (2)
//
// customer preferences should be respected.
sslParameters.setCipherSuites(cipherSuites);
sslParameters.setApplicationProtocols(appProtocols);

There might be concerns, customers preference may be not right and need
to adjusted.  Maybe, a re-order tool is needed before (not after) the
configuration of the parameters.


// the customers' decision  // (1)
String[] cipherSuites = {}; // customer preference
List appProtocols =
{...};  // customer preference
+
+   // reorde the cipher suites // (1.1)
+   cipherSuites = ...   // the actual customer preference
+
+   // reorder application protocols preference
+   appProtocols = ...   // the actual customer preference

// configure the parameters // (2)
//
// customer preferences should be respected.
sslParameters.setCipherSuites(cipherSuites);
sslParameters.setApplicationProtocols(appProtocols);

>> Therefore, personally, I think application may want a handy tool to sort
>> the cipher suite for the strength for general purpose, but not for
>> application protocol.
> 
> Because HTTP/2 would probably be popular given the success of its
> predecessor, it would be handy to have a HTTP/2 comparator to
> influence the selection of the HTTP/2 protocol.
> 
> Nothing forbids to offer a comparator by cipher strength too.
> 
I think a general cipher strength comparator is sufficient for HTTP/2
preference too.  What do you think?

Maybe, need no extra comparator for HTTP2.  Extra comparator would make
behaviors pretty complicated and hard to get expected, as I described in
the previous mail.

Xuelei


Re: TLS ALPN Proposal v5

2015-09-25 Thread Simone Bordet
Hi,

On Fri, Sep 25, 2015 at 11:47 AM, Xuelei Fan  wrote:
> Here is the question to answer, which preference should be respected
> firstly between cipher suite and application protocol?  If application
> protocol are preferred at first, of course, application preference
> should be respected at first; otherwise, cipher suite preference should
> be respected at first.

The answer to this question has been decided when the algorithm has
been chosen to be:

for each cipher
  for each application protocol
  end
end

All the rest being equal, ciphers dominate application protocol selection.

Are you suggesting to change this to:

for each application protocol
  for each cipher
  end
end

?

It's in the hands of the role that configures application protocols
and ciphers to decide whether it's more important to prefer a protocol
or a cipher.

Put it in a different way:

If the role prefers application protocols, it has to sort the ciphers
to influence that.
If the role prefers ciphers, it has to sort the ciphers.

No matter what, it has to sort the ciphers.

> Therefore, personally, I think application may want a handy tool to sort
> the cipher suite for the strength for general purpose, but not for
> application protocol.

Because HTTP/2 would probably be popular given the success of its
predecessor, it would be handy to have a HTTP/2 comparator to
influence the selection of the HTTP/2 protocol.

Nothing forbids to offer a comparator by cipher strength too.

-- 
Simone Bordet

http://cometd.org
http://webtide.com
Developer advice, training, services and support
from the Jetty & CometD experts.


Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
On 9/25/2015 8:48 PM, Simone Bordet wrote:
> Hi,
> 
> On Fri, Sep 25, 2015 at 2:26 PM, Xuelei Fan  wrote:
>> Maybe, we are not on the same page, I think.
> 
> We are.
> 
>> I think a general cipher strength comparator is sufficient for HTTP/2
>> preference too.  What do you think?
> 
> I don't know if all the blacklisted ciphers are actually lower
> strength of all the remaining ciphers, nor what is the exact
> definition of "strength" that you can use in a comparator.
> But because the HTTP/2 specification bothered to say what's
> blacklisted, I would just use that.
> 
HTTP/2 blacklists them because they are no so strong because of various
reasons.

The definition of "strength" can be customized by the customers.
Therefore, I don't worry too much because of this flexibility.

>> Maybe, need no extra comparator for HTTP2.  Extra comparator would make
>> behaviors pretty complicated and hard to get expected, as I described in
>> the previous mail.
> 
> There is no complication, really. Two comparators would compose, not exclude.
> 
For the complication, I posted the comments in previous mail here:

-
> In case you have [HTTP/2, AP_NEW, HTTP/1.1], then you can simply
> compose the comparators to sort first with the H2.CIPHER_COMPARATOR,
> then with AP_NEW.CIPHER_COMPARATOR.
>
> cipherSuites = Arrays.sort(cipherSuites,
>ApplicationProtocol.H2.CIPHER_COMPARATOR.
>thenComparing(AP_NEW.CIPHER_COMPARATOR));
>
Let's look at an example.  application_protocol_1 prefer cipher_suite_1,
and application_protocol_1 prefer cipher_suite_2.

The comparator for application_protocol_1 would set the preference as
{cipher_suite_1, cipher_suite_2}.  and the comparator for
application_protocol_2} would set the preference as {cipher_suite_2,
cipher_suite_1}.

The result to sort 1 and then 2, and the result to sort 2 and then 1 are
different.

The call sequence to the comparators, and the call to each comparator
would result in difference result.  That's may be not the expected behavior.
-

It's not easy to use application comparator, I think.

> For example, let's say that you want to sort by "bit" strength in a
> way that you want to prefer 128 bits or lower to favor performance,
> but also do HTTP/2.
> 
> The H2 comparator will sort the blacklisted at the end.
> Among the good ones, they all compare == 0 for the H2 comparator.
> That is where the second comparator will kick in, grep the cipher name
> for the bits number and sort them accordingly.
> 
It's flexible to meet the requirement by customer's customization.
Maybe, extra comparator is not necessary here.  I think the comparator
can be a handy tool, but not belong to ALPN.

Xuelei


Re: TLS ALPN Proposal v5

2015-09-25 Thread Xuelei Fan
On 9/25/2015 9:14 PM, Simone Bordet wrote:
> On Fri, Sep 25, 2015 at 2:46 PM, David M. Lloyd  
> wrote:
>> > Well, SNI already basically works this way, so it's not so great a stretch.
> I don't follow ?
> SNI has APIs in JDK 8, you don't use SSLExplorer at all.

There are two typical cases for SNI and ALPN. One is that the same
server is used for difference SNI/ALPN. Another one is that different
server is used for different SNI/ALPN.

For example, there is a TLS server 101.101.1.1 for delegation. If SNI
www.example.com get requested, the delegation server may redirect the
connection to 192.168.1.100 (provide the service for www.example.com).
If SNI www.another.com get requested, the delegation server may redirect
the connection to 192.168.1.101 (provide the service for www.another.com).

Similarly, ALPN need to support the case as above.

Another example, there is a server 101.101.1.1. If SNI www.example.com
get requested, the server would act as the service for www.example.com.
If SNI www.another.com get requested, the server would act as the
service for www.another.com.

Similarly, ALPN also need to support the case as above.

Actually, it was a puzzle to me: whether a concrete server can support
both HTTP/2 and HTTP/1.1, or not. If HTTP/2 mode of the server does not
work, is it OK to fall-over to use HTTP/1.1 mode? I did not get the
answer from the HTTP/2 spec. The current design is based on the idea
that a concrete server may support both HTTP/2 and HTTP/1.1 at the same
time, and fall-over mode is necessary. Otherwise, the API and
implementation can be simplified a lot.

Xuelei


Re: TLS ALPN Proposal v5

2015-09-25 Thread Simone Bordet
Hi,

On Fri, Sep 25, 2015 at 3:20 PM, Xuelei Fan  wrote:
> For the complication, I posted the comments in previous mail here:
>
> -
>> In case you have [HTTP/2, AP_NEW, HTTP/1.1], then you can simply
>> compose the comparators to sort first with the H2.CIPHER_COMPARATOR,
>> then with AP_NEW.CIPHER_COMPARATOR.
>>
>> cipherSuites = Arrays.sort(cipherSuites,
>>ApplicationProtocol.H2.CIPHER_COMPARATOR.
>>thenComparing(AP_NEW.CIPHER_COMPARATOR));
>>
> Let's look at an example.  application_protocol_1 prefer cipher_suite_1,
> and application_protocol_1 prefer cipher_suite_2.
>
> The comparator for application_protocol_1 would set the preference as
> {cipher_suite_1, cipher_suite_2}.  and the comparator for
> application_protocol_2} would set the preference as {cipher_suite_2,
> cipher_suite_1}.
>
> The result to sort 1 and then 2, and the result to sort 2 and then 1 are
> different.
>
> The call sequence to the comparators, and the call to each comparator
> would result in difference result.  That's may be not the expected behavior.

The example is malformed, since it does not specify which ciphers are
good for which application protocol, and neither the order of the
application protocols.

Let me rewrite it:

application protocols: [ap1, ap2]
ciphers: [c1, c2]

ap1 requires c1, does not work with c2
ap2 requires c2, does not work with c1

Now the question is: you have to configure your system, what you want to do ?

If you want to favor ap1, then you sort [c1, c2]
If you want to favor ap2, then you sort [c2, c1]
If you want to favor c1, then you sort [c1, c2]
If you want to favor c2, then you sort [c2, c1]

If you want to favor ap1 *and* c2, you have to decide what is more
important between the two, because you cannot have both.

I don't see any problem, really.

That the results are different, sure, but they are predictable.
When the configuration uses one comparator, it will always be that
result, and same for the other comparator.

But you configure the comparators in base of what you want to do.

-- 
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 v5

2015-09-24 Thread Bradford Wetmore


On 9/23/2015 2:33 AM, Simone Bordet wrote:

Hi,

On Wed, Sep 23, 2015 at 7:04 AM, Bradford Wetmore
 wrote:



This new proposal still requires that ciphers are sorted in a way that
matches the ApplicationProtocol order.
Would be nice if, along with the HTTP/2 blacklist, there is a HTTP/2
comparator that sorts ciphers putting the blacklisted ones at the end.


Hm...is the sample code at the end of the initial class description
insufficient?  Adding a comparator seems a little heavyweight in that it
could require access to the ciphersuite internals and would add a lot of
complexity for this one known use case.  When TLSv1.3 is done, the blacklist
stuff in HTTP/2 goes away.


Sure, but until TLS 1.3 widely deployed, applications will have to
sort the ciphers to put HTTP/2 ones before the blacklisted ones.
Providing this comparator is as trivial as providing
ApplicationProtocol.HTTP2BLACKLIST, so I thought to mention it.


I learned something today: Collections/Arrays.sort()/others are stable. 
 (i.e. equal elements will not be reordered as a result of the sort) 
My expectation of "equals" was .equals(), not return value == 0.


I was concerned that such a Comparator might reorder valid H2 suites 
from what was passed in.  Thankfully, that's not the case, so I've added 
this Comparator.  There is a warning now about "consistency with 
equals()", as the Strings obvioulsy won't be equals() and thus sorted 
sets/maps just won't work.  (See the Comparator pages for further 
discussion.)



I also don't understand why there are 2 methods for the protocol name
? What value does it bring to have 2 methods for the same thing ?


Please see the IANA registry:

http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids

for RFC 7301:

 http://www.rfc-editor.org/info/rfc7301

getProtocolName() is the IANA/IETF textual representation of the protocol
name (i.e. "Protocol" column), for example "HTTP/1.1", "SPDY/3", and "HTTP/2
over TLS".  I suppose toString() could be used instead, but thought it might
eventually output additional ALPN value state.  I don't have any concrete
plans at this point.

getNetworkSequence() is the identification sequence for the protocol (i.e.
"Identification Sequence" column), and represents the actual byte
identifiers that will travel the network in an ALPN extension.

 0x68 0x74 0x74 0x70 0x2f 0x31 0x2e 0x31 ("http/1.1")
 0x73 0x70 0x64 0x79 0x2f 0x33 ("spdy/3")
 0x68 0x32 ("h2")

When client wants to send the extension over the network, it grabs the
ApplicationProtocols values from the SSLParameters, then calls
getNetworkSequence() on each ApplicationProtocol to obtain the actual opaque
ProtocolName(1..2^8-1) to send.  Likewise on the server side, we match the
incoming active ALPN opaque values with the list of mutually agreeable ALPN
values.  And of course, send back the final selected value.


Sure, but application will have to implement two methods instead of
one, and AFAIU the JDK implementation is never calling
getProtocolName() since it's just a description for humans.


I think that a textual name will be better than:

// Output:  javax.net.ssl.ApplicationProtocol$1@1b9e1916

System.out.println(ApplicationProtocol.H2);

and there's no UTF-8 ambiguity.


I've updated the webrev to include an SSLSocket test variant, and added a
few more comments.

 http://cr.openjdk.java.net/~wetmore/8051498/webrev.14/

Hopefully things are more clear now.  Thanks for your review/comments.


I see now, thanks for the pointers !

Indulge me a bit more below on the Map passed as parameter to
ApplicationProtocol :)

IIUC, by the time we are executing the code that calls
ApplicationProtocol.match(), the TLS protocol is already chosen and
it's available in SSLSession.


Not necessarily.  This could also be called before the connection has 
even been attempted, say if the client wants to determine if the 
proposed protocols or protocol/ciphersuites it wants to use are even 
allowed by an ApplicationProtocol.



When remains is the transient value of cipher that is being chosen.
Because we already have modified the API to support the application
protocol transient value (by adding
SSLEngine.getHandshakeApplicationProtocol()) to be used by
KeyManagers, I was wondering if we cannot either:


CipherSuite is more of a Session value, so it should probably be part of 
the handshakeSSLSession.  We could set 
handshakeSSLSession.getCipherSuite() before calling the ALPN selector, 
or pass it in as part of the Map.


> A) add: String SSLEngine.getHandshakeCipherSuite(), to be used by
> ApplicationProtocol

That's kind of what we are doing already, but just in the 
ApplicationProtocol matcher instead so that it doesn't add extra methods 
to SSLSocket/SSLEngine.


And this doesn't really help the pre-connection situation where you want 
to query/filter out unacceptable values.



Re: TLS ALPN Proposal v5

2015-09-24 Thread Xuelei Fan
On 9/25/2015 7:45 AM, Bradford Wetmore wrote:
> 
> On 9/23/2015 2:33 AM, Simone Bordet wrote:
>> Hi,
>>
>> On Wed, Sep 23, 2015 at 7:04 AM, Bradford Wetmore
>>  wrote:
>>>
 This new proposal still requires that ciphers are sorted in a way that
 matches the ApplicationProtocol order.
 Would be nice if, along with the HTTP/2 blacklist, there is a HTTP/2
 comparator that sorts ciphers putting the blacklisted ones at the end.
>>>
>>> Hm...is the sample code at the end of the initial class description
>>> insufficient?  Adding a comparator seems a little heavyweight in that it
>>> could require access to the ciphersuite internals and would add a lot of
>>> complexity for this one known use case.  When TLSv1.3 is done, the
>>> blacklist
>>> stuff in HTTP/2 goes away.
>>
>> Sure, but until TLS 1.3 widely deployed, applications will have to
>> sort the ciphers to put HTTP/2 ones before the blacklisted ones.
>> Providing this comparator is as trivial as providing
>> ApplicationProtocol.HTTP2BLACKLIST, so I thought to mention it.
> 
> I learned something today: Collections/Arrays.sort()/others are stable.
>  (i.e. equal elements will not be reordered as a result of the sort) My
> expectation of "equals" was .equals(), not return value == 0.
> 
> I was concerned that such a Comparator might reorder valid H2 suites
> from what was passed in.  Thankfully, that's not the case, so I've added
> this Comparator.  There is a warning now about "consistency with
> equals()", as the Strings obvioulsy won't be equals() and thus sorted
> sets/maps just won't work.  (See the Comparator pages for further
> discussion.)
It might be not customers expected behavior to re-order/sort their
preference of cipher suites or preference.

For example, a client wants to negotiate  {HTTP2,  HTTP1.1} or {HTTP1.1,
HTTP2} and {TLS_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}.
HTTP1.1/TLS_RSA_WITH_AES_128_CBC_SHA should be negotiated per the TLS
and HTTP2 specification.  If the cipher suites are sorted,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 would be negotiated, this is not
what the customer really expected.  The customer preference should be
respected.

I don't think we really need to re-order the cipher suites.

Let's consider the following client requests (prefer cipher suite more
than application protocol; blacklisted_CS are HTTP2 blacklisted cipher
suite):

1. {HTTP2, HTTP1.1} {strong_cipher_site, blacklisted_CS}
HTTP2 and strong_cipher_site should be negotiated.  Need not to re-order
cipher suites.

2. {HTTP1.1, HTTP2} {strong_cipher_site, blacklisted_CS}
HTTP1.1 and strong_cipher_site should be negotiated. Need not to
re-order cipher suites.

3. {HTTP2, HTTP1.1} {blacklisted_CS, strong_cipher_site}
HTTP1.1 and blacklisted_CS should be negotiated. Need not to re-order
cipher suites.

4. {HTTP1.1, HTTP2} {blacklisted_CS, strong_cipher_site}
HTTP1.1 and blacklisted_CS should be negotiated. Need not to re-order
cipher suites.

5. {HTTP2} {strong_cipher_site, blacklisted_CS}
HTTP2 and strong_cipher_site should be negotiated. Need not to re-order
cipher suites.

6. {HTTP1.1} {strong_cipher_site, blacklisted_CS}
HTTP1.1 and strong_cipher_site should be negotiated. Need not to
re-order cipher suites.

7. {HTTP2} {blacklisted_CS, strong_cipher_site}
blacklisted_CS would be filtered out as it does not appy to HTTP2.  Only
strong_cipher_site presents in ClientHello message.

HTTP2 and strong_cipher_site should be negotiated. Need not to re-order
cipher suites.

8. {HTTP1.1} {blacklisted_CS, strong_cipher_site}
HTTP1.1 and blacklisted_CS should be negotiated. Need not to re-order
cipher suites.

One concern may be that, the customer is not intent to negotiate HTTP2
blacklisted cipher suite.  The customer just don't know which are the
strong cipher suites among many cipher suites.  I think we may need a
handy tool to order the cipher suites before configuration.

// there are a few cipher suites are available
String[] cipherSuites = ...  // a array of cipher suites.

// Q: Don't know the strength of them
// A: OK, there is a handy tool
cipherSuites = cipherSuiteReorder.sort(cipherSuites);

// configure the cipher suites
SSLParameters.setCipherSuites(cipherSuites);

The order also apply to the normally cipher suites configuration, not
only to application protocols.  The re-order should be called by
customers explicitly.  JSSE would better not sort them automatically.

I think, the handy sort tool cannot be simply bind to application
protocol.  For example, HTTP2 has a blacklisted cipher suites.  OK,
ApplicationProtocol.H2BLACKLISTCOMPARATOR is expected to make the sort.
 If, in the future, a new application protocol (AP_NEW) has a different
blacklist cipher suites, a new
ApplicationProtocol.APNEWBLACKLISTCOMPARATOR would be defined.  If both
{HTTP2, AP_NEW} would be requested, which comparator for the sorting
would be used?  None of them can sort the cipher suite 

Re: TLS ALPN Proposal v5

2015-09-24 Thread Simone Bordet
Hi,

On Fri, Sep 25, 2015 at 1:45 AM, Bradford Wetmore
 wrote:
> I think that a textual name will be better than:
>
> // Output:  javax.net.ssl.ApplicationProtocol$1@1b9e1916
>
> System.out.println(ApplicationProtocol.H2);
>
> and there's no UTF-8 ambiguity.

Sure, but then I would just keep getNetworkSequence(), and remove
getProtocolName(), since toString() is sufficient.
To have to implement getProtocolName(), I see it as a
non-strictly-needed burden to developers that implement
ApplicationProtocol.
I know of companies that want to use ALPN extensively because they use
many different communication protocols internally, so it won't be a
rare occasion to implement ApplicationProtocol.

> http://cr.openjdk.java.net/~wetmore/8051498/webrev.15/

I gather that the Map parameter can't be solved in other ways, right ?

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 v5

2015-09-23 Thread Simone Bordet
Hi,

On Wed, Sep 23, 2015 at 7:04 AM, Bradford Wetmore
 wrote:
>
>> This new proposal still requires that ciphers are sorted in a way that
>> matches the ApplicationProtocol order.
>> Would be nice if, along with the HTTP/2 blacklist, there is a HTTP/2
>> comparator that sorts ciphers putting the blacklisted ones at the end.
>
> Hm...is the sample code at the end of the initial class description
> insufficient?  Adding a comparator seems a little heavyweight in that it
> could require access to the ciphersuite internals and would add a lot of
> complexity for this one known use case.  When TLSv1.3 is done, the blacklist
> stuff in HTTP/2 goes away.

Sure, but until TLS 1.3 widely deployed, applications will have to
sort the ciphers to put HTTP/2 ones before the blacklisted ones.
Providing this comparator is as trivial as providing
ApplicationProtocol.HTTP2BLACKLIST, so I thought to mention it.

>> I also don't understand why there are 2 methods for the protocol name
>> ? What value does it bring to have 2 methods for the same thing ?
>
> Please see the IANA registry:
>
> http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
>
> for RFC 7301:
>
> http://www.rfc-editor.org/info/rfc7301
>
> getProtocolName() is the IANA/IETF textual representation of the protocol
> name (i.e. "Protocol" column), for example "HTTP/1.1", "SPDY/3", and "HTTP/2
> over TLS".  I suppose toString() could be used instead, but thought it might
> eventually output additional ALPN value state.  I don't have any concrete
> plans at this point.
>
> getNetworkSequence() is the identification sequence for the protocol (i.e.
> "Identification Sequence" column), and represents the actual byte
> identifiers that will travel the network in an ALPN extension.
>
> 0x68 0x74 0x74 0x70 0x2f 0x31 0x2e 0x31 ("http/1.1")
> 0x73 0x70 0x64 0x79 0x2f 0x33 ("spdy/3")
> 0x68 0x32 ("h2")
>
> When client wants to send the extension over the network, it grabs the
> ApplicationProtocols values from the SSLParameters, then calls
> getNetworkSequence() on each ApplicationProtocol to obtain the actual opaque
> ProtocolName(1..2^8-1) to send.  Likewise on the server side, we match the
> incoming active ALPN opaque values with the list of mutually agreeable ALPN
> values.  And of course, send back the final selected value.

Sure, but application will have to implement two methods instead of
one, and AFAIU the JDK implementation is never calling
getProtocolName() since it's just a description for humans.

> I've updated the webrev to include an SSLSocket test variant, and added a
> few more comments.
>
> http://cr.openjdk.java.net/~wetmore/8051498/webrev.14/
>
> Hopefully things are more clear now.  Thanks for your review/comments.

I see now, thanks for the pointers !

Indulge me a bit more below on the Map passed as parameter to
ApplicationProtocol :)

IIUC, by the time we are executing the code that calls
ApplicationProtocol.match(), the TLS protocol is already chosen and
it's available in SSLSession.
When remains is the transient value of cipher that is being chosen.
Because we already have modified the API to support the application
protocol transient value (by adding
SSLEngine.getHandshakeApplicationProtocol()) to be used by
KeyManagers, I was wondering if we cannot either:

A) add: String SSLEngine.getHandshakeCipherSuite(), to be used by
ApplicationProtocol

or

B) add: Map SSLEngine.getHandshakeParameters() or
perhaps: Map SSLParameters.getHandshakeParameters().

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 v5

2015-09-22 Thread Bradford Wetmore


> This new proposal still requires that ciphers are sorted in a way that
> matches the ApplicationProtocol order.
> Would be nice if, along with the HTTP/2 blacklist, there is a HTTP/2
> comparator that sorts ciphers putting the blacklisted ones at the end.

Hm...is the sample code at the end of the initial class description 
insufficient?  Adding a comparator seems a little heavyweight in that it 
could require access to the ciphersuite internals and would add a lot of 
complexity for this one known use case.  When TLSv1.3 is done, the 
blacklist stuff in HTTP/2 goes away.


> I don't like the first parameter of ApplicationProtocol.match() to be
> a Map;

I personally don't like the Map either, but for 
situations where we don't have a connection yet (e.g. trying to reduce 
the set of protocols and/or ciphersuites for setEnabledCiphersuites()), 
this worked.


Xuelei suggested the String->String map for future expansion, making it 
easier to add new parameters in between major releases if new ALPN 
protocols are introduced.  (For those who aren't aware, adding 
classes/methods/variables/etc. is pretty much forbidden in update 
(minor) releases, but simply adding a new string to a Map is generally OK.)


> I would prefer a full blown class at this
> point, that contains all the parameters, for example:
>
> inner class ApplicationProtocol.Info
> {
>  tlsProtocol
>  cipher
>  sslEngine
>  sessionIsResuming
>  etc.
> }

The other problem here is having a way to get at all the parameters of a 
connection.  Enumerating them all in such a class is essentially 
duplicating methods that are already currently available in the 
SSLSession (handshakeSession) + SSLSocket/SSLEngines classes.  Any 
future enhancements to SSLSocket/SSLEngine would have to be added here 
again in such a class.


> I also don't understand why there are 2 methods for the protocol name
> ? What value does it bring to have 2 methods for the same thing ?

Please see the IANA registry:


http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids

for RFC 7301:

http://www.rfc-editor.org/info/rfc7301

getProtocolName() is the IANA/IETF textual representation of the 
protocol name (i.e. "Protocol" column), for example "HTTP/1.1", 
"SPDY/3", and "HTTP/2 over TLS".  I suppose toString() could be used 
instead, but thought it might eventually output additional ALPN value 
state.  I don't have any concrete plans at this point.


getNetworkSequence() is the identification sequence for the protocol 
(i.e. "Identification Sequence" column), and represents the actual byte 
identifiers that will travel the network in an ALPN extension.


0x68 0x74 0x74 0x70 0x2f 0x31 0x2e 0x31 ("http/1.1")
0x73 0x70 0x64 0x79 0x2f 0x33 ("spdy/3")
0x68 0x32 ("h2")

When client wants to send the extension over the network, it grabs the 
ApplicationProtocols values from the SSLParameters, then calls 
getNetworkSequence() on each ApplicationProtocol to obtain the actual 
opaque ProtocolName(1..2^8-1) to send.  Likewise on the server side, we 
match the incoming active ALPN opaque values with the list of mutually 
agreeable ALPN values.  And of course, send back the final selected value.


> RFC 7301 hints that the bytes to send over the network are the UTF-8
> bytes from that string.

Intentional, this ApplicationProtocol class and these two contained 
values eliminate that problem.  There is no UTF-8 to network byte 
conversion needed.  The network sequence is hard-coded into the 
ApplicationProtocol and is used directly as the network bytes.  The 
protocolName string is for user clarity.


> There are still a lot of details missing, such as where is the chosen
> ALPN value stored

In SSLSocket/SSLEngine.

If the connection is in the middle of a handshake and you need the 
handshake value:


getHandshakeApplicationProtocol()

Once the connection has finished handshaking, you can get the 
final/active value:


getApplicationProtocol()

The ALPN value is no longer in SSLSession, since it needs to be 
per-connection, not per session.


>  (and how it can be retrieved by the KeyManager, for
> example),

JSSE makes calls to X509KeyManagers (for SSLSockets) and 
X509ExtendedKeyManager (for SSLEngines).  The chooseServerAlias methods 
are passed SSLSocket/SSLEngines for the connection being negotiated.


As above, SSLSocket/SSLEngine now have:

getHandshakeApplicationProtocol();  // if handshaking
getApplicationProtocol();   // if not handshaking

So if chooseServerAlias is called, we're in the middle of a handshake, 
and can get the ALPN value thusly:


chooseClientAlias(String[] keyType,
Principal[] issuers, Socket socket) {

...deleted...

ApplicationProtocol alpn =
socket.getHandshakeApplicationProtocol();

...deleted...

> as well as the webrev not showing any real implementation,

Yes, 

Re: TLS ALPN Proposal v5

2015-09-22 Thread Simone Bordet
Hi,

On Sat, Sep 19, 2015 at 7:15 AM, Bradford Wetmore
 wrote:
> Here is the new webrev:
>
> http://cr.openjdk.java.net/~wetmore/8051498/webrev.12/
>
> Unless there are major objections, we need to get ALPN into JDK very soon to
> make JDK 9.  We can still tweak the APIs if something is found later.
>
> Major changes:
>
> 1.  ApplicationProtocols interface + H2 + HTTP/1.1 impls
>
> Both client/server call SSLParameters.setApplicationProtocols(List<>) to set
> their preferences.
>
> The matches method can be used for:
>
> .  During server handshaking to determine an acceptable ALPN value.
>
> .  potentially during client preparation to eliminate known bad
> ciphersuites/protocols combos.  If you are going to only request TLSv1.1 and
> earlier, you can disable H2 because it won't match.
>
> In this second case, you may not have a SSLSocket/SSLEngine yet, but you
> still want to do the checks based on ciphersuite/protocol, so the second
> parameters can be null.
>
> 2.  ApplicationProtocolSelector gone.
>
> 3.  SSLParameters AP_HTTP_1_1/AP_H2 effectively moved to
> ApplicationProtocol.  Selection logic added to ApplicationProtocol.
>
> 4.  Moved ALPN values from SSLSession to SSLSocket/SSLSEngine.  Added a
> "handshaking in progress" variant.
>
> 5.  SSLSession.getPeerApplicationProtocols() and
> getHandshakeCipherSuiteList() are gone.  These are all handled internally.

This new proposal still requires that ciphers are sorted in a way that
matches the ApplicationProtocol order.
Would be nice if, along with the HTTP/2 blacklist, there is a HTTP/2
comparator that sorts ciphers putting the blacklisted ones at the end.

I don't like the first parameter of ApplicationProtocol.match() to be
a Map; I would prefer a full blown class at this
point, that contains all the parameters, for example:

inner class ApplicationProtocol.Info
{
tlsProtocol
cipher
sslEngine
sessionIsResuming
etc.
}

I also don't understand why there are 2 methods for the protocol name
? What value does it bring to have 2 methods for the same thing ?
I would just use:

class ApplicationProtocol
{
public String getName()
}

RFC 7301 hints that the bytes to send over the network are the UTF-8
bytes from that string.

There are still a lot of details missing, such as where is the chosen
ALPN value stored (and how it can be retrieved by the KeyManager, for
example), as well as the webrev not showing any real implementation,
and how exactly the ApplicationProtocol instances are called, etc.

For example, client sends ["h2"], server has ["http/1.1", "h2"]. Will
the instance of ApplicationProtocol corresponding to "http/1.1" be
invoked at all ?
If not, there is a missing step in your algorithm above, where the
implementation intersects the ALPN values from both peers.

Finally, I think this API may be suitable for the server, but not much
for the client, which is equally important.

I don't see how a client application can figure out what protocol has
been chosen by the server, because there is no final notification
about that and the API seems totally geared towards server "matching"
more than client notification. For me this is a blocker.

Can you please provide an example of how a client application would
use this new API to be notified that the server has chosen protocol
"foo" ?

I still remain convinced that - so far - the Jetty API proposal (or
the similar version that was proposed here 2-3 proposals ago) is
superior to the latest ones.

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


TLS ALPN Proposal v5

2015-09-18 Thread Bradford Wetmore

Hi all,

On 9/7/2015 7:18 AM, Simone Bordet wrote:

On Mon, Sep 7, 2015 at 5:54 AM, Bradford Wetmore
 wrote:



In general, if the ciphersuites aren't ordered properly, that should be
considered a configuration error on the part of the application(s). However,
this dynamic ALPN selection approach still allows for appropriate ALPN
values to be selected for each possible ciphersuite. That is, if the suites
were ordered H1/H2, the ALPN value should be H1.

For an example of such a selector, please see the new H2/H2+H1/H1
ApplicationProtocolSelector implementions in
ApplicationProtocolSelector.java, and how they are called in
ServerHandshaker.java.


Here is the latest:

http://cr.openjdk.java.net/~wetmore/8051498/webrev.09


Are you sure this is the latest code ?
The relevant changes in ServerHandshaker are commented out.


Yes, sorry for not making this clear.  We've had a lot of internal 
discussions about the API and how to implement it:  the comments in the 
implementation classes (sun.security.ssl) are primarily for Vinnie who 
has been working on the implementation.  But I thought they provide some 
explanation as to how things might be implemented internally so I left 
them in the webrev.



I have the feeling that ApplicationProtocolSelector (APS) is not
really an application protocol selector, but a cipher suite selector.


It was *(note past tense)* primarily an application protocol selector. 
The fact that it could also influence ciphersuite selection was an 
optimization to avoid using suites known not to work with a particular 
ALPN value, but were going to be attempted anyway (say due to a server 
misconfiguration).


However, that has changed as the API has taken a different direction.

You mentioned "session resumption" in your email, which reminded me that 
ALPN values should be attached to connections (i.e. 
SSLSocket/SSLEngine), not SSLSessions.  That simplified things in 
several areas, especially in the Protocol Selector.


We no longer have an ApplicationProtocolSelector, but rather an 
interface called ApplicationProtocol.  These are concrete 
implementations of each ALPN/NPN value, and are responsible for 
examining the state of the connection so far and to return true if the 
conditions are right.   These instances are passed as 
List to SSLParameters and then to 
SSLSocket/SSLEngines.  We have a similar but somewhat simpler server 
selection algorithm than what was described earlier:


Select TLS version

for each ciphersuite

load ALPN query with:
proposed TLS version + proposed ciphersuite
SSLSocket/SSLEngine + handshaking state

for each ALPN value
if (ALPN.matches())
temporarily assign ALPN to the
handshaking SSLSocket/SSLEngine

approve ciphersuite
calls KeyManager for alias
(can use ALPN value above)
checks cipher/MAC restrictions, etc
break;

if no errors
assign ciphersuite to handshakeSession
assign ALPN to SSLSocket/SSLEngine
assign handshakeSesion as the actual Session
to SSLSocket/SSLEngine


APS seem to conflate cipher suite selection with application protocol
selection: the return value of select() actually is a 2-tuple that
means (ciphers[0], protocol) so that returning the empty string or
null does not have any effect on protocol selection, but only on
cipher selection.


To restate the point I think you raising, "Should the ALPN selection 
mechanism influence the TLS protocol version selection mechanism?"


We had a similar discussion internally.

Why would we want to encourage/enable the selection of downrev'd TLS 
protocol versions based on ALPN values?  If we actually support the 
higher/stronger TLS version, IMHO we should be using them.


1.  I think the stronger security benefits from the later protocols 
should always take priority over ALPN values and that we shouldn't be 
encouraging downrev'ing at all. For example, if there is a 
TLSv1.2/1.1/1.0 server, and we negotiated down to 1.0 just to support 
some ALPN value (or due to a bug in the selector), we lose GCM (v1.2) 
and the explicit IV (v1.1). ALPN values are application values, which I 
would expect to not be as security sensitive as the protocol values.


2.  The server hello's protocol version is supposed to be the lower of 
that suggested by the client in the client hello and the highest 
supported by the server.  Returning a lower value just to satisfy an 
ALPN selection would indicate to anyone listening (proxy, other 
connection from same VM?) that the higher TLS values are not supported 
on this server, which I think is incorrect. Future connections to this 
server might cache this lower protocol value and lose the stronger 
protocols.


3. I would expect that "older" ALPN values will likely still be 
supported in later versions of the TLS protocol. I would be surprised if 

Re: TLS ALPN Proposal v4

2015-09-07 Thread Simone Bordet
Hi,

On Mon, Sep 7, 2015 at 5:54 AM, Bradford Wetmore
 wrote:
> IMHO, the following works well.  I've added a new method that contains the
> ordered list of ciphersuites still to be tried which is a hint for ALPNinboked
> selection, but we delay the actual ciphersuite selection until after the
> ALPN value is chosen.  So the algorithm is now:
>
> 0.  Applications (especially server) might order suites with h2
> first for TLSv1.2. sslParameters.setUseCipherSuitesOrder(true)
> should be called on the server to ensure those suites are
> tried first.
>
> 1.  Start Handshake.
>
> 2.  Internal server handshaker chooses the TLS version.
>
> 3.  The internal server handshaker finds the client/server/protocol
> version intersection of the suites, loads the initial ordered
> list into a new method on a SSLSession (obtained by the
> getHandshakeSSLSession()), then iterates through the
> ordered list of ciphersuites as usual.
>
> 4.  For each "candidate" ciphersuite, first call the
> ApplicationProtocolSelector to choose an appropriate ALPN value.
> The getHandshakeSSLSession() contains the negotiated TLS
> protocol version and the ordered ciphersuite list with the
> "candidate" suite as the first entry.
>
> Note:  If the client sent unsupported ALPN values, the Selector
> can throw a SSLHandshakeException at this point and generate the
> "no_application_protocol" alert.
>inboked
> The Selector can also either choose to ignore/skip the suite, or
> accept the suite but choose no ALPN value.
>
> 5.  Continue the ciphersuite selection routine as usual (check for
> appropriate Keys, etc).  The KeyManager now has access to the
> negotiated TLS version and ALPN value along with theit
> ciphersuite via the same/usual
> getHandshakeSSLSession().
> This satisfies the RFC 7301 goal of having
> the certificate selection mechanism use the ALPN value.
>
> As ciphersuites are removed from consideration via the
> internal iterator in 3, they are also removed from the
> corresponding SSLSession entry.
>
> 6.  When handshaking is complete, the applications should verify
> that the session parameters (protocol version, ALPN value, and
> ciphersuites, etc.) are suitable, and send a HTTP-level
> INADEQUATE_SECURITY (H2) if there's a problem.
>
> In general, if the ciphersuites aren't ordered properly, that should be
> considered a configuration error on the part of the application(s). However,
> this dynamic ALPN selection approach still allows for appropriate ALPN
> values to be selected for each possible ciphersuite. That is, if the suites
> were ordered H1/H2, the ALPN value should be H1.
>
> For an example of such a selector, please see the new H2/H2+H1/H1
> ApplicationProtocolSelector implementions in
> ApplicationProtocolSelector.java, and how they are called in
> ServerHandshaker.java.
>
>
> Here is the latest:
>
> http://cr.openjdk.java.net/~wetmore/8051498/webrev.09

Are you sure this is the latest code ?
The relevant changes in ServerHandshaker are commented out.

I have the feeling that ApplicationProtocolSelector (APS) is not
really an application protocol selector, but a cipher suite selector.

APS seem to conflate cipher suite selection with application protocol
selection: the return value of select() actually is a 2-tuple that
means (ciphers[0], protocol) so that returning the empty string or
null does not have any effect on protocol selection, but only on
cipher selection.
You can for example implement APS without even looking at the
application protocol, just to exclude dynamically certain ciphers from
selection (e.g. based on performance or remote IP).

I don't understand exactly bullet 5 above. If APS chooses a cipher and
a protocol, but this is not a valid combination for the KeyManager to
select a certificate, what happens ? That APS is called again, right ?
But what if that was the last cipher ? Then APS won't be called again.
How can an application know that it is done trying to select a
protocol and that the protocol it chose is actually used ?

I guess this also brings to bullet 6: how can an application verify
that the N-tuple chosen is actually a correct one ? Is there an
additional callback that is being invoked (that applications can
implement) before the ServerHello is actually sent to the client ?

A very important point that I saw in the comments is support for TLS
session resumption - this has been asked multiple times by Jetty users
that were using Jetty's ALPN (and we implemented it).
Just make sure that whatever proposal enters JDK 9, session resumption
is supported.

My preference would go to the previous proposal (akin to Jetty - I
know I am biased) where protocol selection was happening in isolation
*after* cipher 

TLS ALPN Proposal v4

2015-09-06 Thread Bradford Wetmore


Hi all,

Simone/Xuelei/I wrote:

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.

>
>Yes, that's my understanding as well.

What are the behaviors of other vendors?  Can we ask for a clarification
from both HTTP/2 and TLS WG?


and then Simone wrote:

I support Xuelei in that you should ask confirmation to the HTTP/2
editor.


Thanks for the encouragement, Simone.  As you've probably heard, I did 
contact the IETF HTTP/2 working group and posed several questions about 
expected usage[1].  I'm combining those responses plus several other 
points that came up since the last discussion.  This may be repeating 
some things already said, but serves as useful background info for those 
here that might not be following closely:


1.  HTTP/2 (aka H2) and TLSv1.3 were developed in parallel.  The H2 
designers wanted the ciphersuite restrictions in the proposed TLSv1.3. 
But since TLSv1.3 wasn't ready, they compromised by allowing TLSv1.2 to 
be used but with the restriction that only those ciphersuites that were 
expected/allowed for TLSv1.3 could be used.  That is, there is a 
blacklist of ciphersuites for TLSv1.2:  if a suite is present, it can't 
be used in TLSv1.2.  (e.g. no RSA KeyExchange, no CBC-based block 
ciphers, no stream ciphers, etc.)


2. RFC 7301 says in a couple places that it would be advantageous to 
have the chosen ALPN value used by the certificate selection mechanism 
(See sections 1 & 4).  Without a radical rewrite of the current 
selection mechanism (n-tuple), that means ALPN selection should be done 
before the ciphersuite is selected.  We could also check after, but I 
have a different approach (see below).


3. From the H2 working group discussion, a server instance will very 
likely support both H2 and legacy HTTP/1.1. This means for servers that 
prefer H2, any iterative cipher selection mechanisms needs to try the 
H2-specific ciphersuites first, then legacy non-H2 suites.  That is, the 
suites must be ordered appropriately so that the ciphersuite selection 
mechanism won't attempt a blacklisted suite before exhausting all 
H2-acceptable suites.  This ordering can be requested today in JSSE by 
the server calling sslParameters.setUseCipherSuitesOrder(true).  This 
particular point won't matter when TLSv1.3 is in play, as we wouldn't 
try those suites at all.


4. Clients may not know whether a server will be H2 or HTTP/1.1, so they 
should also appropriately sort ciphersuites based on their ALPN 
preferences.  (H2 first, H1 second.)


5. For our SunJSSE, while I think our current enabled list order is 
generally ok, we should probably reorder the ciphersuite priorities so 
that the TLSv1.3 acceptable suites are up front, with the others 
following. This prefers forward secrecy ciphersuites to our current 
ordering. I am thinking we should probably do this for JDK 9, and maybe 
backport as well. The current webrev (link below) doesn't have this yet.


6.  To avoid downgrade attacks, applications should not provide for a 
fallback mechanism.  This includes ALPN selection.


Connection#1:  {"h2", "http/1.1"} // Don't make two connections.
Connection#2:  {"http/1.1"}

POODLE was a good example where allowing fallbacks bit hard.

Of course, we can't control this at the JSSE layer, it's the application 
layer responsibility.



Tradeoff between A) change radically the OpenJDK implementation to
support an iterative processing of TLS protocols, extensions (all of
them), ciphers, aliases, etc. that would be future proof (if that is
even possible) and B) hack in just enough of what is needed to support
H2 today (for which we already have working examples) ?


Given where we are now schedule wise (integration currently due at the 
end of September), and that SunJSSE is such an iterative implementation, 
coming up with a multi-selector API is likely beyond what we can do at 
this point.


(webrev link below).

IMHO, the following works well.  I've added a new method that contains 
the ordered list of ciphersuites still to be tried which is a hint for 
ALPN selection, but we delay the actual ciphersuite selection until 
after the ALPN value is chosen.  So the algorithm is now:


0.  Applications (especially server) might order suites with h2
first for TLSv1.2. sslParameters.setUseCipherSuitesOrder(true)
should be called on the server to ensure those suites are
tried first.

1.  Start Handshake.

2.  Internal server handshaker chooses the TLS version.

3.  The internal server handshaker finds the client/server/protocol
version intersection of the suites, loads the initial ordered
list into a new method on a SSLSession (obtained by the
getHandshakeSSLSession()), then iterates through the
ordered list of 

Re: TLS ALPN Proposal v3

2015-07-25 Thread Simone Bordet
Hi,

On Fri, Jul 24, 2015 at 9:38 PM, Jason Greene jason.gre...@redhat.com wrote:
 The truth is that there is a gap between the current capabilities of TLS 
 stacks and what the specs are trying to achieve. Ultimately the desired 
 semantic the specs are trying to achieve is that every ALPN protocol can have 
 its own TLS requirements. In this case H2 wanted TLS 1.3 behavior before it 
 was released. This is basically social engineering, the newer protocol is the 
 carrot for updating your TLS stack. However there are other potential 
 scenarios, such as protocols which desire to be encrypted but unauthenticated.

 To truly resolve this gap in a future proof manner, TLS stacks need to 
 support cipher suite selection based on the combination of ALPN protocol and 
 TLS version.

Had TLS 1.3 been released before H2, we would not need to choose the
cipher suite based on ALPN + TLS version, because any TLS 1.3 cipher
would do, and the support for ALPN would be much simpler (probably
akin to SNI).
The current situation is a temporary glitch produced by the H2
specification, and requires clients and servers to implement hacks to
support H2 (sorting ciphers, etc.).

Another thing to remember is that clients and servers may implement
different ways of selecting the various TLS parameters.
While server have to choose among TLS protocol versions, ciphers,
application protocols, etc., the client can only react to what the
server chose.
For a TLS implementation, it may be simpler to implement a client
(like browsers do) than a server; I think the server algorithm would
work for clients, but not necessarily viceversa.

Tradeoff between A) change radically the OpenJDK implementation to
support an iterative processing of TLS protocols, extensions (all of
them), ciphers, aliases, etc. that would be future proof (if that is
even possible) and B) hack in just enough of what is needed to support
H2 today (for which we already have working examples) ?

Would it be possible to fit the ALPN solution that would have been
implemented if TLS 1.3 was out before HTTP/2 to support the current
situation ?

-- 
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 v3

2015-07-24 Thread Bernd Eckenfels
Am Fri, 24 Jul 2015 14:38:36 -0500
schrieb Jason Greene jason.gre...@redhat.com:
 The truth is that there is a gap between the current capabilities of
 TLS stacks and what the specs are trying to achieve. Ultimately the
 desired semantic the specs are trying to achieve is that every ALPN
 protocol can have its own TLS requirements.

Not sure if this is desireable, it was I guess the motivation, but see
below:

 In this case H2 wanted
 TLS 1.3 behavior before it was released. This is basically social
 engineering, the newer protocol is the carrot for updating your TLS
 stack. However there are other potential scenarios, such as protocols
 which desire to be encrypted but unauthenticated.

I think it is fine to define a minimum security level together with an
application protocol. If the protocol is supported the TLS stack needs
to provide the desired features, and given the fact that it will
negotiate the best protocol version you can just deny H2 if the
cipher is not good enough.

However:

 To truly resolve this gap in a future proof manner, TLS stacks need
 to support cipher suite selection based on the combination of ALPN
 protocol and TLS version.

If each ALPN can select different security parameters, this would be a
configuration and interop nightmare. Dont go that route. I would not
provide any features to enable it, nor require them. Having said that
H2 should really be less demanding.

(not sure whats the best place to discuss it, not part of the H2 group).

Gruss
Bernd


Re: TLS ALPN Proposal v3

2015-07-24 Thread Jason Greene

 On Jul 9, 2015, at 12:02 PM, Bradford Wetmore bradford.wetmore at 
 oracle.com wrote:
 
 Ok, I'll check with the HTTP/2 group tomorrow.  It appears the proper 
 list is:

Hi Brad, 

Your post to the H2 group got my attention, so I thought as a user of JSSE for 
an H2 implementation I should reply additionally here. My responses are inline:

-snip-
 
 On 7/9/2015 8:29 AM, Simone Bordet wrote:
 Hi,
 
 On Thu, Jul 9, 2015 at 1:42 AM, Bradford Wetmore
 bradford.wetmore at oracle.com wrote:
 
 Xuelei/Simone wrote:
 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.
 
 Yes, that's my understanding as well.
 
 Well, to be precise, either the application protocol is negotiated
 after the cipher (and you need cipher sorting to influence the cipher
 selection towards the application protocol you would like to choose),
 or it must happen at the same time - that is, cipher and application
 protocol must be chosen at the same time - but this implies that the
 action of choosing that tuple may be invoked multiple times with the
 current OpenJDK implementation.
 
 Note that I don't know if the fact that cipher selection is an
 iterative process is an OpenJDK implementation detail.
 If other implementations are not iterative, then perhaps they have a
 single moment where the tuple is chosen.
 
 I support Xuelei in that you should ask confirmation to the HTTP/2 editor.
 Also, remember that Firefox, Chrome, OpenSSL, nghttp2, etc. are all
 open source and their code is available to verify the behavior.

The truth is that there is a gap between the current capabilities of TLS stacks 
and what the specs are trying to achieve. Ultimately the desired semantic the 
specs are trying to achieve is that every ALPN protocol can have its own TLS 
requirements. In this case H2 wanted TLS 1.3 behavior before it was released. 
This is basically social engineering, the newer protocol is the carrot for 
updating your TLS stack. However there are other potential scenarios, such as 
protocols which desire to be encrypted but unauthenticated.

To truly resolve this gap in a future proof manner, TLS stacks need to support 
cipher suite selection based on the combination of ALPN protocol and TLS 
version. Until then h2 implementations have to rely on both peers sorting, with 
many clients taking the additional step of post-validating the selected cipher. 
With NSS this is accomplished using an API that that categorizes cipher aspects 
(e.g. not a block cipher etc). This approach, which is arguably a hack can lead 
to interop errors if the administrator has tried to influence cipher suite 
selection for other reasons. As an example, its quite common to use an abstract 
indicator (e.g GNU TLS priority strings  openssl cipher strings), and these 
may inadvertently disable ciphers now required for h2 interop. 
 
 IIUC, the HTTP/2 blacklist is just strongly recommended (...SHOULD NOT use
 any of the cipher suites...black list), but not required.  Such potential
 peers must also support such a configuration, but in general, it will not.
 See section 9.2.2.  I think it's still considered compliant to the spec tho.
 
 From experience, if a server breaks this SHOULD NOT, it won't work
 with any browser.
 We had our share of pain trying to figure out interoperability with
 browsers for Jetty :)
 Sure, it's a SHOULD NOT, but it's like a MUST NOT if you want a
 browser to talk to a Java server (or a Java client to talk to a
 current HTTP/2 server).

Yes exactly. Firefox and Chrome enforce the SHOULDs, and if negotiation results 
in a cipher that violates the SHOULDs you not only fail to establish an h2 
connection, you fail to establish any connection at all.

 
 Simone wrote two different ways to do selection:
 
 1) ... so that TLS protocol, cipher (possibly the alias too) and
 application protocol are chosen together, or
 2) we separate the TLS protocol and
 cipher negotiation (and alias) in one step, and we perform application
 protocol selection afterwards.
 
 Rather than completely redo the JSSE selection mechanism with the
 (version/ciphersuite/ALPN)-tuple idea (which would be a much more involved
 API and behavior change), I think the more straightforward solution (2) is
 better.
 
 That's what we do in Jetty's ALPN implementation too.
 Be aware that it rules out some possibility such as those mentioned by
 Michael from RFC 7301.

I’d highly recommend exploring 1) because its quite possible you will end up 
needing to go that route anyway based on the above reasoning.

-snip-

 
 http://cr.openjdk.java.net/~wetmore/8051498/webrev.04/test/javax/net/ssl/ALPN/SSLEngineAlpnHttp2.java.html
 
 See the configuration in createSSLEngines() around line 265 and 280.
 
 
 

Re: TLS ALPN Proposal v3

2015-07-09 Thread Simone Bordet
Hi,

On Thu, Jul 9, 2015 at 1:42 AM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:
 SSLParameters is a configuration class which is used to configure
 SSLSockets/SSLEngines.  SSLSession/ExtendedSSLSession is a class which holds
 negotiated Session values.  getReceivedApplicationProtocols() represents the
 Application Protocol values received from the peer, thus belongs in the
 SSLSession.

I suggest to rename

ExtendedSSLSession.getRequestedApplicationProtocols()

to

ExtendedSSLSession.getPeerApplicationProtocols()

The protocols are not really requested, they are more offered, but
IIUC the reason to add Requested to this method is to distinguish it
from SSLParameters.getApplicationProtocols() which returns the local
protocols, and in that spirit I think Peer is better for
ExtendedSSLSession.

 Xuelei/Simone wrote:
 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.

 Yes, that's my understanding as well.

Well, to be precise, either the application protocol is negotiated
after the cipher (and you need cipher sorting to influence the cipher
selection towards the application protocol you would like to choose),
or it must happen at the same time - that is, cipher and application
protocol must be chosen at the same time - but this implies that the
action of choosing that tuple may be invoked multiple times with the
current OpenJDK implementation.

Note that I don't know if the fact that cipher selection is an
iterative process is an OpenJDK implementation detail.
If other implementations are not iterative, then perhaps they have a
single moment where the tuple is chosen.

I support Xuelei in that you should ask confirmation to the HTTP/2 editor.
Also, remember that Firefox, Chrome, OpenSSL, nghttp2, etc. are all
open source and their code is available to verify the behavior.

 IIUC, the HTTP/2 blacklist is just strongly recommended (...SHOULD NOT use
 any of the cipher suites...black list), but not required.  Such potential
 peers must also support such a configuration, but in general, it will not.
 See section 9.2.2.  I think it's still considered compliant to the spec tho.

From experience, if a server breaks this SHOULD NOT, it won't work
with any browser.
We had our share of pain trying to figure out interoperability with
browsers for Jetty :)
Sure, it's a SHOULD NOT, but it's like a MUST NOT if you want a
browser to talk to a Java server (or a Java client to talk to a
current HTTP/2 server).

 Simone wrote two different ways to do selection:

 1) ... so that TLS protocol, cipher (possibly the alias too) and
 application protocol are chosen together, or
 2) we separate the TLS protocol and
 cipher negotiation (and alias) in one step, and we perform application
 protocol selection afterwards.

 Rather than completely redo the JSSE selection mechanism with the
 (version/ciphersuite/ALPN)-tuple idea (which would be a much more involved
 API and behavior change), I think the more straightforward solution (2) is
 better.

That's what we do in Jetty's ALPN implementation too.
Be aware that it rules out some possibility such as those mentioned by
Michael from RFC 7301.

 Also, it is critical to detail how the mechanism work.

 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.

 I have a working test example which shows how the ALPN APIs can be used
 for HTTP/2 clients and servers. It is a minor configuration tweak to the
 jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java test that we use as
 the basis for JSSE SSLEngine testing.

Do you have a Java 9 server that can negotiate h2 with current browsers ?

 http://cr.openjdk.java.net/~wetmore/8051498/webrev.04/test/javax/net/ssl/ALPN/SSLEngineAlpnHttp2.java.html

 See the configuration in createSSLEngines() around line 265 and 280.


 http://cr.openjdk.java.net/~wetmore/8051498/webrev.04/test/javax/net/ssl/ALPN/Http2ApplicationSelector.java.html

 Note the HTTP/2 blacklist and reordering code.

 The code is not actually working yet (haven't merged API/impl repos yet),
 but shows how to configure/use this API.

Just a reminder that the cipher blacklist is only valid for TLS 1.2.
For example, if the negotiated TLS protocol is 1.3, there is no need
to look at the ciphers (nor to sort them).

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 v3

2015-07-09 Thread Bradford Wetmore
Ok, I'll check with the HTTP/2 group tomorrow.  It appears the proper 
list is:


ietf-http...@w3.org

Is that correct?

Brad



On 7/9/2015 8:29 AM, Simone Bordet wrote:

Hi,

On Thu, Jul 9, 2015 at 1:42 AM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:

SSLParameters is a configuration class which is used to configure
SSLSockets/SSLEngines.  SSLSession/ExtendedSSLSession is a class which holds
negotiated Session values.  getReceivedApplicationProtocols() represents the
Application Protocol values received from the peer, thus belongs in the
SSLSession.


I suggest to rename

ExtendedSSLSession.getRequestedApplicationProtocols()

to

ExtendedSSLSession.getPeerApplicationProtocols()

The protocols are not really requested, they are more offered, but
IIUC the reason to add Requested to this method is to distinguish it
from SSLParameters.getApplicationProtocols() which returns the local
protocols, and in that spirit I think Peer is better for
ExtendedSSLSession.


Xuelei/Simone wrote:

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.


Yes, that's my understanding as well.


Well, to be precise, either the application protocol is negotiated
after the cipher (and you need cipher sorting to influence the cipher
selection towards the application protocol you would like to choose),
or it must happen at the same time - that is, cipher and application
protocol must be chosen at the same time - but this implies that the
action of choosing that tuple may be invoked multiple times with the
current OpenJDK implementation.

Note that I don't know if the fact that cipher selection is an
iterative process is an OpenJDK implementation detail.
If other implementations are not iterative, then perhaps they have a
single moment where the tuple is chosen.

I support Xuelei in that you should ask confirmation to the HTTP/2 editor.
Also, remember that Firefox, Chrome, OpenSSL, nghttp2, etc. are all
open source and their code is available to verify the behavior.


IIUC, the HTTP/2 blacklist is just strongly recommended (...SHOULD NOT use
any of the cipher suites...black list), but not required.  Such potential
peers must also support such a configuration, but in general, it will not.
See section 9.2.2.  I think it's still considered compliant to the spec tho.


 From experience, if a server breaks this SHOULD NOT, it won't work
with any browser.
We had our share of pain trying to figure out interoperability with
browsers for Jetty :)
Sure, it's a SHOULD NOT, but it's like a MUST NOT if you want a
browser to talk to a Java server (or a Java client to talk to a
current HTTP/2 server).


Simone wrote two different ways to do selection:


1) ... so that TLS protocol, cipher (possibly the alias too) and
application protocol are chosen together, or
2) we separate the TLS protocol and
cipher negotiation (and alias) in one step, and we perform application
protocol selection afterwards.


Rather than completely redo the JSSE selection mechanism with the
(version/ciphersuite/ALPN)-tuple idea (which would be a much more involved
API and behavior change), I think the more straightforward solution (2) is
better.


That's what we do in Jetty's ALPN implementation too.
Be aware that it rules out some possibility such as those mentioned by
Michael from RFC 7301.


Also, it is critical to detail how the mechanism work.

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.


I have a working test example which shows how the ALPN APIs can be used
for HTTP/2 clients and servers. It is a minor configuration tweak to the
jdk/test/javax/net/ssl/templates/SSLEngineTemplate.java test that we use as
the basis for JSSE SSLEngine testing.


Do you have a Java 9 server that can negotiate h2 with current browsers ?


http://cr.openjdk.java.net/~wetmore/8051498/webrev.04/test/javax/net/ssl/ALPN/SSLEngineAlpnHttp2.java.html

See the configuration in createSSLEngines() around line 265 and 280.


http://cr.openjdk.java.net/~wetmore/8051498/webrev.04/test/javax/net/ssl/ALPN/Http2ApplicationSelector.java.html

Note the HTTP/2 blacklist and reordering code.

The code is not actually working yet (haven't merged API/impl repos yet),
but shows how to configure/use this API.


Just a reminder that the cipher blacklist is only valid for TLS 1.2.
For example, if the negotiated TLS protocol is 1.3, there is no need
to look at the ciphers (nor to sort them).

Thanks !



TLS ALPN Proposal v3

2015-07-08 Thread Bradford Wetmore

Greetings,

Xuelei wrote:

 I think Brad would consider our information for his design.

I did, and thanks for the all of the detailed discussion, 
Simone/Michael/Xuelei.  I've taken into account the feedback from the 
previous discussion back in June.  Here is v3 of the public ALPN API.


http://cr.openjdk.java.net/~wetmore/8051498/webrev.04/

Main points:

1.  SSLBase/SSLFunction gone

2.  New ApplicationProtocolSelector class with two select methods:

select(SSLSocket), select(SSLEngine)
throws SSLHandshakeException instead
of SSLProtocolException (oops/sorry!)

3.  @since 1.9 changes to @since 9  (changes for JDK 9)

4.  SSLSession.getCipherSuite()
a getHandshakeSession.getCipherSuite() no longer dynamic value
ALPN Selector will be called after suite has been set.

5.  Psuedo code in the SunJSSEimplementation for ALPN selection.

6.  Working HTTP 2  1.1 client/server configuration example (test).

Various responses, I'll try to attribute the original author correctly. 
 :)  If I missed a point you feel is important, please restate.


Simone wrote:
  ExtendedSSLSession
 public ListString getReceivedApplicationProtocols() {

 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 is a configuration class which is used to configure 
SSLSockets/SSLEngines.  SSLSession/ExtendedSSLSession is a class which 
holds negotiated Session values.  getReceivedApplicationProtocols() 
represents the Application Protocol values received from the peer, thus 
belongs in the SSLSession.


One other point that is not always obvious to folks is that a single 
SSLParameters object can be used to initialize multiple 
SSLEngine/SSLSocket objects.  You can configure sockets as part of a 
customer SSLSocketFactory, or by using SSLParameters.


Regarding the old SSLFunction/SSLBase:

 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.

Previously it was suggested that the ALPN selector could be a 
@FunctionalInterface (Simone?) and generic (Sean?), so I was trying to 
accommodate that.  Both are gone now.  We could still introduce a 
SSLBase with these methods:


---begin---
public abstract String[] getEnabledCipherSuites()
public abstract void setEnabledCipherSuites(String[] suites)

public abstract String[] getEnabledProtocols()
public abstract void setEnabledProtocols(String[] protocols)

public abstract boolean getEnableSessionCreation()
public abstract void setEnableSessionCreation(boolean flag)

public SSLSession getHandshakeSession()
minor tweak for SSLSocket about getSession()

public abstract void setNeedClientAuth(boolean need)
public abstract boolean getNeedClientAuth()

public abstract SSLSession getSession()
minor tweak needed in SSLSocket

public abstract String[] getSupportedCipherSuites()

public abstract String[] getSupportedProtocols()

public abstract boolean getUseClientMode()
public abstract void setUseClientMode(boolean mode)

public abstract boolean getWantClientAuth()
public abstract void setWantClientAuth(boolean want)

public SSLParameters getSSLParameters()
public void setSSLParameters(SSLParameters params)
---end---

which would eliminate the SSLEngine/SSLSocket-specific methods in 
ApplicationProtocolSelector.java, but I'm not sure it's worth the effort 
to isolate all these methods just to lose one method in the ALPN selector.


To do this as a @FunctionInterface, I wanted to use 
java.util.function.Function, but needed it to return a checked 
Exception. Anyway, it's gone for now.


 On the same note, why is SSLFunction generic at all ?

This was an internal idea that in the future there might be additional 
SSL functions we could do as lambdas.


Xuelei/Simone wrote:
 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.

Yes, that's my understanding as well.

Simone wrote:

 Currently, IIUC, the cipher selection is an iterative process where a
 cipher is attempted until one is negotiated.

Yes.

Simone wrote:

 Yesterday a browser could open a page and browse the site over
 http/1.1.

From my readings of the RFC, I agree with Simone and think the intent 
of the RFC writers was that if a sufficient connection state does not 
exist for HTTP/2, then it should be possible to fallback to something 
else instead of killing the connection. If the implementation wants to 
insist on HTTP/2 only, the ALPN selector can certainly enforce that, but 
it needs to try the H2 ciphersuites first.


With this API, we can do either style.


Re: TLS ALPN Proposal v3

2015-07-08 Thread Xuelei Fan
On 7/9/2015 7:42 AM, Bradford Wetmore wrote:
 Xuelei/Simone wrote:
 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.
 
 Yes, that's my understanding as well.
What are the behaviors of other vendors?  Can we ask for a clarification
from both HTTP/2 and TLS WG?

Thanks,
Xuelei


Re: TLS ALPN Proposal v2

2015-06-05 Thread Michael McMahon

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

2015-06-05 Thread Xuelei Fan
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

2015-06-05 Thread Simone Bordet
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

2015-06-05 Thread Xuelei Fan
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

2015-06-05 Thread Simone Bordet
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

2015-06-05 Thread Xuelei Fan
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

2015-06-04 Thread Bradford Wetmore


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

2015-06-04 Thread Xuelei Fan
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

2015-06-04 Thread Xuelei Fan
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

2015-06-04 Thread Simone Bordet
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

2015-06-04 Thread Simone Bordet
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

2015-06-04 Thread Xuelei Fan
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

2015-06-04 Thread Michael McMahon

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

2015-06-04 Thread Xuelei Fan
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

2015-06-04 Thread Simone Bordet
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

2015-06-04 Thread Simone Bordet
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

2015-06-04 Thread Simone Bordet
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

2015-06-04 Thread Michael McMahon

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

2015-06-03 Thread Xuelei Fan
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
  

TLS ALPN Proposal v2

2015-06-02 Thread Bradford Wetmore

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.

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.

Thanks,

Brad

[1] http://mail.openjdk.java.net/pipermail/security-dev/2015-May/012183.html


Re: TLS ALPN Proposal

2015-05-29 Thread Bradford Wetmore

Simone,

I'm sorry for the delay in responding, I've been getting familiar with 
lambdas the last couple days, and how we might be able to apply it to 
the ALPNSelector code.  Interesting stuff.



To the question in this email.  I'll leave the previous discussion for 
context.  See my responses inline.


On 5/27/2015 4:47 AM, Simone Bordet wrote:

Hi,

On Tue, May 26, 2015 at 8:46 PM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:

I am not sure I follow this. Can you please sketch the steps/algorithm
that will be done in your proposed solution ?


I'm assuming you are talking about 1a and not 1b.

Sure, most of the heavy lifting takes place in ServerHandshaker.

ServerHandshaker.java
=

In the SunJSSE code:

 // currently line 330.
 private void clientHello(ClientHello mesg) throws IOException {

 // Was an ALPNExtension received?
 ALPNExtension alpnExt = (ALPNExtension)
 mesg.extensions.get(ExtensionTyp.EXT_ALPN);
...
 // Currently line 706 in JDK9.
 session = new SSLSessionImpl(protocolVersion,
  CipherSuite.C_NULL,
  getLocalSupportedSignAlgs(),
  sslContext.getSecureRandom(),
  getHostAddressSE(), getPortSE());
...
 session.setALPNNames(alpnExt.getNames());
...
 // choose cipher suite and corresponding private key
 // This function is at 987 currently.
 chooseCipherSuite(mesg);
...
 // Only adds an ALPN extension if non-empty.
 m1.extensions.add(applicationProtocolSelector.select(...));
...

Above, chooseCipherSuite() iterates through the collection of suites. Inside
that, trySetCipherSuite() attempts to verify that the suite is acceptable to
use.  Inside that, setupPrivateKeyAndChain() does the actual KeyManager
calls.

 if (conn != null) {
 alias = km.chooseServerAlias(algorithm, null, conn);
 } else {
 alias = km.chooseEngineServerAlias(algorithm, null, engine);
 }

Now in the Application's Code:

If you want the KeyManager to take this info into account, you need to
create your own customer KM.

public String chooseEngineServerAlias(String keyType,
   Principal[] issuers,
   SSLEngine engine) {

 ExtendedSSLSession session = engine.getHandshakeSession();
 String protocol = session.getProtocol();
 String ciphersuite = session.getCipherSuite();
 ListString alpns =
 session.getRequestedApplicationProtocolNames();

 // Some logic for which key to use...
 return choose(protocol, ciphersuite, alpns);
}

And then your actual ALPN selector:

public String select(...) throws SSLProtocolException {
 ExtendedSSLSession session = engine.getHandshakeSession()
 String ciphersuite = session.getCipherSuite();
 ListString alpns =
 session.getRequestedApplicationProtocolNames();

 // Some logic for which key to use...
 return choose(protocol, ciphersuite, alpns);
}

Hopefully that is clear.


Let me see if I understand correctly.

In chooseEngineServerAlias() I will have a proposed cipher and the
list of app protos from the client.
The goal would be to choose the alias based on the app proto, as stated by 7301.

However, the app proto is not yet chosen here. If I don't have other
constraints to choose the app proto (e.g. SNI), the usual algorithm
applies: pick the first server app proto that is in common with the
client.
Let's assume this is h2; but looking at the cipher, it's not good, so
we have to pick another app proto, say http/1.1. Now the cipher is
good and we return the alias.
This is similar to what happens now with Jetty's ALPN: the cipher will
be chosen, then the ALPN callback invoked and there, by looking at the
cipher, we know we have to use http/1.1.

Let's assume now I have the constraint to choose h2 (e.g. I have a SNI
of http2.domain.com).
In chooseEngineServerAlias() I will look at SNI, and therefore choose
h2, then look at the proposed cipher, which is not good, so return
null.
Method chooseEngineServerAlias() will be called repeatedly for other
ciphers, until a cipher good for h2 is found, otherwise it's an alert
120.


Correct.  To expand a bit...

You will have the SSLSocket/SSLEngine which will give you access to the 
Socket's attributes (e.g. local/remote IP address/ports), along with the 
handshakeSession which is being negotiated.  The handshakeSession will 
give access to the selected TLS protocol version number plus the 
received SNI and ALPN names.  With my change to the ciphersuites, it 
will now give you to the proposed ciphersuite, the one being probed 
for valid key material.  If your custom KeyManager don't like this 
combination of protocol/ciphersuite/sni/alpn/Socket attributes, the 
KeyManager can report back no valid key material is available, thus 

Re: TLS ALPN Proposal

2015-05-27 Thread Simone Bordet
Hi,

On Tue, May 26, 2015 at 8:46 PM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:
 I am not sure I follow this. Can you please sketch the steps/algorithm
 that will be done in your proposed solution ?

 I'm assuming you are talking about 1a and not 1b.

 Sure, most of the heavy lifting takes place in ServerHandshaker.

 ServerHandshaker.java
 =

 In the SunJSSE code:

 // currently line 330.
 private void clientHello(ClientHello mesg) throws IOException {

 // Was an ALPNExtension received?
 ALPNExtension alpnExt = (ALPNExtension)
 mesg.extensions.get(ExtensionTyp.EXT_ALPN);
 ...
 // Currently line 706 in JDK9.
 session = new SSLSessionImpl(protocolVersion,
  CipherSuite.C_NULL,
  getLocalSupportedSignAlgs(),
  sslContext.getSecureRandom(),
  getHostAddressSE(), getPortSE());
 ...
 session.setALPNNames(alpnExt.getNames());
 ...
 // choose cipher suite and corresponding private key
 // This function is at 987 currently.
 chooseCipherSuite(mesg);
 ...
 // Only adds an ALPN extension if non-empty.
 m1.extensions.add(applicationProtocolSelector.select(...));
 ...

 Above, chooseCipherSuite() iterates through the collection of suites. Inside
 that, trySetCipherSuite() attempts to verify that the suite is acceptable to
 use.  Inside that, setupPrivateKeyAndChain() does the actual KeyManager
 calls.

 if (conn != null) {
 alias = km.chooseServerAlias(algorithm, null, conn);
 } else {
 alias = km.chooseEngineServerAlias(algorithm, null, engine);
 }

 Now in the Application's Code:

 If you want the KeyManager to take this info into account, you need to
 create your own customer KM.

 public String chooseEngineServerAlias(String keyType,
   Principal[] issuers,
   SSLEngine engine) {

 ExtendedSSLSession session = engine.getHandshakeSession();
 String protocol = session.getProtocol();
 String ciphersuite = session.getCipherSuite();
 ListString alpns =
 session.getRequestedApplicationProtocolNames();

 // Some logic for which key to use...
 return choose(protocol, ciphersuite, alpns);
 }

 And then your actual ALPN selector:

 public String select(...) throws SSLProtocolException {
 ExtendedSSLSession session = engine.getHandshakeSession()
 String ciphersuite = session.getCipherSuite();
 ListString alpns =
 session.getRequestedApplicationProtocolNames();

 // Some logic for which key to use...
 return choose(protocol, ciphersuite, alpns);
 }

 Hopefully that is clear.

Let me see if I understand correctly.

In chooseEngineServerAlias() I will have a proposed cipher and the
list of app protos from the client.
The goal would be to choose the alias based on the app proto, as stated by 7301.

However, the app proto is not yet chosen here. If I don't have other
constraints to choose the app proto (e.g. SNI), the usual algorithm
applies: pick the first server app proto that is in common with the
client.
Let's assume this is h2; but looking at the cipher, it's not good, so
we have to pick another app proto, say http/1.1. Now the cipher is
good and we return the alias.
This is similar to what happens now with Jetty's ALPN: the cipher will
be chosen, then the ALPN callback invoked and there, by looking at the
cipher, we know we have to use http/1.1.

Let's assume now I have the constraint to choose h2 (e.g. I have a SNI
of http2.domain.com).
In chooseEngineServerAlias() I will look at SNI, and therefore choose
h2, then look at the proposed cipher, which is not good, so return
null.
Method chooseEngineServerAlias() will be called repeatedly for other
ciphers, until a cipher good for h2 is found, otherwise it's an alert
120.

Are you proposing to call select(...) from chooseEngineServerAlias(),
and give the ALPN callback a semantic that it may be called multiple
times, each time with a different cipher, and give access to the ALPN
callback implementation to SNI to choose the right protocol based on
that ?

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

2015-05-26 Thread Simone Bordet
Hi,

On Tue, May 26, 2015 at 2:30 AM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:
 Darn those Chicken/Eggs [1]!

 Yes, you are correct.  The steps for the current server code:

 1.  The ClientHello is parsed, and the SNI matcher callback is called. It
 does not return which value was matched in the ServerHello, just whether a
 SNI name was matched or not:

 The extension_data field of this extension SHALL be
 empty.

 2.  Begin generating the ServerHello, choose the Protocol Version.

 3.  Iterate through the list of client's ciphersuites and call the Server's
 KeyManager (KM) callback until the KM returns key material we can use.  A
 return string selects the proposed ciphersuite.

 So we currently don't know the selected ciphersuite until the KM has been
 called (possibly multiple times).

 If we choose the ALPN before the ciphersuite, the ciphersuite selection may
 end up being inappropriate (HTTP/2 blacklist).  If we choose the ciphersuite
 first, then the ALPN value wasn't used to drive the certificate selection.

 Two suggestions in preferred order below.

 In each of these cases, unfortunately there is currently no indication of
 the proposed Ciphersuite, so we need to modify the behavior of
 getHandshakeSession().getCipherSuite() to fill in the proposed CipherSuite
 before the call to the KM.  This seems ok with the current wording, but we'd
 need to make that explicit.  This value will change for each ciphersuite/KM
 choice attempt.

 Each suggestion below is followed by our previously proposed ALPN callback
 to make the actual ALPN value selection:


 1a.  Add a parallel method to ExtendedSSLSession:

 public ListString getRequestedApplicationProtocolNames();

 along with the previously proposed selected name:

 public String getApplicationProtocol()

 (I'll be changing these names.  I'm open to suggestions).

 When the KM is called, the TLS protocol (e.g. TLSv1.2) has already been
 selected.

 Both of the major selection parameters (protocol/proposed ciphersuite) are
 now available, and applications have access to the ordered ALPN list to see
 what the client's requested values were.

 -or-

 1b.  Keep API as is, and make two callbacks.  This first is an advisory
 value, the TLS protocol version and proposed ciphersuite will be available
 in getHandshakeSession().  The second callback sets the final value that
 will be sent.


 I think 1.a is my preference.

I am not sure I follow this. Can you please sketch the steps/algorithm
that will be done in your proposed solution ?

-- 
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

2015-05-26 Thread Bradford Wetmore

 I am not sure I follow this. Can you please sketch the steps/algorithm
 that will be done in your proposed solution ?

I'm assuming you are talking about 1a and not 1b.

Sure, most of the heavy lifting takes place in ServerHandshaker.

ServerHandshaker.java
=

In the SunJSSE code:

// currently line 330.
private void clientHello(ClientHello mesg) throws IOException {

// Was an ALPNExtension received?
ALPNExtension alpnExt = (ALPNExtension)
mesg.extensions.get(ExtensionTyp.EXT_ALPN);
...
// Currently line 706 in JDK9.
session = new SSLSessionImpl(protocolVersion,
 CipherSuite.C_NULL,
 getLocalSupportedSignAlgs(),
 sslContext.getSecureRandom(),
 getHostAddressSE(), getPortSE());
...
session.setALPNNames(alpnExt.getNames());
...
// choose cipher suite and corresponding private key
// This function is at 987 currently.
chooseCipherSuite(mesg);
...
// Only adds an ALPN extension if non-empty.
m1.extensions.add(applicationProtocolSelector.select(...));
...

Above, chooseCipherSuite() iterates through the collection of suites. 
Inside that, trySetCipherSuite() attempts to verify that the suite is 
acceptable to use.  Inside that, setupPrivateKeyAndChain() does the 
actual KeyManager calls.


if (conn != null) {
alias = km.chooseServerAlias(algorithm, null, conn);
} else {
alias = km.chooseEngineServerAlias(algorithm, null, engine);
}

Now in the Application's Code:

If you want the KeyManager to take this info into account, you need to 
create your own customer KM.


public String chooseEngineServerAlias(String keyType,
  Principal[] issuers,
  SSLEngine engine) {

ExtendedSSLSession session = engine.getHandshakeSession();
String protocol = session.getProtocol();
String ciphersuite = session.getCipherSuite();
ListString alpns =
session.getRequestedApplicationProtocolNames();

// Some logic for which key to use...
return choose(protocol, ciphersuite, alpns);
}

And then your actual ALPN selector:

public String select(...) throws SSLProtocolException {
ExtendedSSLSession session = engine.getHandshakeSession()
String ciphersuite = session.getCipherSuite();
ListString alpns =
session.getRequestedApplicationProtocolNames();

// Some logic for which key to use...
return choose(protocol, ciphersuite, alpns);
}

Hopefully that is clear.

Brad


On 5/26/2015 1:00 AM, Simone Bordet wrote:

Hi,

On Tue, May 26, 2015 at 2:30 AM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:

Darn those Chicken/Eggs [1]!

Yes, you are correct.  The steps for the current server code:

1.  The ClientHello is parsed, and the SNI matcher callback is called. It
does not return which value was matched in the ServerHello, just whether a
SNI name was matched or not:

 The extension_data field of this extension SHALL be
 empty.

2.  Begin generating the ServerHello, choose the Protocol Version.

3.  Iterate through the list of client's ciphersuites and call the Server's
KeyManager (KM) callback until the KM returns key material we can use.  A
return string selects the proposed ciphersuite.

So we currently don't know the selected ciphersuite until the KM has been
called (possibly multiple times).

If we choose the ALPN before the ciphersuite, the ciphersuite selection may
end up being inappropriate (HTTP/2 blacklist).  If we choose the ciphersuite
first, then the ALPN value wasn't used to drive the certificate selection.

Two suggestions in preferred order below.

In each of these cases, unfortunately there is currently no indication of
the proposed Ciphersuite, so we need to modify the behavior of
getHandshakeSession().getCipherSuite() to fill in the proposed CipherSuite
before the call to the KM.  This seems ok with the current wording, but we'd
need to make that explicit.  This value will change for each ciphersuite/KM
choice attempt.

Each suggestion below is followed by our previously proposed ALPN callback
to make the actual ALPN value selection:


1a.  Add a parallel method to ExtendedSSLSession:

 public ListString getRequestedApplicationProtocolNames();

along with the previously proposed selected name:

 public String getApplicationProtocol()

(I'll be changing these names.  I'm open to suggestions).

When the KM is called, the TLS protocol (e.g. TLSv1.2) has already been
selected.

Both of the major selection parameters (protocol/proposed ciphersuite) are
now available, and applications have access to the ordered ALPN list to see
what the client's requested values were.

-or-

1b.  Keep API as is, and make two callbacks.  This first is an advisory
value, the TLS protocol version and proposed 

Re: TLS ALPN Proposal

2015-05-25 Thread Michael McMahon

Hi Brad,

A couple of initial comments/questions.

1) Certificate selection is one feature envisaged by ALPN. ie a client 
or a server
ought to be able to choose a different certificate depending on the 
application name

that gets negotiated. Is that possible with this API?

2) The notion of client preference needs to be made explicit. This could 
just be a matter
of javadoc given that ListString is ordered. So, it could be 
enough to say the same

order is used in the protocol.

3) It's a shame that the RFC didn't mandate UTF8 encoded byte sequences 
for the
protocol name, because it's theoretically possible that non UTF8 
byte sequences

could get registered, but that's not a concern for HTTP/2 at least.

Thanks,
Michael

On 22/05/15 01:55, Bradford Wetmore wrote:

This is a fork of the previous thread:

Subject:  TLS Handshake Message Proposal
  (Was: Re: JEP 244: TLS Application-Layer Protocol
  Negotiation Extension)

I broke this thread off to keep this proposal discussion together, but 
if you're interested in the history, please see the previous thread.


This approach combines different suggestions from security-dev in a 
new way, and simplifies the ALPN selection process quite a bit. I 
think it addresses most of the concerns about selection that were raised.


This approach can be completely separated from the Handshake mechanism 
I discussed in the previous message, so I'm thinking of this approach 
for JDK 9 and targeting the more general handshake approach for JDK 10.


Here's the summary of API additions:


SSLParameters:
--
Client-side:  gets/sets the list of protocol names to send.
Server-side:  gets/sets a ApplicationProtocolSelector which is a
  user-defined callback mechanism.

ApplicationProtocolSelector:

Server-side:  callback methods for SSLSocket/SSLEngine which
  are provided with handshake information for making
  the selection

ExtendedSSLSession:
---
gets the negotiated protocol String



Specifics below.  The javadoc obviously needs work.

class SSLParameters {

...deleted...

/**
 * Gets the list of application protocols that will sent by
 * the client.
 *
 * The list could be empty, in which case no protocols will be
 * sent.
 *
 * @returns a list of application protocol names.
 */
public ListString getApplicationProtocols() { };

/**
 * Sets the list of application protocols that will sent by
 * the client.
 *
 * protocols could be empty, in which case no protocols will be
 * sent.
 *
 * @param protocols a list of application protocol names
 * @throws IllegalArgumentException if protocols is null.
 */
public void setApplicationProtocols(ListString protocols);

/**
 * Gets the current server-side application layer protocol selector.
 *
 * @param the selector mechanism.
 * @return the current application protocol selector, or null if
 * there is not one.
 */
public ApplicationProtocolSelector
getApplicationProtocolSelector() {};

/**
 * Sets the server-side application layer protocol selector.
 *
 * @param the selector mechanism, or null if protocol selection
 * should not be done.
 */
public void setApplicationProtocolSelector(
ApplicationProtocolSelector selector) {};
}


/*
 * A callback class on the server side that is responsible for
 * choosing which Application Protocol should be used in a SSL/TLS
 * connection.
 */
public abstract class ApplicationProtocolSelector {

/*
 * SSLSocket callback to choose which Application Protocol value
 * to return to a SSL/TLS client
 *
 * @param sslSocket the SSLSocket for this connection
 * @param protocols the list of protocols advertised by the client
 * @param protocolVersion the negotiated protocol version
 * @param ciphersuite the negotiated ciphersuite
 * @return a non-empty protocol String to send to the client,
 * or null if no protocol value (i.e. extension) should be sent.
 * @throws SSLProtocolException if the connection should be aborted
 * because the the server supports none of the protocols that
 * the client advertised.
 */
public String select(SSLSocket sslSocket, String[] protocols,
String protocolVersion, String ciphersuite)
throws SSLProtocolException;

/*
 * SSLEngine callback to choose which Application Protocol to return
 * to a SSL/TLS client.
 *
 * @param sslEngine the SSLEngine for this connection
 * @param protocols the list of protocols advertised by the client
 * @param protocolVersion the negotiated protocol version
 * @param ciphersuite the negotiated ciphersuite
 * @return a non-empty protocol String to send to the client,
 * or null if no 

Re: TLS ALPN Proposal

2015-05-25 Thread Simone Bordet
Hi,

On Mon, May 25, 2015 at 12:08 PM, Michael McMahon
michael.x.mcma...@oracle.com wrote:
 Hi Brad,

 A couple of initial comments/questions.

 1) Certificate selection is one feature envisaged by ALPN. ie a client or a
 server
 ought to be able to choose a different certificate depending on the
 application name
 that gets negotiated. Is that possible with this API?

Interesting.

I can definitely see choosing the ALPN protocol based on the SNI name
sent by the client.
For example, a server able to speak http/1.1 and h2 receiving a
request for http1.domain.com wants to force http/1.1.
This would be possible, IIUC, using
sslEngine.getHandshakeSession().getRequestedServerNames() in the
ApplicationProtocolSelector implementation.

I see less common choosing the certificate given the application
protocol, but I understand it's mentioned in RFC 7301.

ALPN definitely needs the cipher to be negotiated to support HTTP/2,
so I hope it's not a chicken-egg problem.

-- 
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

2015-05-25 Thread Michael McMahon

On 25/05/15 12:34, Simone Bordet wrote:

Hi,

On Mon, May 25, 2015 at 12:08 PM, Michael McMahon
michael.x.mcma...@oracle.com wrote:

Hi Brad,

A couple of initial comments/questions.

1) Certificate selection is one feature envisaged by ALPN. ie a client or a
server
 ought to be able to choose a different certificate depending on the
application name
 that gets negotiated. Is that possible with this API?

Interesting.

I can definitely see choosing the ALPN protocol based on the SNI name
sent by the client.
For example, a server able to speak http/1.1 and h2 receiving a
request for http1.domain.com wants to force http/1.1.
This would be possible, IIUC, using
sslEngine.getHandshakeSession().getRequestedServerNames() in the
ApplicationProtocolSelector implementation.


Perhaps, though it seems there are specific ALPNs for HTTP/1.1 (http/1.1)
and for HTTP/2 (h2). So, I think you would use ALPN itself to do that 
negotiation.
An incoming TLS connection without the ALPN extension is just assumed to 
be HTTP/1.1



I see less common choosing the certificate given the application
protocol, but I understand it's mentioned in RFC 7301.


There aren't very many different applications envisaged yet. There are
a couple of NAT related protocols registered. But, actually having 
thought about it
again, client certificate selection happens in the 
X509ExtendedKeyManager class
and that implementation could presumably call 
sslEngine.getHandshakeSession().getApplicationProtocol()
and select the client cert using that information. It doesn't do that 
now obviously

but I think it could in future if necessary.


ALPN definitely needs the cipher to be negotiated to support HTTP/2,
so I hope it's not a chicken-egg problem.



I've been assuming that (by default) we just need to avoid using the 
black-listed
ciphers and make sure to propose at least the one mandatory cipher; then 
we shouldn't
have any problem. HTTP/2 apps can still create their own SSLContexts and 
configure

them any way they want.

- Michael.


Re: TLS ALPN Proposal

2015-05-25 Thread Simone Bordet
Hi,

On Mon, May 25, 2015 at 3:57 PM, Michael McMahon
michael.x.mcma...@oracle.com wrote:
 Perhaps, though it seems there are specific ALPNs for HTTP/1.1 (http/1.1)
 and for HTTP/2 (h2). So, I think you would use ALPN itself to do that
 negotiation.
 An incoming TLS connection without the ALPN extension is just assumed to be
 HTTP/1.1

Sure, but I can see a client looping over a list of domain names (e.g.
to check whether the sites support HTTP/2) and therefore not having
any knowledge of whether it should or not add the ALPN extension.
This client will always add it, but the server must force http/1.1 for
http1.domain.com.

 There aren't very many different applications envisaged yet. There are
 a couple of NAT related protocols registered. But, actually having thought
 about it
 again, client certificate selection happens in the X509ExtendedKeyManager
 class
 and that implementation could presumably call
 sslEngine.getHandshakeSession().getApplicationProtocol()
 and select the client cert using that information. It doesn't do that now
 obviously
 but I think it could in future if necessary.

Sure, unless the protocol is not available because ALPN code has not run yet.
For what I understand, currently cipher selection and certificate
selection happen at the same time, please correct me if I am wrong.

If that's the case, then we have a chicken-egg problem: you can't call
ALPN code before the cipher is selected, but you need ALPN to select
the certificate.
If those two steps can be split, then ALPN code could be put in
between and all is solved.

-- 
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

2015-05-25 Thread Bradford Wetmore



On 5/22/2015 8:28 PM, Weijun Wang wrote:



On 5/23/2015 9:13 AM, Bradford Wetmore wrote:

Weijun wrote:

  But in the RFC the name is in uppercase and chars in string are all
  lowercases.
  ...deleted...
  - Compare with equalsIgnoreCase()

Not following here, the spec is specific about the over-the-wire byte
values, and http/1.1 != Http/1.1.


Because the spec says

o  Identification Sequence: The precise set of octet values that
   identifies the protocol.  This could be the UTF-8 encoding
   [RFC3629] of the protocol name.

and the name is uppercase. What if someone really sends
HTTP/1.1.getBytes(UTF-8)?


I'm sorry, but I'm still not understanding your point.  Looking at an 
existing ALPN directory entry:


   Protocol:  HTTP/1.1
   Identification Sequence:
  0x68 0x74 0x74 0x70 0x2f 0x31 0x2e 0x31 (http/1.1)
   Reference:  [RFC7230]

The name of the Protocol is HTTP/1.1, but the Identification 
Sequence is 0x68 0x74 0x74 0x70 0x2f 0x31 0x2e 0x31 (http/1.1).  I 
am proposing that the ListString be the values of the Identification 
Sequence, not the IANA Protocol Names.


Is your opinion that the ALPN API String Protocol be the Protocol: 
and that we should internally map from HTTP/1.1 to http/1.1 before 
sending?  Or that Identification Sequence HTTP/1.1 SHOULD BE treated 
the same as http/1.1?  I think that's what you're saying, since I 
think you want to compare it using equalsIgnoreCase().  That will make 
future ALPN protocol name addition challenging.


 What if someone really sends HTTP/1.1.getBytes(UTF-8)?

In my proposal, then they should send HTTP/1.1 instead of http/1.1.

I'm really sorry if I'm still missing something.

Brad



Re: TLS ALPN Proposal

2015-05-25 Thread Bradford Wetmore

Darn those Chicken/Eggs [1]!

Yes, you are correct.  The steps for the current server code:

1.  The ClientHello is parsed, and the SNI matcher callback is called. 
It does not return which value was matched in the ServerHello, just 
whether a SNI name was matched or not:


The extension_data field of this extension SHALL be
empty.

2.  Begin generating the ServerHello, choose the Protocol Version.

3.  Iterate through the list of client's ciphersuites and call the 
Server's KeyManager (KM) callback until the KM returns key material we 
can use.  A return string selects the proposed ciphersuite.


So we currently don't know the selected ciphersuite until the KM has 
been called (possibly multiple times).


If we choose the ALPN before the ciphersuite, the ciphersuite selection 
may end up being inappropriate (HTTP/2 blacklist).  If we choose the 
ciphersuite first, then the ALPN value wasn't used to drive the 
certificate selection.


Two suggestions in preferred order below.

In each of these cases, unfortunately there is currently no indication 
of the proposed Ciphersuite, so we need to modify the behavior of 
getHandshakeSession().getCipherSuite() to fill in the proposed 
CipherSuite before the call to the KM.  This seems ok with the current 
wording, but we'd need to make that explicit.  This value will change 
for each ciphersuite/KM choice attempt.


Each suggestion below is followed by our previously proposed ALPN 
callback to make the actual ALPN value selection:



1a.  Add a parallel method to ExtendedSSLSession:

public ListString getRequestedApplicationProtocolNames();

along with the previously proposed selected name:

public String getApplicationProtocol()

(I'll be changing these names.  I'm open to suggestions).

When the KM is called, the TLS protocol (e.g. TLSv1.2) has already been 
selected.


Both of the major selection parameters (protocol/proposed ciphersuite) 
are now available, and applications have access to the ordered ALPN list 
to see what the client's requested values were.


-or-

1b.  Keep API as is, and make two callbacks.  This first is an advisory 
value, the TLS protocol version and proposed ciphersuite will be 
available in getHandshakeSession().  The second callback sets the final 
value that will be sent.



I think 1.a is my preference.

To answer some of the other questions.

On 5/25/2015 3:08 AM, Michael McMahon wrote:


2) The notion of client preference needs to be made explicit. This could
just be a matter
 of javadoc given that ListString is ordered. So, it could be
enough to say the same
 order is used in the protocol.


Yes, I'll add that.


3) It's a shame that the RFC didn't mandate UTF8 encoded byte sequences
for the
 protocol name, because it's theoretically possible that non UTF8
byte sequences
 could get registered, but that's not a concern for HTTP/2 at least.


No.  Not sure what we can do about that, short of going back to the 
byte[] option.  Given that IANA operates mainly in English, I would 
expect the namespaces will probably be ASCII, but that is just conjecture.


 This would be possible, IIUC, using
 sslEngine.getHandshakeSession().getRequestedServerNames() in the
 ApplicationProtocolSelector implementation.

Yes.

 but I understand it's mentioned in RFC 7301.

Yes, see the last sentence section 1.

Brad


[1] https://www.youtube.com/watch?v=ixgf5SlvOB4feature=youtu.bet=27



Re: TLS ALPN Proposal

2015-05-23 Thread Simone Bordet
Hi,

On Sat, May 23, 2015 at 3:13 AM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:
 Thanks for the thorough reviews and comments, I really appreciate it and
 always learn something.  FunctionalInterface (@since 1.8) is something I
 haven't really explored yet, so off to the books.

Just to be clear, this is what I am proposing:

class SSLParameters
{
...
ListString getApplicationProtocols();
void setApplicationProtocols(ListString protocols);
void setApplicationProtocolSelector(ApplicationProtocolSelector selector);
ApplicationProtocolSelector getApplicationProtocolSelector();
}

@FunctionalInterface
interface ApplicationProtocolSelector
{
String select(ListString protocols) throws SSLException;
}

In this way, there is no need for a SSLBase to converge SSLSocket and
SSLEngine, the ApplicationProtocolSelector can be specified as a
lambda expression on SSLParameters, and everything is much simpler.

-- 
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

2015-05-22 Thread Weijun Wang



On 5/23/2015 9:13 AM, Bradford Wetmore wrote:

Weijun wrote:

  But in the RFC the name is in uppercase and chars in string are all
  lowercases.
  ...deleted...
  - Compare with equalsIgnoreCase()

Not following here, the spec is specific about the over-the-wire byte
values, and http/1.1 != Http/1.1.


Because the spec says

   o  Identification Sequence: The precise set of octet values that
  identifies the protocol.  This could be the UTF-8 encoding
  [RFC3629] of the protocol name.

and the name is uppercase. What if someone really sends 
HTTP/1.1.getBytes(UTF-8)?


--Max


Re: TLS ALPN Proposal

2015-05-22 Thread Bradford Wetmore
Thanks for the thorough reviews and comments, I really appreciate it and 
always learn something.  FunctionalInterface (@since 1.8) is something I 
haven't really explored yet, so off to the books.


I'm glad this ALPN approach seems worth pursing.  I have several 
different comments I'll combine into this single message.


On 5/22/2015 9:12 AM, Simone Bordet wrote:


ExtendedSSLSession:
---
gets the negotiated protocol String


If I understand correctly, SSLParameters will have methods that can
only be used by one side of the TLS protocol (e.g. client or server,
but not both).
It's already like this for other things (e.g. SNI) so it will work,
but I had hoped for some kind of reworking in this area too, but I'm
digressing.


I don't have a better idea/suggestion for this, protocol advertisement 
and selection are two very different things.  At this point, I am 
thinking it should remain in SSLParameters.


I considered putting the selector into the SSLContext initialization:

sslContext.init(KeyManager, TrustManager, SecureRandom, Selector);

but that means 1 selector for all SSLSockets/SSLEngines that get 
generated from that SSLContext.  That is constricting if the selector 
wanted to keep any connection-specific values.  It could go into 
SSLSocket/SSLEngine, but starting in JDK 6, we've been lumping all set* 
configuration parameters into SSLParameters, so that once configured, 
devs can reuse one SSLParameters object without having to reconstruct it 
(source code or at runtime) from scratch.


BTW, there was a previous question about when to use SSLSocket.set*() 
and sslSocket.setSSLParameters(params).  I gave a partial answer in:



http://mail.openjdk.java.net/pipermail/security-dev/2014-November/011430.html

I recently filed:

https://bugs.openjdk.java.net/browse/JDK-8080799
Provide guidance on repeated configuration parameter APIs

to address this.  I don't think we need to deprecate the set() methods, 
but having a note here will alleviate confusion.



/*
  * A callback class on the server side that is responsible for
  * choosing which Application Protocol should be used in a SSL/TLS
  * connection.
  */
public abstract class ApplicationProtocolSelector {

 /*
  * SSLSocket callback to choose which Application Protocol value
  * to return to a SSL/TLS client
  *
  * @param sslSocket the SSLSocket for this connection
  * @param protocols the list of protocols advertised by the client
  * @param protocolVersion the negotiated protocol version


Egads, this is confusing.  protocols is the ALPN protocols, 
protocolVersion is the TLS version number.  I'll fix this.



  * @param ciphersuite the negotiated ciphersuite
  * @return a non-empty protocol String to send to the client,
  * or null if no protocol value (i.e. extension) should be sent.
  * @throws SSLProtocolException if the connection should be aborted
  * because the the server supports none of the protocols that
  * the client advertised.


Whoops, I put exactly the Exception I didn't want to use!  I was 
originally thinking SSLHandshakeException.  See below for more comments.



  */
 public String select(SSLSocket sslSocket, String[] protocols,
 String protocolVersion, String ciphersuite)
 throws SSLProtocolException;


We are currently getting the protocolVersion and the cipherSuite via:

[sslSocket|sslEngine].getHandshakeSession().get[Protocol|CipherSuite]()

If this is correct, perhaps there is no need to pass those 2
parameters to select() ?


Good point.  Yes, those are no longer needed.

There was a suggestion to have access to the clientHello information in 
order to guide ciphersuite/protocol selection, however, there isn't a 
way to control that part of the internals at this time, so I didn't 
include it.


As an aside, if we do develop the Handshake API (other mail) and allow 
for handshake message modification (not currently proposed, but hinted 
at), the protocols/ciphersuites values could be adjusted before they are 
handled.  e.g. INBOUND callbacks would be triggered after the message 
has been parsed and added to the handshake hash calculation, but before 
clientHello() is actually called.



I would suggest that if SSLParameters.setApplicationProtocols() takes
a ListString, then also select() should take a ListString, rather
than a String[].
Since it's the server picking the protocols, would be handy to have
the client protocols in a ListString in order to call contains(),
etc. on it.


Good points.


I would suggest to throw SSLException rather than the too specific
SSLProtocolException (which may also be misleading, since its javadoc
hints at a flaw in one of the protocol implementations, while in
this case it is just a failure to negotiate an *application* protocol
- perfectly fine from the point of view of the TLS protocol).


See above.  I'll change it to SSLException for now, but I think it 

Re: TLS ALPN Proposal

2015-05-22 Thread Weijun Wang



On 5/23/2015 3:20 AM, Simone Bordet wrote:

Hi,

On Fri, May 22, 2015 at 9:14 PM, Bernd Eckenfels e...@zusammenkunft.net wrote:

I would suggest to make this encoded in latin1 instead. This is
supposed to be a 8bit clean encoding (and will be compatible to all
ASCII only strings). It is still ugly and needs to be documanted
cleanly that the string you get back might not be a string at all.


RFC 7301 hints that protocol string could be UTF-8 encoded:
http://tools.ietf.org/html/rfc7301#section-6


But in the RFC the name is in uppercase and chars in string are all 
lowercases. So maybe the preferred impl will be like this?


 - Fields use String
 - on the wire UTF-8
 - Compare with equalsIgnoreCase()

--Max





Re: TLS ALPN Proposal

2015-05-22 Thread Simone Bordet
Hi,

On Fri, May 22, 2015 at 2:55 AM, Bradford Wetmore
bradford.wetm...@oracle.com wrote:
 This is a fork of the previous thread:

 Subject:  TLS Handshake Message Proposal
   (Was: Re: JEP 244: TLS Application-Layer Protocol
   Negotiation Extension)

 I broke this thread off to keep this proposal discussion together, but if
 you're interested in the history, please see the previous thread.

 This approach combines different suggestions from security-dev in a new way,
 and simplifies the ALPN selection process quite a bit.  I think it addresses
 most of the concerns about selection that were raised.

 This approach can be completely separated from the Handshake mechanism I
 discussed in the previous message, so I'm thinking of this approach for JDK
 9 and targeting the more general handshake approach for JDK 10.

 Here's the summary of API additions:


 SSLParameters:
 --
 Client-side:  gets/sets the list of protocol names to send.
 Server-side:  gets/sets a ApplicationProtocolSelector which is a
   user-defined callback mechanism.

 ApplicationProtocolSelector:
 
 Server-side:  callback methods for SSLSocket/SSLEngine which
   are provided with handshake information for making
   the selection

 ExtendedSSLSession:
 ---
 gets the negotiated protocol String

If I understand correctly, SSLParameters will have methods that can
only be used by one side of the TLS protocol (e.g. client or server,
but not both).
It's already like this for other things (e.g. SNI) so it will work,
but I had hoped for some kind of reworking in this area too, but I'm
digressing.

 /*
  * A callback class on the server side that is responsible for
  * choosing which Application Protocol should be used in a SSL/TLS
  * connection.
  */
 public abstract class ApplicationProtocolSelector {

 /*
  * SSLSocket callback to choose which Application Protocol value
  * to return to a SSL/TLS client
  *
  * @param sslSocket the SSLSocket for this connection
  * @param protocols the list of protocols advertised by the client
  * @param protocolVersion the negotiated protocol version
  * @param ciphersuite the negotiated ciphersuite
  * @return a non-empty protocol String to send to the client,
  * or null if no protocol value (i.e. extension) should be sent.
  * @throws SSLProtocolException if the connection should be aborted
  * because the the server supports none of the protocols that
  * the client advertised.
  */
 public String select(SSLSocket sslSocket, String[] protocols,
 String protocolVersion, String ciphersuite)
 throws SSLProtocolException;

We are currently getting the protocolVersion and the cipherSuite via:

[sslSocket|sslEngine].getHandshakeSession().get[Protocol|CipherSuite]()

If this is correct, perhaps there is no need to pass those 2
parameters to select() ?

I would suggest that if SSLParameters.setApplicationProtocols() takes
a ListString, then also select() should take a ListString, rather
than a String[].
Since it's the server picking the protocols, would be handy to have
the client protocols in a ListString in order to call contains(),
etc. on it.

I would suggest to throw SSLException rather than the too specific
SSLProtocolException (which may also be misleading, since its javadoc
hints at a flaw in one of the protocol implementations, while in
this case it is just a failure to negotiate an *application* protocol
- perfectly fine from the point of view of the TLS protocol).

Would be great if we could make this class a FunctionalInterface, but
I guess it's not easy due to lack of commonality between SSLSocket and
SSLEngine.
Unless there is a way to abstract something out of those 2 :)

 public class ExtendedSSLSession implements SSLSession {

   ...deleted...

   /**
* Gets the application protocol negotiated for this connection.
*
* @returns the application protocol name or null if none was
* negotiated.
*/
   public String getApplicationProtocol() { };
 }

How would this case be covered:

* client sends protocol list foo,bar
* server sends back bax.
* client has to decide what to do.

The only chance to call ExtendedSSLSession.getApplicationProtocol()
would be *after* the handshake is completed, right ?
Do you plan to hardcode the abort of the handshake with an alert_120,
or give the application a chance (just asking) ?

 There was also some internal discussion about whether the values should be
 Strings or byte arrays.  The ALPN RFC only discusses bytes, and a
 String.toBytes(US-ASCII) would limit the API to ASCII strings.

 Lastly, we could also add some convenience values for well-known values.
 e.g.:

 public static final AP_HTTP_1.1 = http/1.1;

 or in byte form:

 public static final AP_H2 = h2.getBytes(US-ASCII);

 I refrained 

Re: TLS ALPN Proposal

2015-05-22 Thread Sean Mullan

On 05/22/2015 12:12 PM, Simone Bordet wrote:

Would be great if we could make this class a FunctionalInterface


Yes, that would be nice.


, but
I guess it's not easy due to lack of commonality between SSLSocket and
SSLEngine.
Unless there is a way to abstract something out of those 2:)


There's actually a bunch of methods in common, so one possibility is to 
create a new interface containing the common methods (say SSLBase for 
now for lack of a better name). Then you could change SSLEngine and 
SSLSocket to implement SSLBase (which should be a compatible change), 
and then have a single method on ApplicationProtocolSelector. Question 
is if there are enough common methods to do what you want? I don't know 
enough about ALPN to answer that question.


--Sean


Re: TLS ALPN Proposal

2015-05-22 Thread Bernd Eckenfels
  There was also some internal discussion about whether the values
  should be Strings or byte arrays.  The ALPN RFC only discusses
  bytes, and a String.toBytes(US-ASCII) would limit the API to
  ASCII strings.
 
  Lastly, we could also add some convenience values for well-known
  values. e.g.:
 
  public static final AP_HTTP_1.1 = http/1.1;
 
  or in byte form:
 
  public static final AP_H2 = h2.getBytes(US-ASCII);
 
  I refrained from including SPDY/*, since they are on their way out
  now, and NAT/STUN since there hasn't been any call for it so far.
 
 I agree that only http/1.1 and h2 deserve a constant.

I would suggest to make this encoded in latin1 instead. This is
supposed to be a 8bit clean encoding (and will be compatible to all
ASCII only strings). It is still ugly and needs to be documanted
cleanly that the string you get back might not be a string at all.

Gruss
Bernd


Re: TLS ALPN Proposal

2015-05-22 Thread Simone Bordet
Hi,

On Fri, May 22, 2015 at 8:54 PM, Sean Mullan sean.mul...@oracle.com wrote:
 There's actually a bunch of methods in common, so one possibility is to
 create a new interface containing the common methods (say SSLBase for now
 for lack of a better name). Then you could change SSLEngine and SSLSocket to
 implement SSLBase (which should be a compatible change), and then have a
 single method on ApplicationProtocolSelector. Question is if there are
 enough common methods to do what you want? I don't know enough about ALPN to
 answer that question.

There are 2 things that conflate here: one is to provide the mechanism
to support ALPN, and the second is to make sure that it is possible to
support HTTP/2.

ALPN per se, for example, does not need any information about
SSLEngine or TLS protocol versions or ciphers.
It just needs the protocol strings, so the ApplicationProtocolSelector
would just need select(ListString).

For HTTP/2, however, the choice of the protocol will depend on the TLS
version and the cipher, so we will need a way to obtain that
information.

Typically, in the code where you pass the ApplicationProtocolSelector
you have the SSLEngine available, e.g.:

sslEngine.getSSLParameters().setApplicationProtocolSelector(new
ApplicationProtocolSelector()
{
public String select(ListString clientProtocols)
{
// Here sslEngine will be in lexical scope
}
});

In this way, ApplicationProtocolSelector won't depend on SSLEngine or
SSLSocket, and can be reduced to a FunctionalInterface.

-- 
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

2015-05-22 Thread Simone Bordet
Hi,

On Fri, May 22, 2015 at 9:14 PM, Bernd Eckenfels e...@zusammenkunft.net wrote:
 I would suggest to make this encoded in latin1 instead. This is
 supposed to be a 8bit clean encoding (and will be compatible to all
 ASCII only strings). It is still ugly and needs to be documanted
 cleanly that the string you get back might not be a string at all.

RFC 7301 hints that protocol string could be UTF-8 encoded:
http://tools.ietf.org/html/rfc7301#section-6

-- 
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


TLS ALPN Proposal

2015-05-21 Thread Bradford Wetmore

This is a fork of the previous thread:

Subject:  TLS Handshake Message Proposal
  (Was: Re: JEP 244: TLS Application-Layer Protocol
  Negotiation Extension)

I broke this thread off to keep this proposal discussion together, but 
if you're interested in the history, please see the previous thread.


This approach combines different suggestions from security-dev in a new 
way, and simplifies the ALPN selection process quite a bit.  I think it 
addresses most of the concerns about selection that were raised.


This approach can be completely separated from the Handshake mechanism I 
discussed in the previous message, so I'm thinking of this approach for 
JDK 9 and targeting the more general handshake approach for JDK 10.


Here's the summary of API additions:


SSLParameters:
--
Client-side:  gets/sets the list of protocol names to send.
Server-side:  gets/sets a ApplicationProtocolSelector which is a
  user-defined callback mechanism.

ApplicationProtocolSelector:

Server-side:  callback methods for SSLSocket/SSLEngine which
  are provided with handshake information for making
  the selection

ExtendedSSLSession:
---
gets the negotiated protocol String



Specifics below.  The javadoc obviously needs work.

class SSLParameters {

...deleted...

/**
 * Gets the list of application protocols that will sent by
 * the client.
 *
 * The list could be empty, in which case no protocols will be
 * sent.
 *
 * @returns a list of application protocol names.
 */
public ListString getApplicationProtocols() { };

/**
 * Sets the list of application protocols that will sent by
 * the client.
 *
 * protocols could be empty, in which case no protocols will be
 * sent.
 *
 * @param protocols a list of application protocol names
 * @throws IllegalArgumentException if protocols is null.
 */
public void setApplicationProtocols(ListString protocols);

/**
 * Gets the current server-side application layer protocol selector.
 *
 * @param the selector mechanism.
 * @return the current application protocol selector, or null if
 * there is not one.
 */
public ApplicationProtocolSelector
getApplicationProtocolSelector() {};

/**
 * Sets the server-side application layer protocol selector.
 *
 * @param the selector mechanism, or null if protocol selection
 * should not be done.
 */
public void setApplicationProtocolSelector(
ApplicationProtocolSelector selector) {};
}


/*
 * A callback class on the server side that is responsible for
 * choosing which Application Protocol should be used in a SSL/TLS
 * connection.
 */
public abstract class ApplicationProtocolSelector {

/*
 * SSLSocket callback to choose which Application Protocol value
 * to return to a SSL/TLS client
 *
 * @param sslSocket the SSLSocket for this connection
 * @param protocols the list of protocols advertised by the client
 * @param protocolVersion the negotiated protocol version
 * @param ciphersuite the negotiated ciphersuite
 * @return a non-empty protocol String to send to the client,
 * or null if no protocol value (i.e. extension) should be sent.
 * @throws SSLProtocolException if the connection should be aborted
 * because the the server supports none of the protocols that
 * the client advertised.
 */
public String select(SSLSocket sslSocket, String[] protocols,
String protocolVersion, String ciphersuite)
throws SSLProtocolException;

/*
 * SSLEngine callback to choose which Application Protocol to return
 * to a SSL/TLS client.
 *
 * @param sslEngine the SSLEngine for this connection
 * @param protocols the list of protocols advertised by the client
 * @param protocolVersion the negotiated protocol version
 * @param ciphersuite the negotiated ciphersuite
 * @return a non-empty protocol String to send to the client,
 * or null if no protocol value should be sent.
 * @throws SSLProtocolException if the connection should be aborted
 * because the the server supports none of the protocols that
 * the client advertised.
 */
public String select(SSLEngine sslEngine, String[] protocols,
String protocolVersion, String ciphersuite)
throws SSLProtocolException;
}

If need be, we could include the received extensions or in a future 
version of this class.



public class ExtendedSSLSession implements SSLSession {

  ...deleted...

  /**
   * Gets the application protocol negotiated for this connection.
   *
   * @returns the application protocol name or null if none was
   * negotiated.
   */
  public String getApplicationProtocol() { };
}

There