TLS ALPN Proposal

Simone Bordet simone.bordet at gmail.com
Wed May 27 11:47:52 UTC 2015


Hi,

On Tue, May 26, 2015 at 8:46 PM, Bradford Wetmore
<bradford.wetmore at 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();
>     List<String> 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();
>     List<String> 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


More information about the security-dev mailing list