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

Reply via email to