1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
https://bugs.gentoo.org/965061
https://gitlab.com/openconnect/openconnect/-/merge_requests/574
From 94868eef754f88569f690f8440010b331a3a67fb Mon Sep 17 00:00:00 2001
From: David Woodhouse <dwmw2@infradead.org>
Date: Fri, 15 Nov 2024 15:46:05 +0000
Subject: [PATCH] Use RFC9266 'tls-exporter' channel bindings for Cisco STRAP
with TLSv1.3
Fixes #659
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
(cherry picked from commit 94e0b16c011b7b88708b8a8505fac6bfbe2e3cca)
---
gnutls.c | 20 +++++++++++++++++++-
openconnect-internal.h | 5 +++++
openssl.c | 30 +++++++++++++++++++++++-------
3 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/gnutls.c b/gnutls.c
index 9fc010b9..6c2e3aec 100644
--- a/gnutls.c
+++ b/gnutls.c
@@ -3176,7 +3176,25 @@ void append_strap_verify(struct openconnect_info *vpninfo,
/* 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 */
diff --git a/openconnect-internal.h b/openconnect-internal.h
index f19b4d81..541d5594 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -1058,6 +1058,11 @@ static inline void __monitor_fd_new(struct openconnect_info *vpninfo,
#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 */
diff --git a/openssl.c b/openssl.c
index 12a08692..4177e3f9 100644
--- a/openssl.c
+++ b/openssl.c
@@ -2510,14 +2510,30 @@ void append_strap_verify(struct openconnect_info *vpninfo,
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 (%zd 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. */
--
2.51.1
|