Skip to content

Geting TLS Channel Binding data for later use in SCRAM #1535

Open

Description

@bmalkow

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

Activity

  1. peterdettman commented on Nov 21, 2023

    @peterdettman
    Collaborator

    e.g.:

    byte[] channelBinding = ((BCSSLEngine)engine).getConnection().getChannelBinding("tls-exporter");

  2. bmalkow commented on Nov 21, 2023

    @bmalkow
    Author

    Unfortunately it doesn't work, when I use BC as provider:

    java.lang.IllegalStateException: Export of key material only available from notifyHandshakeComplete()
    

    There is no way to disable cleanupHandshake() or export those data before cleanup.

  3. peterdettman commented on Nov 21, 2023

    @peterdettman
    Collaborator

    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.

  4. Neustradamus commented on Jun 26, 2024

    @Neustradamus

    @peterdettman: Have you progressed on it?

    Thanks in advance.

    Linked to:

  5. peterdettman commented on Jun 27, 2024

    @peterdettman
    Collaborator

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

  6. omnine commented on Jul 20, 2024

    @omnine

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

  7. ligefeiBouncycastle commented on Jun 9, 2026

    @ligefeiBouncycastle
    Collaborator

    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.

  8. Neustradamus commented on Jun 9, 2026

    @Neustradamus

    @ligefeiBouncycastle: Can you confirm me:

    • tls-unique for TLS =< 1.2 (RFC5929)
    • tls-server-end-point for TLS =< 1.2 + 1.3 (RFC5929)
    • tls-exporter for TLS = 1.3 (RFC9266)

    It is good?

  9. removed their assignment
    on Aug 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions