TLS ALPN Proposal

Bradford Wetmore bradford.wetmore at oracle.com
Tue May 26 18:46:34 UTC 2015


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

Brad


On 5/26/2015 1:00 AM, Simone Bordet wrote:
> Hi,
>
> On Tue, May 26, 2015 at 2:30 AM, Bradford Wetmore
> <bradford.wetmore at 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 List<String> 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 ?
>


More information about the security-dev mailing list