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