/* Concatenate our Finished message with our pubkey to be signed */
struct oc_text_buf *nonce = buf_alloc();
- buf_append_bytes(nonce, vpninfo->finished, vpninfo->finished_len);
+ if (gnutls_protocol_get_version(vpninfo->https_sess) <= GNUTLS_TLS1_2) {
+ /* For TLSv1.2 and earlier, use RFC5929 'tls-unique' channel binding */
+ buf_append_bytes(nonce, vpninfo->finished, vpninfo->finished_len);
+ } else {
+ /* For TLSv1.3 use RFC9266 'tls-exporter' channel binding */
+ char channel_binding_buf[TLS_EXPORTER_KEY_SIZE];
+ err = gnutls_prf(vpninfo->https_sess, TLS_EXPORTER_LABEL_SIZE, TLS_EXPORTER_LABEL,
+ 0, 0, 0, TLS_EXPORTER_KEY_SIZE, channel_binding_buf);
+ if (err) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Failed to generate channel bindings for STRAP key: %s\n"),
+ gnutls_strerror(err));
+ if (!buf_error(buf))
+ buf->error = -EIO;
+ buf_free(nonce);
+ return;
+ }
+ buf_append_bytes(nonce, channel_binding_buf, TLS_EXPORTER_KEY_SIZE);
+ }
if (rekey) {
/* We have a copy and we don't want it freed just yet */
#define PSK_LABEL_SIZE (sizeof(PSK_LABEL) - 1)
#define PSK_KEY_SIZE 32
+/* Key material for RFC9266 tls-exporter channel binding */
+#define TLS_EXPORTER_LABEL "EXPORTER-Channel-Binding"
+#define TLS_EXPORTER_LABEL_SIZE (sizeof(TLS_EXPORTER_LABEL) - 1)
+#define TLS_EXPORTER_KEY_SIZE 32
+
/* Packet types */
#define AC_PKT_DATA 0 /* Uncompressed data */
struct oc_text_buf *buf, int rekey)
{
unsigned char finished[64];
- size_t flen = SSL_get_finished(vpninfo->https_ssl, finished, sizeof(finished));
+ size_t flen;
- if (flen > sizeof(finished)) {
- vpn_progress(vpninfo, PRG_ERR,
- _("SSL Finished message too large (%zu bytes)\n"), flen);
- if (!buf_error(buf))
- buf->error = -EIO;
- return;
+ if (SSL_SESSION_get_protocol_version(SSL_get_session(vpninfo->https_ssl)) <= TLS1_2_VERSION) {
+ /* For TLSv1.2 and earlier, use RFC5929 'tls-unique' channel binding */
+ flen = SSL_get_finished(vpninfo->https_ssl, finished, sizeof(finished));
+ if (flen > sizeof(finished)) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("SSL Finished message too large (%zu bytes)\n"), flen);
+ if (!buf_error(buf))
+ buf->error = -EIO;
+ return;
+ }
+ } else {
+ /* For TLSv1.3 use RFC9266 'tls-exporter' channel binding */
+ if (!SSL_export_keying_material(vpninfo->https_ssl,
+ finished, TLS_EXPORTER_KEY_SIZE,
+ TLS_EXPORTER_LABEL, TLS_EXPORTER_LABEL_SIZE,
+ NULL, 0, 0)) {
+ vpn_progress(vpninfo, PRG_ERR,
+ _("Failed to generate channel bindings for STRAP key\n"));
+ openconnect_report_ssl_errors(vpninfo);
+ return;
+ }
+ flen = TLS_EXPORTER_KEY_SIZE;
}
/* If we're rekeying, we need to sign the Verify header with the *old* key. */
<ul>
<li><b>OpenConnect HEAD</b>
<ul>
+ <li>Fix Cisco Anyconnect STRAP channel bindings with TLSv1.3 (<a href="https://gitlab.com/openconnect/openconnect/-/issues/659">#659</a>).</li>
<li>Fix ASN.1 encoding of TPMv2 ECDSA signatures with GnuTLS &lt; 3.6.0</li>
<li>Handle Pulse configuration packets that cannot fit in a single TLS frame (<a href="https://gitlab.com/openconnect/openconnect/-/issues/617">#617</a>, <a href="https://gitlab.com/openconnect/openconnect/-/merge_requests/480">!480</a>).</li>
<li>Send operating system information to Pulse servers (<a href="https://gitlab.com/openconnect/openconnect/-/merge_requests/481">!481</a>).</li>