fix(quic): thread offered ALPN list through TlsClient → ClientHello
QuicConnection.alpnList → TlsClient.offeredAlpns was captured but never threaded into buildQuicClientHello. The builder accepted only an "additionalAlpn" parameter and hardcoded "h3" first, so our wire ClientHello always carried just [h3] regardless of caller intent. quic-go enforces strictly with TLS alert 120 (no_application_protocol, CRYPTO_ERROR 376) when none of the offered ALPNs match its server config — handshake failed at the very first server response against quic-go's hq-interop testcases. Replaced the awkward additionalAlpn shape with `alpns: List<ByteArray>` (default [h3] for backward-compat) and threaded TlsClient.offeredAlpns through. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -154,6 +154,7 @@ class TlsClient(
|
|||||||
serverName = serverName,
|
serverName = serverName,
|
||||||
x25519PublicKey = keyPair!!.publicKey,
|
x25519PublicKey = keyPair!!.publicKey,
|
||||||
quicTransportParams = transportParameters,
|
quicTransportParams = transportParameters,
|
||||||
|
alpns = offeredAlpns,
|
||||||
random = random,
|
random = random,
|
||||||
cipherSuites = cipherSuites,
|
cipherSuites = cipherSuites,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -83,14 +83,22 @@ class TlsClientHello(
|
|||||||
* - signature_algorithms covering ECDSA / RSA-PSS / Ed25519
|
* - signature_algorithms covering ECDSA / RSA-PSS / Ed25519
|
||||||
* - key_share with the caller's X25519 public
|
* - key_share with the caller's X25519 public
|
||||||
* - psk_key_exchange_modes = [ psk_dhe_ke ]
|
* - psk_key_exchange_modes = [ psk_dhe_ke ]
|
||||||
* - ALPN = [ h3 ]
|
* - ALPN = caller-supplied list (default `[ h3 ]`)
|
||||||
* - quic_transport_parameters = (caller-supplied opaque bytes)
|
* - quic_transport_parameters = (caller-supplied opaque bytes)
|
||||||
|
*
|
||||||
|
* Caller must pass the FULL list of ALPNs to offer. Earlier shape took an
|
||||||
|
* `additionalAlpn` parameter and forced `h3` first — that silently dropped
|
||||||
|
* any caller-supplied list (e.g. `[hq-interop, h3]` for the interop
|
||||||
|
* runner's hq-interop testcases) because the production call site never
|
||||||
|
* threaded the list through. quic-go enforces strictly with TLS alert
|
||||||
|
* 120 (`no_application_protocol`, CRYPTO_ERROR 376) when the offered
|
||||||
|
* ALPNs don't include one its server is configured for.
|
||||||
*/
|
*/
|
||||||
fun buildQuicClientHello(
|
fun buildQuicClientHello(
|
||||||
serverName: String,
|
serverName: String,
|
||||||
x25519PublicKey: ByteArray,
|
x25519PublicKey: ByteArray,
|
||||||
quicTransportParams: ByteArray,
|
quicTransportParams: ByteArray,
|
||||||
additionalAlpn: List<ByteArray> = emptyList(),
|
alpns: List<ByteArray> = listOf(TlsConstants.ALPN_H3),
|
||||||
random: ByteArray = RandomInstance.bytes(32),
|
random: ByteArray = RandomInstance.bytes(32),
|
||||||
cipherSuites: IntArray =
|
cipherSuites: IntArray =
|
||||||
intArrayOf(
|
intArrayOf(
|
||||||
@@ -98,9 +106,6 @@ fun buildQuicClientHello(
|
|||||||
TlsConstants.CIPHER_TLS_CHACHA20_POLY1305_SHA256,
|
TlsConstants.CIPHER_TLS_CHACHA20_POLY1305_SHA256,
|
||||||
),
|
),
|
||||||
): TlsClientHello {
|
): TlsClientHello {
|
||||||
val alpn = mutableListOf<ByteArray>()
|
|
||||||
alpn += TlsConstants.ALPN_H3
|
|
||||||
alpn += additionalAlpn
|
|
||||||
val exts =
|
val exts =
|
||||||
listOf(
|
listOf(
|
||||||
TlsExtension(TlsConstants.EXT_SERVER_NAME, encodeServerNameExtension(serverName)),
|
TlsExtension(TlsConstants.EXT_SERVER_NAME, encodeServerNameExtension(serverName)),
|
||||||
@@ -109,7 +114,7 @@ fun buildQuicClientHello(
|
|||||||
TlsExtension(TlsConstants.EXT_SIGNATURE_ALGORITHMS, encodeSignatureAlgorithms()),
|
TlsExtension(TlsConstants.EXT_SIGNATURE_ALGORITHMS, encodeSignatureAlgorithms()),
|
||||||
TlsExtension(TlsConstants.EXT_KEY_SHARE, encodeKeyShareClientX25519(x25519PublicKey)),
|
TlsExtension(TlsConstants.EXT_KEY_SHARE, encodeKeyShareClientX25519(x25519PublicKey)),
|
||||||
TlsExtension(TlsConstants.EXT_PSK_KEY_EXCHANGE_MODES, encodePskKeyExchangeModesDhe()),
|
TlsExtension(TlsConstants.EXT_PSK_KEY_EXCHANGE_MODES, encodePskKeyExchangeModesDhe()),
|
||||||
TlsExtension(TlsConstants.EXT_ALPN, encodeAlpn(alpn)),
|
TlsExtension(TlsConstants.EXT_ALPN, encodeAlpn(alpns)),
|
||||||
TlsExtension(TlsConstants.EXT_QUIC_TRANSPORT_PARAMETERS, quicTransportParams),
|
TlsExtension(TlsConstants.EXT_QUIC_TRANSPORT_PARAMETERS, quicTransportParams),
|
||||||
)
|
)
|
||||||
return TlsClientHello(random = random, cipherSuites = cipherSuites, extensions = exts)
|
return TlsClientHello(random = random, cipherSuites = cipherSuites, extensions = exts)
|
||||||
|
|||||||
Reference in New Issue
Block a user