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 >> <david.ll...@redhat.com> 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 >>> to be >>> involved. >> >> See above. >> Unless it is verified that trySetCipherSuite() cannot *ever* fail >> after a cipher has been chosen (but then the method should return >> void), then I don't see how your proposal could work. > > The method isn't magical; it is just working off of known inputs. If > you give inputs that will ultimately result in a correct negotiation > (and nothing leads me to believe that there is any reason that the > application protocol user cannot do this), then you will get a > successful output. On the other hand, if (for example) the user selects > a cipher suite that is incompatible with their credentials, or which is > incompatible with the protocol which the user *also* selected, I don't > see any good reason to give them another chance. > > In other words, you're assuming that the only way to know if a > configuration is correct is to try it, but that just isn't true. > >> Have you written an implementation already ? That would help. > > No.