You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Geting TLS Channel Binding data for later use in SCRAM #1535
I need to use TLS channel binding data in SASL SCRAM. Easiest way for me is using BC as provider, because I don't want to implement own AbstractTlsServer (especially getCredentials() is thing I don't fully understand).
So, please add way to get channel binding data after notifyHandshakeComplete() via ProvSSLEngine.
Or improve implementation of DefaultTlsServer to be easy to use. 😄
Thanks
Oh I see that this is broken because we currently clear the master secret (and in TLS 1.3 the exporter secret) after the handshake completes. Our existing tests only cover "tls-unique" channel binding so this wasn't picked up.
A quick fix would be to calculate the "tls-exporter" channel binding for all connections, but it'd be nicer if it could be on demand, including access to the more general TlsContext#exportKeyingMaterial.
@Neustradamus I have a branch that adds BCSSLParameters#setChannelBindings; those channel bindings will then be established at handshake completion for later collection via BCSSLConnection#getChannelBinding . This is fairly simple but the binding "tls-exporter" has the annoyance that it might be calculated for TLS 1.2 even when you only wanted it in case TLS 1.3 was negotiated (and e.g. "tls-unique" otherwise). I'm inclined to use a separate "tls-exporter-legacy" for the TLS 1.2 case.
Another possibility would be using a callback in the vein of SSLEngine#setHandshakeApplicationProtocolSelector that is called to determine the list of channel bindings (with access to the handshake session presumably).
Finally, I've been contemplating to just have a callback that will give access to the new BCSSLConnection while the "handshake completion window" is still open. There are concerns here around threading issues. The standard JSSE HandshakeCompletedListener notification is thread-decoupled, which would defeat the purpose here. OTOH, SSLSessionBindingListener calls are not thread-decoupled, but I guess that is not so tangled up in the actual protocol. Maybe BCSSLConnection could store values like a session, or perhaps this callback could return a generic "user data" Object that could be collected via a different BCSSLConnection method later.
Comments welcome on the above, or if I've overlooked a better option.
I tried to use ProvSSLEngine in RADIUS EAP TLS Authentication (server side), but I am stuck on how to use TlsContext#exportKeyingMaterial, which is necessary to generate MPPE keys.
With Java Reflection, I can get the field protocolPeer then the method getTlsContext, but calling exportKeyingMaterial when SSLEngineResult.HandshakeStatus.FINISHED failed with the same exception.
java.lang.IllegalStateException: Export of key material only available from notifyHandshakeComplete()
I guess it is the same reason of cleanupHandshake().
Channel binding has been available since 1.72 (Aug 2022, 93fb415). From the JSSE provider, after the handshake completes: ((BCSSLSocket) socket).getConnection().getChannelBinding("tls-exporter") (or via BCSSLEngine.getConnection() / ProvSSLEngine.getConnection()). The low‑level API equivalent is TlsContext.exportChannelBinding(ChannelBinding.tls_exporter). Supported names: tls-exporter (RFC 9266 — recommended, works on TLS 1.2 w/ EMS and TLS 1.3), tls-server-end-point, and tls-unique. Note that on TLS 1.3 only tls-exporter is available (tls-server-end-point/tls-unique return null by design), so use tls-exporter for SCRAM over TLS 1.3. Closing as already supported — please reopen if this doesn't cover your case.
Activity
peterdettman commentedon Nov 21, 2023
e.g.:
byte[] channelBinding = ((BCSSLEngine)engine).getConnection().getChannelBinding("tls-exporter");bmalkow commentedon Nov 21, 2023
Unfortunately it doesn't work, when I use BC as provider:
There is no way to disable
cleanupHandshake()or export those data before cleanup.peterdettman commentedon Nov 21, 2023
Oh I see that this is broken because we currently clear the master secret (and in TLS 1.3 the exporter secret) after the handshake completes. Our existing tests only cover "tls-unique" channel binding so this wasn't picked up.
A quick fix would be to calculate the "tls-exporter" channel binding for all connections, but it'd be nicer if it could be on demand, including access to the more general
TlsContext#exportKeyingMaterial.Neustradamus commentedon Jun 26, 2024
@peterdettman: Have you progressed on it?
Thanks in advance.
Linked to:
peterdettman commentedon Jun 27, 2024
@Neustradamus I have a branch that adds
BCSSLParameters#setChannelBindings; those channel bindings will then be established at handshake completion for later collection viaBCSSLConnection#getChannelBinding. This is fairly simple but the binding "tls-exporter" has the annoyance that it might be calculated for TLS 1.2 even when you only wanted it in case TLS 1.3 was negotiated (and e.g. "tls-unique" otherwise). I'm inclined to use a separate "tls-exporter-legacy" for the TLS 1.2 case.Another possibility would be using a callback in the vein of
SSLEngine#setHandshakeApplicationProtocolSelectorthat is called to determine the list of channel bindings (with access to the handshake session presumably).Finally, I've been contemplating to just have a callback that will give access to the new
BCSSLConnectionwhile the "handshake completion window" is still open. There are concerns here around threading issues. The standard JSSEHandshakeCompletedListenernotification is thread-decoupled, which would defeat the purpose here. OTOH,SSLSessionBindingListenercalls are not thread-decoupled, but I guess that is not so tangled up in the actual protocol. MaybeBCSSLConnectioncould store values like a session, or perhaps this callback could return a generic "user data"Objectthat could be collected via a differentBCSSLConnectionmethod later.Comments welcome on the above, or if I've overlooked a better option.
omnine commentedon Jul 20, 2024
I tried to use
ProvSSLEnginein RADIUS EAP TLS Authentication (server side), but I am stuck on how to useTlsContext#exportKeyingMaterial, which is necessary to generate MPPE keys.With Java Reflection, I can get the field
protocolPeerthen the methodgetTlsContext, but callingexportKeyingMaterialwhenSSLEngineResult.HandshakeStatus.FINISHEDfailed with the same exception.java.lang.IllegalStateException: Export of key material only available from notifyHandshakeComplete()I guess it is the same reason of
cleanupHandshake().ligefeiBouncycastle commentedon Jun 9, 2026
Channel binding has been available since 1.72 (Aug 2022, 93fb415). From the JSSE provider, after the handshake completes: ((BCSSLSocket) socket).getConnection().getChannelBinding("tls-exporter") (or via BCSSLEngine.getConnection() / ProvSSLEngine.getConnection()). The low‑level API equivalent is TlsContext.exportChannelBinding(ChannelBinding.tls_exporter). Supported names: tls-exporter (RFC 9266 — recommended, works on TLS 1.2 w/ EMS and TLS 1.3), tls-server-end-point, and tls-unique. Note that on TLS 1.3 only tls-exporter is available (tls-server-end-point/tls-unique return null by design), so use tls-exporter for SCRAM over TLS 1.3. Closing as already supported — please reopen if this doesn't cover your case.
Neustradamus commentedon Jun 9, 2026
@ligefeiBouncycastle: Can you confirm me:
It is good?