OpenVPN
ssl_ncp.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
9  * Copyright (C) 2010-2021 Fox Crypto B.V. <openvpn@foxcrypto.com>
10  * Copyright (C) 2008-2021 David Sommerseth <dazo@eurephia.org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License version 2
14  * as published by the Free Software Foundation.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25 
31 /*
32  * The routines in this file deal with dynamically negotiating
33  * the data channel HMAC and cipher keys through a TLS session.
34  *
35  * Both the TLS session and the data channel are multiplexed
36  * over the same TCP/UDP port.
37  */
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #elif defined(_MSC_VER)
41 #include "config-msvc.h"
42 #endif
43 
44 #include "syshead.h"
45 #include "win32.h"
46 
47 #include "error.h"
48 #include "common.h"
49 
50 #include "ssl_ncp.h"
51 #include "ssl_util.h"
52 #include "openvpn.h"
53 
58 static int
59 tls_peer_info_ncp_ver(const char *peer_info)
60 {
61  const char *ncpstr = peer_info ? strstr(peer_info, "IV_NCP=") : NULL;
62  if (ncpstr)
63  {
64  int ncp = 0;
65  int r = sscanf(ncpstr, "IV_NCP=%d", &ncp);
66  if (r == 1)
67  {
68  return ncp;
69  }
70  }
71  return 0;
72 }
73 
78 bool
79 tls_peer_supports_ncp(const char *peer_info)
80 {
81  if (!peer_info)
82  {
83  return false;
84  }
85  else if (tls_peer_info_ncp_ver(peer_info) >= 2
86  || strstr(peer_info, "IV_CIPHERS="))
87  {
88  return true;
89  }
90  else
91  {
92  return false;
93  }
94 }
95 
96 char *
97 mutate_ncp_cipher_list(const char *list, struct gc_arena *gc)
98 {
99  bool error_found = false;
100 
101  struct buffer new_list = alloc_buf(MAX_NCP_CIPHERS_LENGTH);
102 
103  char *const tmp_ciphers = string_alloc(list, NULL);
104  const char *token = strtok(tmp_ciphers, ":");
105  while (token)
106  {
107  /*
108  * Going through a roundtrip by using cipher_kt_get/cipher_kt_name
109  * (and translate_cipher_name_from_openvpn/
110  * translate_cipher_name_to_openvpn) also normalises the cipher name,
111  * e.g. replacing AeS-128-gCm with AES-128-GCM
112  */
113  const cipher_kt_t *ktc = cipher_kt_get(token);
114  if (strcmp(token, "none") == 0)
115  {
116  msg(M_WARN, "WARNING: cipher 'none' specified for --data-ciphers. "
117  "This allows negotiation of NO encryption and "
118  "tunnelled data WILL then be transmitted in clear text "
119  "over the network! "
120  "PLEASE DO RECONSIDER THIS SETTING!");
121  }
122  if (!ktc && strcmp(token, "none") != 0)
123  {
124  msg(M_WARN, "Unsupported cipher in --data-ciphers: %s", token);
125  error_found = true;
126  }
127  else
128  {
129  const char *ovpn_cipher_name = cipher_kt_name(ktc);
130  if (ktc == NULL)
131  {
132  /* NULL resolves to [null-cipher] but we need none for
133  * data-ciphers */
134  ovpn_cipher_name = "none";
135  }
136 
137  if (buf_len(&new_list)> 0)
138  {
139  /* The next if condition ensure there is always space for
140  * a :
141  */
142  buf_puts(&new_list, ":");
143  }
144 
145  /* Ensure buffer has capacity for cipher name + : + \0 */
146  if (!(buf_forward_capacity(&new_list) >
147  strlen(ovpn_cipher_name) + 2))
148  {
149  msg(M_WARN, "Length of --data-ciphers is over the "
150  "limit of 127 chars");
151  error_found = true;
152  }
153  else
154  {
155  buf_puts(&new_list, ovpn_cipher_name);
156  }
157  }
158  token = strtok(NULL, ":");
159  }
160 
161 
162 
163  char *ret = NULL;
164  if (!error_found && buf_len(&new_list) > 0)
165  {
166  buf_null_terminate(&new_list);
167  ret = string_alloc(buf_str(&new_list), gc);
168  }
169  free(tmp_ciphers);
170  free_buf(&new_list);
171 
172  return ret;
173 }
174 
175 
176 void
177 append_cipher_to_ncp_list(struct options *o, const char *ciphername)
178 {
179  /* Append the --cipher to ncp_ciphers to allow it in NCP */
180  size_t newlen = strlen(o->ncp_ciphers) + 1 + strlen(ciphername) + 1;
181  char *ncp_ciphers = gc_malloc(newlen, false, &o->gc);
182 
183  ASSERT(openvpn_snprintf(ncp_ciphers, newlen, "%s:%s", o->ncp_ciphers,
184  ciphername));
185  o->ncp_ciphers = ncp_ciphers;
186 }
187 
188 bool
189 tls_item_in_cipher_list(const char *item, const char *list)
190 {
191  char *tmp_ciphers = string_alloc(list, NULL);
192  char *tmp_ciphers_orig = tmp_ciphers;
193 
194  const char *token = strtok(tmp_ciphers, ":");
195  while (token)
196  {
197  if (0 == strcmp(token, item))
198  {
199  break;
200  }
201  token = strtok(NULL, ":");
202  }
203  free(tmp_ciphers_orig);
204 
205  return token != NULL;
206 }
207 
208 const char *
209 tls_peer_ncp_list(const char *peer_info, struct gc_arena *gc)
210 {
211  /* Check if the peer sends the IV_CIPHERS list */
212  const char *iv_ciphers = extract_var_peer_info(peer_info,"IV_CIPHERS=", gc);
213  if (iv_ciphers)
214  {
215  return iv_ciphers;
216  }
217  else if (tls_peer_info_ncp_ver(peer_info)>=2)
218  {
219  /* If the peer announces IV_NCP=2 then it supports the AES GCM
220  * ciphers */
221  return "AES-256-GCM:AES-128-GCM";
222  }
223  else
224  {
225  return "";
226  }
227 }
228 
229 char *
230 ncp_get_best_cipher(const char *server_list, const char *peer_info,
231  const char *remote_cipher, struct gc_arena *gc)
232 {
233  /*
234  * The gc of the parameter is tied to the VPN session, create a
235  * short lived gc arena that is only valid for the duration of
236  * this function
237  */
238 
239  struct gc_arena gc_tmp = gc_new();
240 
241  const char *peer_ncp_list = tls_peer_ncp_list(peer_info, &gc_tmp);
242 
243  /* non-NCP client without OCC? "assume nothing" */
244  /* For client doing the newer version of NCP (that send IV_CIPHER)
245  * we cannot assume that they will accept remote_cipher */
246  if (remote_cipher == NULL ||
247  (peer_info && strstr(peer_info, "IV_CIPHERS=")))
248  {
249  remote_cipher = "";
250  }
251 
252  char *tmp_ciphers = string_alloc(server_list, &gc_tmp);
253 
254  const char *token;
255  while ((token = strsep(&tmp_ciphers, ":")))
256  {
257  if (tls_item_in_cipher_list(token, peer_ncp_list)
258  || streq(token, remote_cipher))
259  {
260  break;
261  }
262  }
263 
264  char *ret = NULL;
265  if (token != NULL)
266  {
267  ret = string_alloc(token, gc);
268  }
269 
270  gc_free(&gc_tmp);
271  return ret;
272 }
273 
283 static bool
284 tls_poor_mans_ncp(struct options *o, const char *remote_ciphername)
285 {
286  if (remote_ciphername
287  && tls_item_in_cipher_list(remote_ciphername, o->ncp_ciphers))
288  {
289  o->ciphername = string_alloc(remote_ciphername, &o->gc);
290  msg(D_TLS_DEBUG_LOW, "Using peer cipher '%s'", o->ciphername);
291  return true;
292  }
293  return false;
294 }
295 
296 bool
297 check_pull_client_ncp(struct context *c, const int found)
298 {
299  if (found & OPT_P_NCP)
300  {
301  msg(D_PUSH, "OPTIONS IMPORT: data channel crypto options modified");
302  return true;
303  }
304 
305  /* If the server did not push a --cipher, we will switch to the
306  * remote cipher if it is in our ncp-ciphers list */
308  {
309  return true;
310  }
311 
312  /* We could not figure out the peer's cipher but we have fallback
313  * enabled */
315  {
316  return true;
317  }
318 
319  /* We failed negotiation, give appropiate error message */
321  {
322  msg(D_TLS_ERRORS, "OPTIONS ERROR: failed to negotiate "
323  "cipher with server. Add the server's "
324  "cipher ('%s') to --data-ciphers (currently '%s') if "
325  "you want to connect to this server.",
327  c->options.ncp_ciphers);
328  return false;
329 
330  }
331  else
332  {
333  msg(D_TLS_ERRORS, "OPTIONS ERROR: failed to negotiate "
334  "cipher with server. Configure "
335  "--data-ciphers-fallback if you want to connect "
336  "to this server.");
337  return false;
338  }
339 }
340 
341 const char*
342 get_p2p_ncp_cipher(struct tls_session *session, const char *peer_info,
343  struct gc_arena *gc)
344 {
345  /* we use a local gc arena to keep the temporary strings needed by strsep */
346  struct gc_arena gc_local = gc_new();
347  const char *peer_ciphers = extract_var_peer_info(peer_info, "IV_CIPHERS=", &gc_local);
348 
349  if (!peer_ciphers)
350  {
351  gc_free(&gc_local);
352  return NULL;
353  }
354 
355  const char* server_ciphers;
356  const char* client_ciphers;
357 
358  if (session->opt->server)
359  {
360  server_ciphers = session->opt->config_ncp_ciphers;
361  client_ciphers = peer_ciphers;
362  }
363  else
364  {
365  client_ciphers = session->opt->config_ncp_ciphers;
366  server_ciphers = peer_ciphers;
367  }
368 
369  /* Find the first common cipher from TLS server and TLS client. We
370  * use the preference of the server here to make it deterministic */
371  char *tmp_ciphers = string_alloc(server_ciphers, &gc_local);
372 
373  const char *token;
374  while ((token = strsep(&tmp_ciphers, ":")))
375  {
376  if (tls_item_in_cipher_list(token, client_ciphers))
377  {
378  break;
379  }
380  }
381 
382  const char *ret = NULL;
383  if (token != NULL)
384  {
385  ret = string_alloc(token, gc);
386  }
387  gc_free(&gc_local);
388 
389  return ret;
390 }
391 
392 static void
394 {
395  /* will return 0 if peer_info is null */
396  const unsigned int iv_proto_peer = extract_iv_proto(multi->peer_info);
397 
398  /* The other peer does not support P2P NCP */
399  if (!(iv_proto_peer & IV_PROTO_NCP_P2P))
400  {
401  return;
402  }
403 
404  if (iv_proto_peer & IV_PROTO_DATA_V2)
405  {
406  multi->use_peer_id = true;
407  multi->peer_id = 0x76706e; // 'v' 'p' 'n'
408  }
409 
410 #if defined(HAVE_EXPORT_KEYING_MATERIAL)
411  if (iv_proto_peer & IV_PROTO_TLS_KEY_EXPORT)
412  {
414 
415  if (multi->use_peer_id)
416  {
417  /* Using a non hardcoded peer-id makes a tiny bit harder to
418  * fingerprint packets and also gives each connection a unique
419  * peer-id that can be useful for NAT tracking etc. */
420 
421  uint8_t peerid[3];
423  strlen(EXPORT_P2P_PEERID_LABEL),
424  &peerid, 3))
425  {
426  /* Non DCO setup might still work but also this should never
427  * happen or very likely the TLS encryption key exporter will
428  * also fail */
429  msg(M_NONFATAL, "TLS key export for P2P peer id failed. "
430  "Continuing anyway, expect problems");
431  }
432  else
433  {
434  multi->peer_id = (peerid[0] << 16) + (peerid[1] << 8) + peerid[2];
435  }
436 
437  }
438  }
439 #endif
440 }
441 
442 void
443 p2p_mode_ncp(struct tls_multi *multi, struct tls_session *session)
444 {
445  /* Set the common options */
446  p2p_ncp_set_options(multi, session);
447 
448  struct gc_arena gc = gc_new();
449 
450  /* Query the common cipher here to log it as part of our message.
451  * We postpone switching the cipher to do_up */
452  const char* common_cipher = get_p2p_ncp_cipher(session, multi->peer_info, &gc);
453 
454  if (!common_cipher)
455  {
456  struct buffer out = alloc_buf_gc(128, &gc);
457  struct key_state *ks = get_key_scan(multi, KS_PRIMARY);
458 
460  const cipher_kt_t *cipher = cipher_ctx_get_cipher_kt(ctx);
461  const char *fallback_name = cipher_kt_name(cipher);
462 
463  if (!cipher)
464  {
465  /* at this point we do not really know if our fallback is
466  * not enabled or if we use 'none' cipher as fallback, so
467  * keep this ambiguity here and print fallback-cipher: none
468  */
469  fallback_name = "none";
470  }
471 
472  buf_printf(&out, "(not negotiated, fallback-cipher: %s)", fallback_name);
473  common_cipher = BSTR(&out);
474  }
475 
476  msg(D_TLS_DEBUG_LOW, "P2P mode NCP negotiation result: "
477  "TLS_export=%d, DATA_v2=%d, peer-id %d, cipher=%s",
478  (bool)(session->opt->crypto_flags & CO_USE_TLS_KEY_MATERIAL_EXPORT),
479  multi->use_peer_id, multi->peer_id, common_cipher);
480 
481  gc_free(&gc);
482 }
#define M_NONFATAL
Definition: error.h:99
#define IV_PROTO_NCP_P2P
Support doing NCP in P2P mode.
Definition: ssl.h:125
const cipher_kt_t * cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx)
Returns the static cipher parameters for this context.
mbedtls_cipher_context_t cipher_ctx_t
Generic cipher context.
Security parameter state of one TLS and data channel key session.
Definition: ssl_common.h:203
struct options options
Options loaded from command line or configuration file.
Definition: openvpn.h:463
void free_buf(struct buffer *buf)
Definition: buffer.c:185
#define D_TLS_DEBUG_LOW
Definition: errlevel.h:77
static int buf_len(const struct buffer *buf)
Definition: buffer.h:240
char * string_alloc(const char *str, struct gc_arena *gc)
Definition: buffer.c:685
bool enable_ncp_fallback
If defined fall back to ciphername if NCP fails.
Definition: options.h:517
#define IV_PROTO_DATA_V2
Support P_DATA_V2.
Definition: ssl.h:110
#define streq(x, y)
Definition: options.h:667
Contains all state information for one tunnel.
Definition: openvpn.h:461
#define D_PUSH
Definition: errlevel.h:83
struct tls_options * opt
Definition: ssl_common.h:457
char * peer_info
Definition: ssl_common.h:619
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
Security parameter state for a single VPN tunnel.
Definition: ssl_common.h:566
#define D_TLS_ERRORS
Definition: errlevel.h:59
static bool tls_poor_mans_ncp(struct options *o, const char *remote_ciphername)
"Poor man&#39;s NCP": Use peer cipher if it is an allowed (NCP) cipher.
Definition: ssl_ncp.c:284
struct buffer alloc_buf(size_t size)
Definition: buffer.c:64
unsigned int extract_iv_proto(const char *peer_info)
Extracts the IV_PROTO variable and returns its value or 0 if it cannot be extracted.
Definition: ssl_util.c:64
const char * config_ncp_ciphers
Definition: ssl_common.h:353
void p2p_mode_ncp(struct tls_multi *multi, struct tls_session *session)
Determines if there is common cipher of both peer by looking at the IV_CIPHER peer info...
Definition: ssl_ncp.c:443
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:242
#define EXPORT_P2P_PEERID_LABEL
Definition: ssl_backend.h:393
bool tls_item_in_cipher_list(const char *item, const char *list)
Return true iff item is present in the colon-separated zero-terminated cipher list.
Definition: ssl_ncp.c:189
#define ASSERT(x)
Definition: error.h:204
unsigned int crypto_flags
Definition: ssl_common.h:346
#define IV_PROTO_TLS_KEY_EXPORT
Supports key derivation via TLS key material exporter [RFC5705].
Definition: ssl.h:117
bool use_peer_id
Definition: ssl_common.h:643
bool tls_peer_supports_ncp(const char *peer_info)
Returns whether the client supports NCP either by announcing IV_NCP>=2 or the IV_CIPHERS list...
Definition: ssl_ncp.c:79
const char * ncp_ciphers
Definition: options.h:519
void append_cipher_to_ncp_list(struct options *o, const char *ciphername)
Appends the cipher specified by the ciphernamer parameter to to the o->ncp_ciphers list...
Definition: ssl_ncp.c:177
bool openvpn_snprintf(char *str, size_t size, const char *format,...)
Definition: buffer.c:296
#define MAX_NCP_CIPHERS_LENGTH
The maximum length of a ncp-cipher string that is accepted.
Definition: ssl_ncp.h:125
bool buf_puts(struct buffer *buf, const char *str)
Definition: buffer.c:269
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
#define KS_PRIMARY
Primary key state index.
Definition: ssl_common.h:430
void buf_null_terminate(struct buffer *buf)
Definition: buffer.c:569
struct crypto_options crypto_options
Definition: ssl_common.h:227
bool check_pull_client_ncp(struct context *c, const int found)
Checks whether the cipher negotiation is in an acceptable state and we continue to connect or should ...
Definition: ssl_ncp.c:297
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition: buffer.c:405
bool key_state_export_keying_material(struct tls_session *session, const char *label, size_t label_size, void *ekm, size_t ekm_size)
Keying Material Exporters [RFC 5705] allows additional keying material to be derived from existing TL...
Definition: ssl_openssl.c:159
cipher_ctx_t * cipher
Generic cipher context.
Definition: crypto.h:166
#define OPT_P_NCP
Negotiable crypto parameters.
Definition: options.h:684
const char * ciphername
Definition: options.h:516
static void p2p_ncp_set_options(struct tls_multi *multi, struct tls_session *session)
Definition: ssl_ncp.c:393
mbedtls_cipher_info_t cipher_kt_t
Generic cipher key type context.
struct key_ctx encrypt
Cipher and/or HMAC contexts for sending direction.
Definition: crypto.h:221
#define CO_USE_TLS_KEY_MATERIAL_EXPORT
Bit-flag indicating that data channel key derivation is done using TLS keying material export [RFC570...
Definition: crypto.h:257
static int buf_forward_capacity(const struct buffer *buf)
Definition: buffer.h:562
char * ncp_get_best_cipher(const char *server_list, const char *peer_info, const char *remote_cipher, struct gc_arena *gc)
Iterates through the ciphers in server_list and return the first cipher that is also supported by the...
Definition: ssl_ncp.c:230
static struct key_state * get_key_scan(struct tls_multi *multi, int index)
gets an item of key_state objects in the order they should be scanned by data channel modules...
Definition: ssl_common.h:661
char * remote_ciphername
cipher specified in peer&#39;s config file
Definition: ssl_common.h:645
static char * buf_str(const struct buffer *buf)
Definition: buffer.h:284
struct context_2 c2
Level 2 context.
Definition: openvpn.h:502
char * strsep(char **stringp, const char *delim)
Definition: compat-strsep.c:38
const char * get_p2p_ncp_cipher(struct tls_session *session, const char *peer_info, struct gc_arena *gc)
Determines the best common cipher from both peers IV_CIPHER lists.
Definition: ssl_ncp.c:342
#define msg(flags,...)
Definition: error.h:153
struct key_ctx_bi key_ctx_bi
OpenSSL cipher and HMAC contexts for both sending and receiving directions.
Definition: crypto.h:234
Security parameter state of a single session within a VPN tunnel.
Definition: ssl_common.h:454
const char * tls_peer_ncp_list(const char *peer_info, struct gc_arena *gc)
Returns the support cipher list from the peer according to the IV_NCP and IV_CIPHER values in peer_in...
Definition: ssl_ncp.c:209
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:90
uint32_t peer_id
Definition: ssl_common.h:642
#define M_WARN
Definition: error.h:100
static int tls_peer_info_ncp_ver(const char *peer_info)
Return the Negotiable Crypto Parameters version advertised in the peer info string, or 0 if none specified.
Definition: ssl_ncp.c:59
#define free
Definition: cmocka.c:1850
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
char * extract_var_peer_info(const char *peer_info, const char *var, struct gc_arena *gc)
Extracts a variable from peer info, the returned string will be allocated using the supplied gc_arena...
Definition: ssl_util.c:34
#define BSTR(buf)
Definition: buffer.h:129
char * mutate_ncp_cipher_list(const char *list, struct gc_arena *gc)
Check whether the ciphers in the supplied list are supported.
Definition: ssl_ncp.c:97
struct gc_arena gc
Definition: options.h:215
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
Definition: openvpn.h:319
const cipher_kt_t * cipher_kt_get(const char *ciphername)
Return cipher parameters, based on the given cipher name.
const char * cipher_kt_name(const cipher_kt_t *cipher_kt)
Retrieve a string describing the cipher (e.g.