TLS ALPN Proposal v5
Xuelei Fan
xuelei.fan at oracle.com
Sat Sep 26 01:18:10 UTC 2015
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.lloyd at 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.
More information about the security-dev
mailing list