Pushes AES-256-GCM when a connection client advertises IV_NCP=2, and
supports serving connections to clients with different data channel
cipher configuration simultaneously.
v2:
* Update manpage
* Add Changes.rst entry
v3:
* Do not regenerate keys if the client sends a second pull request
* Don't postpone key generation if client has no IV_NCP support
v4:
* rebase on client-side NCP v4
Signed-off-by: Steffan Karger <steffan@karger.me>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <1467149771-10374-1-git-send-email-steffan@karger.me>
URL: http://article.gmane.org/gmane.network.openvpn.devel/12009
Signed-off-by: Gert Doering <gert@greenie.muc.de>
... | ... |
@@ -55,6 +55,13 @@ Http proxy password inside config file |
55 | 55 |
Http proxy passwords can be specified with the inline file option |
56 | 56 |
http-proxy-user-pass |
57 | 57 |
|
58 |
+Cipher negotiation |
|
59 |
+ Data channel ciphers are now by default negotiated. If a client advertises |
|
60 |
+ support for Negotiable Crypto Parameters (NCP), the server will choose a |
|
61 |
+ cipher (by default AES-256-GCM) for the data channel, and tell the client |
|
62 |
+ to use that cipher. Data channel cipher negotiation can be controlled |
|
63 |
+ using --ncp-ciphers and --ncp-disable. |
|
64 |
+ |
|
58 | 65 |
|
59 | 66 |
User-visible Changes |
60 | 67 |
-------------------- |
... | ... |
@@ -124,6 +131,11 @@ User-visible Changes |
124 | 124 |
time in seconds to wait between reconnection attempts when an exponential |
125 | 125 |
backoff is triggered due to repeated retries. Default = 300 seconds. |
126 | 126 |
|
127 |
+- Data channel cipher negotiation (see New features section) can override |
|
128 |
+ ciphers configured in the config file. Use --ncp-disable if you don't want |
|
129 |
+ that. |
|
130 |
+ |
|
131 |
+ |
|
127 | 132 |
Maintainer-visible changes |
128 | 133 |
-------------------------- |
129 | 134 |
- OpenVPN no longer supports building with crypto support, but without TLS |
... | ... |
@@ -4137,6 +4137,10 @@ Restrict the allowed ciphers to be negotiated to the ciphers in |
4137 | 4137 |
.B cipher_list |
4138 | 4138 |
is a colon-separated list of ciphers, and defaults to |
4139 | 4139 |
"AES-256-GCM:AES-128-GCM". |
4140 |
+ |
|
4141 |
+For servers, the first cipher from |
|
4142 |
+.B cipher_list |
|
4143 |
+will be pushed to clients that support cipher negotiation. |
|
4140 | 4144 |
.\"********************************************************* |
4141 | 4145 |
.TP |
4142 | 4146 |
.B \-\-ncp\-disable |
... | ... |
@@ -2330,8 +2330,8 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) |
2330 | 2330 |
/* In short form, unique datagram identifier is 32 bits, in long form 64 bits */ |
2331 | 2331 |
packet_id_long_form = cipher_kt_mode_ofb_cfb (c->c1.ks.key_type.cipher); |
2332 | 2332 |
|
2333 |
- /* Compute MTU parameters (postpone if we pull options) */ |
|
2334 |
- if (c->options.pull) |
|
2333 |
+ /* Compute MTU parameters (postpone if we push/pull options) */ |
|
2334 |
+ if (c->options.pull || c->options.mode == MODE_SERVER) |
|
2335 | 2335 |
{ |
2336 | 2336 |
/* Account for worst-case crypto overhead before allocating buffers */ |
2337 | 2337 |
frame_add_to_extra_frame (&c->c2.frame, crypto_max_overhead()); |
... | ... |
@@ -2375,6 +2375,7 @@ do_init_crypto_tls (struct context *c, const unsigned int flags) |
2375 | 2375 |
to.renegotiate_packets = options->renegotiate_packets; |
2376 | 2376 |
to.renegotiate_seconds = options->renegotiate_seconds; |
2377 | 2377 |
to.single_session = options->single_session; |
2378 |
+ to.mode = options->mode; |
|
2378 | 2379 |
to.pull = options->pull; |
2379 | 2380 |
#ifdef ENABLE_PUSH_PEER_INFO |
2380 | 2381 |
if (options->push_peer_info) /* all there is */ |
... | ... |
@@ -245,13 +245,30 @@ incoming_push_message (struct context *c, const struct buffer *buffer) |
245 | 245 |
if (!do_up (c, true, c->options.push_option_types_found)) |
246 | 246 |
{ |
247 | 247 |
msg (D_PUSH_ERRORS, "Failed to open tun/tap interface"); |
248 |
- register_signal (c, SIGUSR1, "do_up-failed"); |
|
249 |
- goto cleanup; |
|
248 |
+ goto error; |
|
250 | 249 |
} |
251 | 250 |
} |
252 | 251 |
event_timeout_clear (&c->c2.push_request_interval); |
253 | 252 |
} |
253 |
+ else if (status == PUSH_MSG_REQUEST) |
|
254 |
+ { |
|
255 |
+ if (c->options.mode == MODE_SERVER) |
|
256 |
+ { |
|
257 |
+ struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; |
|
258 |
+ /* Do not regenerate keys if client send a second push request */ |
|
259 |
+ if (!session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized && |
|
260 |
+ !tls_session_update_crypto_params (session, &c->options, |
|
261 |
+ &c->c2.frame)) |
|
262 |
+ { |
|
263 |
+ msg (D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed"); |
|
264 |
+ goto error; |
|
265 |
+ } |
|
266 |
+ } |
|
267 |
+ } |
|
254 | 268 |
|
269 |
+ goto cleanup; |
|
270 |
+error: |
|
271 |
+ register_signal (c, SIGUSR1, "process-push-msg-failed"); |
|
255 | 272 |
cleanup: |
256 | 273 |
gc_free (&gc); |
257 | 274 |
} |
... | ... |
@@ -302,15 +319,13 @@ prepare_push_reply (struct options *o, struct tls_multi *tls_multi) |
302 | 302 |
} |
303 | 303 |
|
304 | 304 |
/* Push cipher if client supports Negotiable Crypto Parameters */ |
305 |
- optstr = peer_info ? strstr(peer_info, "IV_NCP=") : NULL; |
|
306 |
- if (optstr) |
|
305 |
+ if (tls_peer_info_ncp_ver (peer_info) >= 2 && o->ncp_enabled) |
|
307 | 306 |
{ |
308 |
- int ncp = 0; |
|
309 |
- int r = sscanf(optstr, "IV_NCP=%d", &ncp); |
|
310 |
- if ((r == 1) && (ncp == 2)) |
|
311 |
- { |
|
312 |
- push_option_fmt(o, M_USAGE, "cipher %s", o->ciphername); |
|
313 |
- } |
|
307 |
+ /* Push the first cipher from --ncp-ciphers to the client. |
|
308 |
+ * TODO: actual negotiation, instead of server dictatorship. */ |
|
309 |
+ char *push_cipher = string_alloc(o->ncp_ciphers, &o->gc); |
|
310 |
+ o->ciphername = strtok (push_cipher, ":"); |
|
311 |
+ push_option_fmt(o, M_USAGE, "cipher %s", o->ciphername); |
|
314 | 312 |
} |
315 | 313 |
return true; |
316 | 314 |
} |
... | ... |
@@ -1665,10 +1665,10 @@ tls_session_update_crypto_params(struct tls_session *session, |
1665 | 1665 |
bool ret = false; |
1666 | 1666 |
struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ |
1667 | 1667 |
|
1668 |
- ASSERT (!session->opt->server); |
|
1669 | 1668 |
ASSERT (ks->authenticated); |
1670 | 1669 |
|
1671 |
- if (0 != strcmp(options->ciphername, session->opt->config_ciphername) && |
|
1670 |
+ if (!session->opt->server && |
|
1671 |
+ 0 != strcmp(options->ciphername, session->opt->config_ciphername) && |
|
1672 | 1672 |
!item_in_list(options->ciphername, options->ncp_ciphers)) |
1673 | 1673 |
{ |
1674 | 1674 |
msg (D_TLS_ERRORS, "Error: pushed cipher not allowed - %s not in %s or %s", |
... | ... |
@@ -1695,12 +1695,13 @@ tls_session_update_crypto_params(struct tls_session *session, |
1695 | 1695 |
options->ce.tun_mtu_defined, options->ce.tun_mtu); |
1696 | 1696 |
frame_print (frame, D_MTU_INFO, "Data Channel MTU parms"); |
1697 | 1697 |
|
1698 |
+ const struct session_id *client_sid = session->opt->server ? |
|
1699 |
+ &ks->session_id_remote : &session->session_id; |
|
1700 |
+ const struct session_id *server_sid = !session->opt->server ? |
|
1701 |
+ &ks->session_id_remote : &session->session_id; |
|
1698 | 1702 |
if (!generate_key_expansion (&ks->crypto_options.key_ctx_bi, |
1699 |
- &session->opt->key_type, |
|
1700 |
- ks->key_src, |
|
1701 |
- &session->session_id, |
|
1702 |
- &ks->session_id_remote, |
|
1703 |
- false)) |
|
1703 |
+ &session->opt->key_type, ks->key_src, client_sid, server_sid, |
|
1704 |
+ session->opt->server)) |
|
1704 | 1705 |
{ |
1705 | 1706 |
msg (D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed"); |
1706 | 1707 |
goto cleanup; |
... | ... |
@@ -1958,8 +1959,11 @@ push_peer_info(struct buffer *buf, struct tls_session *session) |
1958 | 1958 |
buf_printf(&out, "IV_PROTO=2\n"); |
1959 | 1959 |
|
1960 | 1960 |
/* support for Negotiable Crypto Paramters */ |
1961 |
- if (session->opt->ncp_enabled && session->opt->pull) |
|
1962 |
- buf_printf(&out, "IV_NCP=2\n"); |
|
1961 |
+ if (session->opt->ncp_enabled && |
|
1962 |
+ (session->opt->mode == MODE_SERVER || session->opt->pull)) |
|
1963 |
+ { |
|
1964 |
+ buf_printf(&out, "IV_NCP=2\n"); |
|
1965 |
+ } |
|
1963 | 1966 |
|
1964 | 1967 |
/* push compression status */ |
1965 | 1968 |
#ifdef USE_COMP |
... | ... |
@@ -2063,10 +2067,13 @@ key_method_2_write (struct buffer *buf, struct tls_session *session) |
2063 | 2063 |
if (!push_peer_info (buf, session)) |
2064 | 2064 |
goto error; |
2065 | 2065 |
|
2066 |
- /* |
|
2067 |
- * generate tunnel keys if server |
|
2066 |
+ /* Generate tunnel keys if we're a TLS server. |
|
2067 |
+ * If we're a p2mp server and IV_NCP >= 2 is negotiated, the first key |
|
2068 |
+ * generation is postponed until after the pull/push, so we can process pushed |
|
2069 |
+ * cipher directives. |
|
2068 | 2070 |
*/ |
2069 |
- if (session->opt->server) |
|
2071 |
+ if (session->opt->server && !(session->opt->ncp_enabled && |
|
2072 |
+ session->opt->mode == MODE_SERVER && ks->key_id <= 0)) |
|
2070 | 2073 |
{ |
2071 | 2074 |
if (ks->authenticated) |
2072 | 2075 |
{ |
... | ... |
@@ -2218,6 +2225,12 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi |
2218 | 2218 |
multi->peer_info = read_string_alloc (buf); |
2219 | 2219 |
if ( multi->peer_info ) |
2220 | 2220 |
output_peer_info_env (session->opt->es, multi->peer_info); |
2221 |
+ |
|
2222 |
+ if (tls_peer_info_ncp_ver (multi->peer_info) < 2) |
|
2223 |
+ { |
|
2224 |
+ /* Peer does not support NCP */ |
|
2225 |
+ session->opt->ncp_enabled = false; |
|
2226 |
+ } |
|
2221 | 2227 |
#endif |
2222 | 2228 |
|
2223 | 2229 |
if (tls_session_user_pass_enabled(session)) |
... | ... |
@@ -3689,6 +3702,20 @@ tls_update_remote_addr (struct tls_multi *multi, const struct link_socket_actual |
3689 | 3689 |
gc_free (&gc); |
3690 | 3690 |
} |
3691 | 3691 |
|
3692 |
+int |
|
3693 |
+tls_peer_info_ncp_ver(const char *peer_info) |
|
3694 |
+{ |
|
3695 |
+ const char *ncpstr = peer_info ? strstr (peer_info, "IV_NCP=") : NULL; |
|
3696 |
+ if (ncpstr) |
|
3697 |
+ { |
|
3698 |
+ int ncp = 0; |
|
3699 |
+ int r = sscanf(ncpstr, "IV_NCP=%d", &ncp); |
|
3700 |
+ if (r == 1) |
|
3701 |
+ return ncp; |
|
3702 |
+ } |
|
3703 |
+ return 0; |
|
3704 |
+} |
|
3705 |
+ |
|
3692 | 3706 |
/* |
3693 | 3707 |
* Dump a human-readable rendition of an openvpn packet |
3694 | 3708 |
* into a garbage collectable string which is returned. |
... | ... |
@@ -497,6 +497,12 @@ tls_get_peer_info(const struct tls_multi *multi) |
497 | 497 |
} |
498 | 498 |
#endif |
499 | 499 |
|
500 |
+/** |
|
501 |
+ * Return the Negotiable Crypto Parameters version advertised in the peer info |
|
502 |
+ * string, or 0 if none specified. |
|
503 |
+ */ |
|
504 |
+int tls_peer_info_ncp_ver(const char *peer_info); |
|
505 |
+ |
|
500 | 506 |
/* |
501 | 507 |
* inline functions |
502 | 508 |
*/ |