diff options
Diffstat (limited to 'src/openvpn/ssl.c')
-rw-r--r-- | src/openvpn/ssl.c | 1132 |
1 files changed, 717 insertions, 415 deletions
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 9e31c3c..dc06350 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -35,7 +35,6 @@ * Both the TLS session and the data channel are multiplexed * over the same TCP/UDP port. */ - #ifdef HAVE_CONFIG_H #include "config.h" #elif defined(_MSC_VER) @@ -45,11 +44,10 @@ #include "syshead.h" #include "win32.h" -#if defined(ENABLE_CRYPTO) && defined(ENABLE_SSL) +#if defined(ENABLE_CRYPTO) #include "error.h" #include "common.h" -#include "integer.h" #include "socket.h" #include "misc.h" #include "fdmisc.h" @@ -58,9 +56,8 @@ #include "status.h" #include "gremlin.h" #include "pkcs11.h" -#include "list.h" -#include "base64.h" #include "route.h" +#include "tls_crypt.h" #include "ssl.h" #include "ssl_verify.h" @@ -150,6 +147,7 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"DHE-RSA-CAMELLIA128-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, {"DHE-RSA-CAMELLIA256-SHA256", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, {"DHE-RSA-CAMELLIA256-SHA", "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, + {"DHE-RSA-CHACHA20-POLY1305", "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256"}, {"DHE-RSA-SEED-SHA", "TLS-DHE-RSA-WITH-SEED-CBC-SHA"}, {"DH-RSA-SEED-SHA", "TLS-DH-RSA-WITH-SEED-CBC-SHA"}, {"ECDH-ECDSA-AES128-GCM-SHA256", "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256"}, @@ -178,6 +176,7 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"ECDHE-ECDSA-CAMELLIA128-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA"}, {"ECDHE-ECDSA-CAMELLIA256-SHA256", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA256"}, {"ECDHE-ECDSA-CAMELLIA256-SHA", "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA"}, + {"ECDHE-ECDSA-CHACHA20-POLY1305", "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256"}, {"ECDHE-ECDSA-DES-CBC3-SHA", "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA"}, {"ECDHE-ECDSA-DES-CBC-SHA", "TLS-ECDHE-ECDSA-WITH-DES-CBC-SHA"}, {"ECDHE-ECDSA-RC4-SHA", "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA"}, @@ -193,6 +192,7 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"ECDHE-RSA-CAMELLIA128-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA"}, {"ECDHE-RSA-CAMELLIA256-SHA256", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA256"}, {"ECDHE-RSA-CAMELLIA256-SHA", "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA"}, + {"ECDHE-RSA-CHACHA20-POLY1305", "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"}, {"ECDHE-RSA-DES-CBC3-SHA", "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA"}, {"ECDHE-RSA-DES-CBC-SHA", "TLS-ECDHE-RSA-WITH-DES-CBC-SHA"}, {"ECDHE-RSA-RC4-SHA", "TLS-ECDHE-RSA-WITH-RC4-128-SHA"}, @@ -237,21 +237,37 @@ static const tls_cipher_name_pair tls_cipher_name_translation_table[] = { {"SRP-RSA-AES-128-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-128-CBC-SHA"}, {"SRP-RSA-AES-256-CBC-SHA", "TLS-SRP-SHA-RSA-WITH-AES-256-CBC-SHA"}, #ifdef ENABLE_CRYPTO_OPENSSL + /* OpenSSL-specific group names */ {"DEFAULT", "DEFAULT"}, {"ALL", "ALL"}, - {"HIGH", "HIGH"}, - {"MEDIUM", "MEDIUM"}, - {"LOW", "LOW"}, - {"ECDH", "ECDH"}, - {"ECDSA", "ECDSA"}, - {"EDH", "EDH"}, - {"EXP", "EXP"}, - {"RSA", "RSA"}, - {"SRP", "SRP"}, + {"HIGH", "HIGH"}, {"!HIGH", "!HIGH"}, + {"MEDIUM", "MEDIUM"}, {"!MEDIUM", "!MEDIUM"}, + {"LOW", "LOW"}, {"!LOW", "!LOW"}, + {"ECDH", "ECDH"}, {"!ECDH", "!ECDH"}, + {"ECDSA", "ECDSA"}, {"!ECDSA", "!ECDSA"}, + {"EDH", "EDH"}, {"!EDH", "!EDH"}, + {"EXP", "EXP"}, {"!EXP", "!EXP"}, + {"RSA", "RSA"}, {"!RSA", "!RSA"}, + {"kRSA", "kRSA"}, {"!kRSA", "!kRSA"}, + {"SRP", "SRP"}, {"!SRP", "!SRP"}, #endif {NULL, NULL} }; +/** + * Update the implicit IV for a key_ctx_bi based on TLS session ids and cipher + * used. + * + * Note that the implicit IV is based on the HMAC key, but only in AEAD modes + * where the HMAC key is not used for an actual HMAC. + * + * @param ctx Encrypt/decrypt key context + * @param key HMAC key, used to calculate implicit IV + * @param key_len HMAC key length + */ +static void +key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len); + const tls_cipher_name_pair * tls_get_cipher_name_pair (const char * cipher_name, size_t len) { const tls_cipher_name_pair * pair = tls_cipher_name_translation_table; @@ -268,6 +284,27 @@ tls_get_cipher_name_pair (const char * cipher_name, size_t len) { return NULL; } +/** + * Limit the reneg_bytes value when using a small-block (<128 bytes) cipher. + * + * @param cipher The current cipher (may be NULL). + * @param reneg_bytes Pointer to the current reneg_bytes, updated if needed. + * May *not* be NULL. + */ +static void +tls_limit_reneg_bytes (const cipher_kt_t *cipher, int *reneg_bytes) +{ + if (cipher && (cipher_kt_block_size(cipher) < 128/8)) + { + if (*reneg_bytes == -1) /* Not user-specified */ + { + msg (M_WARN, "WARNING: cipher with small block size in use, " + "reducing reneg-bytes to 64MB to mitigate SWEET32 attacks."); + *reneg_bytes = 64 * 1024 * 1024; + } + } +} + /* * Max number of bytes we will add * for data structures common to both @@ -488,12 +525,15 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) if (options->tls_server) { - tls_ctx_server_new(new_ctx, options->ssl_flags); - tls_ctx_load_dh_params(new_ctx, options->dh_file, options->dh_file_inline); + tls_ctx_server_new(new_ctx); + + if (options->dh_file) + tls_ctx_load_dh_params(new_ctx, options->dh_file, + options->dh_file_inline); } else /* if client */ { - tls_ctx_client_new(new_ctx, options->ssl_flags); + tls_ctx_client_new(new_ctx); } tls_ctx_set_options(new_ctx, options->ssl_flags); @@ -522,10 +562,19 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) } #endif #ifdef MANAGMENT_EXTERNAL_KEY - else if ((options->management_flags & MF_EXTERNAL_KEY) && options->cert_file) - { - tls_ctx_use_external_private_key(new_ctx, options->cert_file, - options->cert_file_inline); + else if ((options->management_flags & MF_EXTERNAL_KEY) && + (options->cert_file || options->management_flags & MF_EXTERNAL_CERT)) + { + if (options->cert_file) { + tls_ctx_use_external_private_key(new_ctx, options->cert_file, + options->cert_file_inline); + } else { + char *external_certificate = management_query_cert(management, + options->management_certificate); + tls_ctx_use_external_private_key(new_ctx, INLINE_FILE_TAG, + external_certificate); + free(external_certificate); + } } #endif else @@ -552,7 +601,7 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) /* Load extra certificates that are part of our own certificate chain but shouldn't be included in the verify chain */ - if (options->extra_certs_file || options->extra_certs_file_inline) + if (options->extra_certs_file) { tls_ctx_load_extra_certs(new_ctx, options->extra_certs_file, options->extra_certs_file_inline); } @@ -560,10 +609,20 @@ init_ssl (const struct options *options, struct tls_root_ctx *new_ctx) /* Check certificate notBefore and notAfter */ tls_ctx_check_cert_time(new_ctx); + /* Read CRL */ + if (options->crl_file && !(options->ssl_flags & SSLF_CRL_VERIFY_DIR)) + { + tls_ctx_reload_crl(new_ctx, options->crl_file, options->crl_file_inline); + } + + /* Once keys and cert are loaded, load ECDH parameters */ + if (options->tls_server) + tls_ctx_load_ecdh_params(new_ctx, options->ecdh_curve); + /* Allowable ciphers */ tls_ctx_restrict_ciphers(new_ctx, options->cipher_list); -#ifdef ENABLE_CRYPTO_POLARSSL +#ifdef ENABLE_CRYPTO_MBEDTLS /* Personalise the random by mixing in the certificate */ tls_ctx_personalise_random (new_ctx); #endif @@ -766,11 +825,17 @@ key_state_init (struct tls_session *session, struct key_state *ks) reliable_set_timeout (ks->send_reliable, session->opt->packet_timeout); /* init packet ID tracker */ - packet_id_init (&ks->packet_id, - session->opt->tcp_mode, - session->opt->replay_window, - session->opt->replay_time, - "SSL", ks->key_id); + if (session->opt->replay) + { + packet_id_init (&ks->crypto_options.packet_id, + session->opt->replay_window, session->opt->replay_time, "SSL", + ks->key_id); + } + + ks->crypto_options.pid_persist = NULL; + ks->crypto_options.flags = session->opt->crypto_flags; + ks->crypto_options.flags &= session->opt->crypto_flags_and; + ks->crypto_options.flags |= session->opt->crypto_flags_or; #ifdef MANAGEMENT_DEF_AUTH ks->mda_key_id = session->opt->mda_context->mda_key_id_counter++; @@ -798,7 +863,7 @@ key_state_free (struct key_state *ks, bool clear) key_state_ssl_free(&ks->ks_ssl); - free_key_ctx_bi (&ks->key); + free_key_ctx_bi (&ks->crypto_options.key_ctx_bi); free_buf (&ks->plaintext_read_buf); free_buf (&ks->plaintext_write_buf); free_buf (&ks->ack_write_buf); @@ -822,7 +887,7 @@ key_state_free (struct key_state *ks, bool clear) if (ks->key_src) free (ks->key_src); - packet_id_free (&ks->packet_id); + packet_id_free (&ks->crypto_options.packet_id); #ifdef PLUGIN_DEF_AUTH key_state_rm_auth_control_file (ks); @@ -837,11 +902,23 @@ key_state_free (struct key_state *ks, bool clear) /** @} addtogroup control_processor */ -/* - * Must be called if we move a tls_session in memory. +/** + * Returns whether or not the server should check for username/password + * + * @param session The current TLS session + * + * @return true if username and password verification is enabled, + * false if not. */ -static inline void tls_session_set_self_referential_pointers (struct tls_session* session) { - session->tls_auth.packet_id = &session->tls_auth_pid; +static inline bool +tls_session_user_pass_enabled(struct tls_session *session) +{ + return (session->opt->auth_user_pass_verify_script + || plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) +#ifdef MANAGEMENT_DEF_AUTH + || management_enable_def_auth (management) +#endif + ); } @@ -895,20 +972,18 @@ tls_session_init (struct tls_multi *multi, struct tls_session *session) } /* Initialize control channel authentication parameters */ - session->tls_auth = session->opt->tls_auth; - - /* Set session internal pointers (also called if session object is moved in memory) */ - tls_session_set_self_referential_pointers (session); + session->tls_wrap = session->opt->tls_wrap; + session->tls_wrap.work = alloc_buf (TLS_CHANNEL_BUF_SIZE); /* initialize packet ID replay window for --tls-auth */ - packet_id_init (session->tls_auth.packet_id, - session->opt->tcp_mode, + packet_id_init (&session->tls_wrap.opt.packet_id, session->opt->replay_window, session->opt->replay_time, - "TLS_AUTH", session->key_id); + "TLS_WRAP", session->key_id); /* load most recent packet-id to replay protect on --tls-auth */ - packet_id_persist_load_obj (session->tls_auth.pid_persist, session->tls_auth.packet_id); + packet_id_persist_load_obj (session->tls_wrap.opt.pid_persist, + &session->tls_wrap.opt.packet_id); key_state_init (session, &session->key[KS_PRIMARY]); @@ -935,8 +1010,10 @@ tls_session_free (struct tls_session *session, bool clear) { int i; - if (session->tls_auth.packet_id) - packet_id_free (session->tls_auth.packet_id); + if (packet_id_initialized(&session->tls_wrap.opt.packet_id)) + packet_id_free (&session->tls_wrap.opt.packet_id); + + free_buf (&session->tls_wrap.work); for (i = 0; i < KS_SIZE; ++i) key_state_free (&session->key[i], false); @@ -967,7 +1044,6 @@ move_session (struct tls_multi* multi, int dest, int src, bool reinit_src) ASSERT (dest >= 0 && dest < TM_SIZE); tls_session_free (&multi->session[dest], false); multi->session[dest] = multi->session[src]; - tls_session_set_self_referential_pointers (&multi->session[dest]); if (reinit_src) tls_session_init (multi, &multi->session[src]); @@ -984,22 +1060,6 @@ reset_session (struct tls_multi *multi, struct tls_session *session) tls_session_init (multi, session); } -#if 0 -/* - * Transmit a TLS reset on our untrusted channel. - */ -static void -initiate_untrusted_session (struct tls_multi *multi, struct sockaddr_in *to) -{ - struct tls_session *session = &multi->session[TM_UNTRUSTED]; - struct key_state *ks = &session->key[KS_PRIMARY]; - - reset_session (multi, session); - ks->remote_addr = *to; - msg (D_TLS_DEBUG_LOW, "TLS: initiate_untrusted_session: addr=%s", print_sockaddr (to)); -} -#endif - /* * Used to determine in how many seconds we should be * called again. @@ -1048,9 +1108,6 @@ tls_multi_init (struct tls_options *tls_options) /* get command line derived options */ ret->opt = *tls_options; - /* set up pointer to HMAC object for TLS packet authentication */ - ret->opt.tls_auth.key_ctx_bi = &ret->opt.tls_auth_key; - /* set up list of keys to be scanned by data channel encrypt and decrypt routines */ ASSERT (SIZE (ret->key_scan) == 3); ret->key_scan[0] = &ret->session[TM_ACTIVE].key[KS_PRIMARY]; @@ -1088,10 +1145,14 @@ tls_auth_standalone_init (struct tls_options *tls_options, ALLOC_OBJ_CLEAR_GC (tas, struct tls_auth_standalone, gc); - /* set up pointer to HMAC object for TLS packet authentication */ - tas->tls_auth_key = tls_options->tls_auth_key; - tas->tls_auth_options.key_ctx_bi = &tas->tls_auth_key; - tas->tls_auth_options.flags |= CO_PACKET_ID_LONG_FORM; + tas->tls_wrap = tls_options->tls_wrap; + + /* + * Standalone tls-auth is in read-only mode with respect to TLS + * control channel state. After we build a new client instance + * object, we will process this session-initiating packet for real. + */ + tas->tls_wrap.opt.flags |= CO_IGNORE_PACKET_ID; /* get initial frame parms, still need to finalize */ tas->frame = tls_options->frame; @@ -1136,6 +1197,8 @@ tls_multi_free (struct tls_multi *multi, bool clear) #ifdef MANAGEMENT_DEF_AUTH man_def_auth_set_client_reason(multi, NULL); +#endif +#if P2MP_SERVER free (multi->peer_info); #endif @@ -1147,6 +1210,12 @@ tls_multi_free (struct tls_multi *multi, bool clear) cert_hash_free (multi->locked_cert_hash_set); + if (multi->auth_token) + { + memset (multi->auth_token, 0, AUTH_TOKEN_SIZE); + free (multi->auth_token); + } + for (i = 0; i < TM_SIZE; ++i) tls_session_free (&multi->session[i], false); @@ -1171,11 +1240,11 @@ tls_multi_free (struct tls_multi *multi, bool clear) static bool swap_hmac (struct buffer *buf, const struct crypto_options *co, bool incoming) { - struct key_ctx *ctx; + const struct key_ctx *ctx; ASSERT (co); - ctx = (incoming ? &co->key_ctx_bi->decrypt : &co->key_ctx_bi->encrypt); + ctx = (incoming ? &co->key_ctx_bi.decrypt : &co->key_ctx_bi.encrypt); ASSERT (ctx->hmac); { @@ -1230,20 +1299,34 @@ write_control_auth (struct tls_session *session, int max_ack, bool prepend_ack) { - uint8_t *header; + uint8_t header = ks->key_id | (opcode << P_OPCODE_SHIFT); struct buffer null = clear_buf (); ASSERT (link_socket_actual_defined (&ks->remote_addr)); ASSERT (reliable_ack_write (ks->rec_ack, buf, &ks->session_id_remote, max_ack, prepend_ack)); - ASSERT (session_id_write_prepend (&session->session_id, buf)); - ASSERT (header = buf_prepend (buf, 1)); - *header = ks->key_id | (opcode << P_OPCODE_SHIFT); - if (session->tls_auth.key_ctx_bi->encrypt.hmac) + + if (session->tls_wrap.mode == TLS_WRAP_AUTH || + session->tls_wrap.mode == TLS_WRAP_NONE) + { + ASSERT (session_id_write_prepend (&session->session_id, buf)); + ASSERT (buf_write_prepend (buf, &header, sizeof(header))); + } + if (session->tls_wrap.mode == TLS_WRAP_AUTH) { /* no encryption, only write hmac */ - openvpn_encrypt (buf, null, &session->tls_auth, NULL); - ASSERT (swap_hmac (buf, &session->tls_auth, false)); + openvpn_encrypt (buf, null, &session->tls_wrap.opt); + ASSERT (swap_hmac (buf, &session->tls_wrap.opt, false)); + } + else if (session->tls_wrap.mode == TLS_WRAP_CRYPT) + { + buf_init (&session->tls_wrap.work, buf->offset); + ASSERT (buf_write (&session->tls_wrap.work, &header, sizeof(header))); + ASSERT (session_id_write (&session->session_id, &session->tls_wrap.work)); + ASSERT (tls_crypt_wrap (buf, &session->tls_wrap.work, &session->tls_wrap.opt)); + /* Don't change the original data in buf, it's used by the reliability + * layer to resend on failure. */ + *buf = session->tls_wrap.work; } *to_link_addr = &ks->remote_addr; } @@ -1253,17 +1336,18 @@ write_control_auth (struct tls_session *session, */ static bool read_control_auth (struct buffer *buf, - const struct crypto_options *co, + struct tls_wrap_ctx *ctx, const struct link_socket_actual *from) { struct gc_arena gc = gc_new (); + bool ret = false; - if (co->key_ctx_bi->decrypt.hmac) + if (ctx->mode == TLS_WRAP_AUTH) { struct buffer null = clear_buf (); /* move the hmac record to the front of the packet */ - if (!swap_hmac (buf, co, true)) + if (!swap_hmac (buf, &ctx->opt, true)) { msg (D_TLS_ERRORS, "TLS Error: cannot locate HMAC in incoming packet from %s", @@ -1274,24 +1358,41 @@ read_control_auth (struct buffer *buf, /* authenticate only (no decrypt) and remove the hmac record from the head of the buffer */ - openvpn_decrypt (buf, null, co, NULL); + openvpn_decrypt (buf, null, &ctx->opt, NULL, BPTR (buf)); if (!buf->len) { msg (D_TLS_ERRORS, "TLS Error: incoming packet authentication failed from %s", print_link_socket_actual (from, &gc)); - gc_free (&gc); - return false; + goto cleanup; } } + else if (ctx->mode == TLS_WRAP_CRYPT) + { + struct buffer tmp = alloc_buf (buf_forward_capacity_total (buf)); + if (!tls_crypt_unwrap (buf, &tmp, &ctx->opt)) + { + msg (D_TLS_ERRORS, "TLS Error: tls-crypt unwrapping failed from %s", + print_link_socket_actual (from, &gc)); + goto cleanup; + } + ASSERT (buf_init (buf, buf->offset)); + ASSERT (buf_copy (buf, &tmp)); + free_buf (&tmp); + } - /* advance buffer pointer past opcode & session_id since our caller - already read it */ - buf_advance (buf, SID_SIZE + 1); + if (ctx->mode == TLS_WRAP_NONE || ctx->mode == TLS_WRAP_AUTH) + { + /* advance buffer pointer past opcode & session_id since our caller + already read it */ + buf_advance (buf, SID_SIZE + 1); + } + ret = true; +cleanup: gc_free (&gc); - return true; + return ret; } /* @@ -1352,7 +1453,7 @@ tls1_P_hash(const md_kt_t *md_kt, int olen) { struct gc_arena gc = gc_new (); - int chunk,n; + int chunk; hmac_ctx_t ctx; hmac_ctx_t ctx_tmp; uint8_t A1[MAX_HMAC_KEY_LENGTH]; @@ -1378,7 +1479,6 @@ tls1_P_hash(const md_kt_t *md_kt, hmac_ctx_update(&ctx,seed,seed_len); hmac_ctx_final(&ctx, A1); - n=0; for (;;) { hmac_ctx_reset(&ctx); @@ -1429,7 +1529,7 @@ tls1_P_hash(const md_kt_t *md_kt, * (2) The pre-master secret is generated by the client. */ static void -tls1_PRF(uint8_t *label, +tls1_PRF(const uint8_t *label, int label_len, const uint8_t *sec, int slen, @@ -1581,6 +1681,13 @@ generate_key_expansion (struct key_ctx_bi *key, OPENVPN_OP_DECRYPT, "Data Channel Decrypt"); + /* Initialize implicit IVs */ + key_ctx_update_implicit_iv (&key->encrypt, key2.keys[(int)server].hmac, + MAX_HMAC_KEY_LENGTH); + key_ctx_update_implicit_iv (&key->decrypt, key2.keys[1-(int)server].hmac, + MAX_HMAC_KEY_LENGTH); + + key->initialized = true; ret = true; exit: @@ -1590,6 +1697,96 @@ generate_key_expansion (struct key_ctx_bi *key, return ret; } +static void +key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len) { + const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt (ctx->cipher); + + /* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */ + if (cipher_kt_mode_aead (cipher_kt)) + { + size_t impl_iv_len = 0; + ASSERT (cipher_kt_iv_size (cipher_kt) >= OPENVPN_AEAD_MIN_IV_LEN); + impl_iv_len = cipher_kt_iv_size (cipher_kt) - sizeof (packet_id_type); + ASSERT (impl_iv_len <= OPENVPN_MAX_IV_LENGTH); + ASSERT (impl_iv_len <= key_len); + memcpy (ctx->implicit_iv, key, impl_iv_len); + ctx->implicit_iv_len = impl_iv_len; + } +} + +static bool +item_in_list(const char *item, const char *list) +{ + char *tmp_ciphers = string_alloc (list, NULL); + char *tmp_ciphers_orig = tmp_ciphers; + + const char *token = strtok (tmp_ciphers, ":"); + while(token) + { + if (0 == strcmp (token, item)) + break; + token = strtok (NULL, ":"); + } + free(tmp_ciphers_orig); + + return token != NULL; +} + +bool +tls_session_update_crypto_params(struct tls_session *session, + const struct options *options, struct frame *frame) +{ + bool ret = false; + struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ + + ASSERT (ks->authenticated); + + if (!session->opt->server && + 0 != strcmp(options->ciphername, session->opt->config_ciphername) && + !item_in_list(options->ciphername, options->ncp_ciphers)) + { + msg (D_TLS_ERRORS, "Error: pushed cipher not allowed - %s not in %s or %s", + options->ciphername, session->opt->config_ciphername, + options->ncp_ciphers); + return false; + } + + init_key_type (&session->opt->key_type, options->ciphername, + options->authname, options->keysize, true, true); + + bool packet_id_long_form = cipher_kt_mode_ofb_cfb (session->opt->key_type.cipher); + session->opt->crypto_flags_and &= ~(CO_PACKET_ID_LONG_FORM); + if (packet_id_long_form) + session->opt->crypto_flags_and = CO_PACKET_ID_LONG_FORM; + + /* Update frame parameters: undo worst-case overhead, add actual overhead */ + frame_add_to_extra_frame (frame, -(crypto_max_overhead())); + crypto_adjust_frame_parameters (frame, &session->opt->key_type, + options->use_iv, options->replay, packet_id_long_form); + frame_finalize(frame, options->ce.link_mtu_defined, options->ce.link_mtu, + options->ce.tun_mtu_defined, options->ce.tun_mtu); + frame_init_mssfix(frame, options); + frame_print (frame, D_MTU_INFO, "Data Channel MTU parms"); + + const struct session_id *client_sid = session->opt->server ? + &ks->session_id_remote : &session->session_id; + const struct session_id *server_sid = !session->opt->server ? + &ks->session_id_remote : &session->session_id; + if (!generate_key_expansion (&ks->crypto_options.key_ctx_bi, + &session->opt->key_type, ks->key_src, client_sid, server_sid, + session->opt->server)) + { + msg (D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed"); + goto cleanup; + } + tls_limit_reneg_bytes (session->opt->key_type.cipher, + &session->opt->renegotiate_bytes); + ret = true; +cleanup: + CLEAR (*ks->key_src); + return ret; +} + static bool random_bytes_to_buf (struct buffer *buf, uint8_t *out, @@ -1762,7 +1959,6 @@ key_method_1_write (struct buffer *buf, struct tls_session *session) { struct key key; struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - struct key_state *ks_lame = &session->key[KS_LAME_DUCK]; /* retiring key */ ASSERT (session->opt->key_method == 1); ASSERT (buf_init (buf, 0)); @@ -1780,8 +1976,9 @@ key_method_1_write (struct buffer *buf, struct tls_session *session) return false; } - init_key_ctx (&ks->key.encrypt, &key, &session->opt->key_type, - OPENVPN_OP_ENCRYPT, "Data Channel Encrypt"); + init_key_ctx (&ks->crypto_options.key_ctx_bi.encrypt, &key, + &session->opt->key_type, OPENVPN_OP_ENCRYPT, + "Data Channel Encrypt"); CLEAR (key); /* send local options string */ @@ -1827,17 +2024,30 @@ push_peer_info(struct buffer *buf, struct tls_session *session) buf_printf (&out, "IV_PLAT=netbsd\n"); #elif defined(TARGET_FREEBSD) buf_printf (&out, "IV_PLAT=freebsd\n"); -#elif defined(WIN32) +#elif defined(TARGET_ANDROID) + buf_printf (&out, "IV_PLAT=android\n"); +#elif defined(_WIN32) buf_printf (&out, "IV_PLAT=win\n"); #endif - /* push LZO status */ -#ifdef ENABLE_LZO_STUB - buf_printf (&out, "IV_LZO_STUB=1\n"); -#endif /* support for P_DATA_V2 */ buf_printf(&out, "IV_PROTO=2\n"); + /* support for Negotiable Crypto Paramters */ + if (session->opt->ncp_enabled && + (session->opt->mode == MODE_SERVER || session->opt->pull)) + { + buf_printf(&out, "IV_NCP=2\n"); + } + + /* push compression status */ +#ifdef USE_COMP + comp_generate_peer_info_string(&session->opt->comp_options, &out); +#endif + + /* support for redirecting IPv6 gateway */ + buf_printf(&out, "IV_RGI6=1\n"); + if (session->opt->push_peer_info_detail >= 2) { /* push mac addr */ @@ -1846,17 +2056,19 @@ push_peer_info(struct buffer *buf, struct tls_session *session) if (rgi.flags & RGI_HWADDR_DEFINED) buf_printf (&out, "IV_HWADDR=%s\n", format_hex_ex (rgi.hwaddr, 6, 0, 1, ":", &gc)); buf_printf (&out, "IV_SSL=%s\n", get_ssl_library_version() ); -#if defined(WIN32) +#if defined(_WIN32) buf_printf (&out, "IV_PLAT_VER=%s\n", win32_version_string (&gc, false)); #endif } - /* push env vars that begin with UV_ and IV_GUI_VER */ + /* push env vars that begin with UV_, IV_PLAT_VER and IV_GUI_VER */ for (e=es->list; e != NULL; e=e->next) { if (e->string) { - if (((strncmp(e->string, "UV_", 3)==0 && session->opt->push_peer_info_detail >= 2) + if ((((strncmp(e->string, "UV_", 3)==0 || + strncmp(e->string, "IV_PLAT_VER=", sizeof("IV_PLAT_VER=")-1)==0) + && session->opt->push_peer_info_detail >= 2) || (strncmp(e->string,"IV_GUI_VER=",sizeof("IV_GUI_VER=")-1)==0)) && buf_safe(&out, strlen(e->string)+1)) buf_printf (&out, "%s\n", e->string); @@ -1883,7 +2095,6 @@ static bool key_method_2_write (struct buffer *buf, struct tls_session *session) { struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - struct key_state *ks_lame = &session->key[KS_LAME_DUCK]; /* retiring key */ ASSERT (session->opt->key_method == 2); ASSERT (buf_init (buf, 0)); @@ -1931,14 +2142,17 @@ key_method_2_write (struct buffer *buf, struct tls_session *session) if (!push_peer_info (buf, session)) goto error; - /* - * generate tunnel keys if server + /* Generate tunnel keys if we're a TLS server. + * If we're a p2mp server and IV_NCP >= 2 is negotiated, the first key + * generation is postponed until after the pull/push, so we can process pushed + * cipher directives. */ - if (session->opt->server) + if (session->opt->server && !(session->opt->ncp_enabled && + session->opt->mode == MODE_SERVER && ks->key_id <= 0)) { if (ks->authenticated) { - if (!generate_key_expansion (&ks->key, + if (!generate_key_expansion (&ks->crypto_options.key_ctx_bi, &session->opt->key_type, ks->key_src, &ks->session_id_remote, @@ -1951,6 +2165,8 @@ key_method_2_write (struct buffer *buf, struct tls_session *session) } CLEAR (*ks->key_src); + tls_limit_reneg_bytes (session->opt->key_type.cipher, + &session->opt->renegotiate_bytes); } return true; @@ -1967,7 +2183,6 @@ key_method_1_read (struct buffer *buf, struct tls_session *session) int status; struct key key; struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - struct key_state *ks_lame = &session->key[KS_LAME_DUCK]; /* retiring key */ ASSERT (session->opt->key_method == 1); @@ -2010,8 +2225,9 @@ key_method_1_read (struct buffer *buf, struct tls_session *session) buf_clear (buf); - init_key_ctx (&ks->key.decrypt, &key, &session->opt->key_type, - OPENVPN_OP_DECRYPT, "Data Channel Decrypt"); + init_key_ctx (&ks->crypto_options.key_ctx_bi.decrypt, &key, + &session->opt->key_type, OPENVPN_OP_DECRYPT, + "Data Channel Decrypt"); CLEAR (key); ks->authenticated = true; return true; @@ -2026,13 +2242,13 @@ static bool key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_session *session) { struct key_state *ks = &session->key[KS_PRIMARY]; /* primary key */ - struct key_state *ks_lame = &session->key[KS_LAME_DUCK]; /* retiring key */ int key_method_flags; bool username_status, password_status; struct gc_arena gc = gc_new (); char *options; + struct user_pass *up; /* allocate temporary objects */ ALLOC_ARRAY_CLEAR_GC (options, char, TLS_OPTIONS_LEN, &gc); @@ -2072,15 +2288,31 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi ks->authenticated = false; - if (verify_user_pass_enabled(session)) - { - /* Perform username/password authentication */ - struct user_pass *up; + /* always extract username + password fields from buf, even if not + * authenticating for it, because otherwise we can't get at the + * peer_info data which follows behind + */ + ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc); + username_status = read_string (buf, up->username, USER_PASS_LEN); + password_status = read_string (buf, up->password, USER_PASS_LEN); + +#if P2MP_SERVER + /* get peer info from control channel */ + free (multi->peer_info); + multi->peer_info = read_string_alloc (buf); + if ( multi->peer_info ) + output_peer_info_env (session->opt->es, multi->peer_info); - ALLOC_OBJ_CLEAR_GC (up, struct user_pass, &gc); - username_status = read_string (buf, up->username, USER_PASS_LEN); - password_status = read_string (buf, up->password, USER_PASS_LEN); + if (tls_peer_info_ncp_ver (multi->peer_info) < 2) + { + /* Peer does not support NCP */ + session->opt->ncp_enabled = false; + } +#endif + if (tls_session_user_pass_enabled(session)) + { + /* Perform username/password authentication */ if (!username_status || !password_status) { CLEAR (*up); @@ -2091,14 +2323,7 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi } } -#ifdef MANAGEMENT_DEF_AUTH - /* get peer info from control channel */ - free (multi->peer_info); - multi->peer_info = read_string_alloc (buf); -#endif - verify_user_pass(up, multi, session); - CLEAR (*up); } else { @@ -2112,6 +2337,9 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi ks->authenticated = true; } + /* clear username and password from memory */ + CLEAR (*up); + /* Perform final authentication checks */ if (ks->authenticated) { @@ -2140,16 +2368,22 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi */ if (ks->authenticated && plugin_defined (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL)) { + key_state_export_keying_material(&ks->ks_ssl, session); + if (plugin_call (session->opt->plugins, OPENVPN_PLUGIN_TLS_FINAL, NULL, NULL, session->opt->es) != OPENVPN_PLUGIN_FUNC_SUCCESS) ks->authenticated = false; + + setenv_del (session->opt->es, "exported_keying_material"); } /* - * Generate tunnel keys if client + * Generate tunnel keys if we're a client. + * If --pull is enabled, the first key generation is postponed until after the + * pull/push, so we can process pushed cipher directives. */ - if (!session->opt->server) + if (!session->opt->server && (!session->opt->pull || ks->key_id > 0)) { - if (!generate_key_expansion (&ks->key, + if (!generate_key_expansion (&ks->crypto_options.key_ctx_bi, &session->opt->key_type, ks->key_src, &session->session_id, @@ -2159,8 +2393,10 @@ key_method_2_read (struct buffer *buf, struct tls_multi *multi, struct tls_sessi msg (D_TLS_ERRORS, "TLS Error: client generate_key_expansion failed"); goto error; } - + CLEAR (*ks->key_src); + tls_limit_reneg_bytes (session->opt->key_type.cipher, + &session->opt->renegotiate_bytes); } gc_free (&gc); @@ -2217,11 +2453,11 @@ tls_process (struct tls_multi *multi, if (ks->state >= S_ACTIVE && ((session->opt->renegotiate_seconds && now >= ks->established + session->opt->renegotiate_seconds) - || (session->opt->renegotiate_bytes + || (session->opt->renegotiate_bytes > 0 && ks->n_bytes >= session->opt->renegotiate_bytes) || (session->opt->renegotiate_packets && ks->n_packets >= session->opt->renegotiate_packets) - || (packet_id_close_to_wrapping (&ks->packet_id.send)))) + || (packet_id_close_to_wrapping (&ks->crypto_options.packet_id.send)))) { msg (D_TLS_DEBUG_LOW, "TLS: soft reset sec=%d bytes=" counter_format "/%d pkts=" counter_format "/%d", @@ -2257,269 +2493,274 @@ tls_process (struct tls_multi *multi, * CHANGED with 2.0 -> now we may send tunnel configuration * info over the control channel. */ - if (true) + + /* Initial handshake */ + if (ks->state == S_INITIAL) { - /* Initial handshake */ - if (ks->state == S_INITIAL) + buf = reliable_get_buf_output_sequenced (ks->send_reliable); + if (buf) { - buf = reliable_get_buf_output_sequenced (ks->send_reliable); - if (buf) - { - ks->must_negotiate = now + session->opt->handshake_window; - ks->auth_deferred_expire = now + auth_deferred_expire_window (session->opt); + ks->must_negotiate = now + session->opt->handshake_window; + ks->auth_deferred_expire = now + auth_deferred_expire_window (session->opt); - /* null buffer */ - reliable_mark_active_outgoing (ks->send_reliable, buf, ks->initial_opcode); - INCR_GENERATED; + /* null buffer */ + reliable_mark_active_outgoing (ks->send_reliable, buf, ks->initial_opcode); + INCR_GENERATED; - ks->state = S_PRE_START; - state_change = true; - dmsg (D_TLS_DEBUG, "TLS: Initial Handshake, sid=%s", - session_id_print (&session->session_id, &gc)); + ks->state = S_PRE_START; + state_change = true; + dmsg (D_TLS_DEBUG, "TLS: Initial Handshake, sid=%s", + session_id_print (&session->session_id, &gc)); #ifdef ENABLE_MANAGEMENT - if (management && ks->initial_opcode != P_CONTROL_SOFT_RESET_V1) - { - management_set_state (management, - OPENVPN_STATE_WAIT, - NULL, - 0, - 0); - } -#endif + if (management && ks->initial_opcode != P_CONTROL_SOFT_RESET_V1) + { + management_set_state (management, + OPENVPN_STATE_WAIT, + NULL, + NULL, + NULL, + NULL, + NULL); } +#endif } + } - /* Are we timed out on receive? */ - if (now >= ks->must_negotiate) + /* Are we timed out on receive? */ + if (now >= ks->must_negotiate) + { + if (ks->state < S_ACTIVE) { - if (ks->state < S_ACTIVE) - { - msg (D_TLS_ERRORS, - "TLS Error: TLS key negotiation failed to occur within %d seconds (check your network connectivity)", - session->opt->handshake_window); - goto error; - } - else /* assume that ks->state == S_ACTIVE */ - { - dmsg (D_TLS_DEBUG_MED, "STATE S_NORMAL_OP"); - ks->state = S_NORMAL_OP; - ks->must_negotiate = 0; - } + msg (D_TLS_ERRORS, + "TLS Error: TLS key negotiation failed to occur within %d seconds (check your network connectivity)", + session->opt->handshake_window); + goto error; } + else /* assume that ks->state == S_ACTIVE */ + { + dmsg (D_TLS_DEBUG_MED, "STATE S_NORMAL_OP"); + ks->state = S_NORMAL_OP; + ks->must_negotiate = 0; + } + } - /* Wait for Initial Handshake ACK */ - if (ks->state == S_PRE_START && FULL_SYNC) + /* Wait for Initial Handshake ACK */ + if (ks->state == S_PRE_START && FULL_SYNC) + { + ks->state = S_START; + state_change = true; + + /* Reload the CRL before TLS negotiation */ + if (session->opt->crl_file && + !(session->opt->ssl_flags & SSLF_CRL_VERIFY_DIR)) { - ks->state = S_START; - state_change = true; - dmsg (D_TLS_DEBUG_MED, "STATE S_START"); + tls_ctx_reload_crl(&session->opt->ssl_ctx, + session->opt->crl_file, session->opt->crl_file_inline); } - /* Wait for ACK */ - if (((ks->state == S_GOT_KEY && !session->opt->server) || - (ks->state == S_SENT_KEY && session->opt->server))) + dmsg (D_TLS_DEBUG_MED, "STATE S_START"); + } + + /* Wait for ACK */ + if (((ks->state == S_GOT_KEY && !session->opt->server) || + (ks->state == S_SENT_KEY && session->opt->server))) + { + if (FULL_SYNC) { - if (FULL_SYNC) - { - ks->established = now; - dmsg (D_TLS_DEBUG_MED, "STATE S_ACTIVE"); - if (check_debug_level (D_HANDSHAKE)) - print_details (&ks->ks_ssl, "Control Channel:"); - state_change = true; - ks->state = S_ACTIVE; - INCR_SUCCESS; + ks->established = now; + dmsg (D_TLS_DEBUG_MED, "STATE S_ACTIVE"); + if (check_debug_level (D_HANDSHAKE)) + print_details (&ks->ks_ssl, "Control Channel:"); + state_change = true; + ks->state = S_ACTIVE; + INCR_SUCCESS; - /* Set outgoing address for data channel packets */ - link_socket_set_outgoing_addr (NULL, to_link_socket_info, &ks->remote_addr, session->common_name, session->opt->es); + /* Set outgoing address for data channel packets */ + link_socket_set_outgoing_addr (NULL, to_link_socket_info, &ks->remote_addr, session->common_name, session->opt->es); - /* Flush any payload packets that were buffered before our state transitioned to S_ACTIVE */ - flush_payload_buffer (ks); + /* Flush any payload packets that were buffered before our state transitioned to S_ACTIVE */ + flush_payload_buffer (ks); #ifdef MEASURE_TLS_HANDSHAKE_STATS - show_tls_performance_stats(); + show_tls_performance_stats(); #endif - } } + } - /* Reliable buffer to outgoing TCP/UDP (send up to CONTROL_SEND_ACK_MAX ACKs - for previously received packets) */ - if (!to_link->len && reliable_can_send (ks->send_reliable)) - { - int opcode; - struct buffer b; - - buf = reliable_send (ks->send_reliable, &opcode); - ASSERT (buf); - b = *buf; - INCR_SENT; - - write_control_auth (session, ks, &b, to_link_addr, opcode, - CONTROL_SEND_ACK_MAX, true); - *to_link = b; - active = true; - state_change = true; - dmsg (D_TLS_DEBUG, "Reliable -> TCP/UDP"); - break; - } + /* Reliable buffer to outgoing TCP/UDP (send up to CONTROL_SEND_ACK_MAX ACKs + for previously received packets) */ + if (!to_link->len && reliable_can_send (ks->send_reliable)) + { + int opcode; + struct buffer b; + + buf = reliable_send (ks->send_reliable, &opcode); + ASSERT (buf); + b = *buf; + INCR_SENT; + + write_control_auth (session, ks, &b, to_link_addr, opcode, + CONTROL_SEND_ACK_MAX, true); + *to_link = b; + active = true; + state_change = true; + dmsg (D_TLS_DEBUG, "Reliable -> TCP/UDP"); + break; + } #ifndef TLS_AGGREGATE_ACK - /* Send 1 or more ACKs (each received control packet gets one ACK) */ - if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) - { - buf = &ks->ack_write_buf; - ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); - write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, - RELIABLE_ACK_SIZE, false); - *to_link = *buf; - active = true; - state_change = true; - dmsg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); - break; - } + /* Send 1 or more ACKs (each received control packet gets one ACK) */ + if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) + { + buf = &ks->ack_write_buf; + ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); + write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, + RELIABLE_ACK_SIZE, false); + *to_link = *buf; + active = true; + state_change = true; + dmsg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); + break; + } #endif - /* Write incoming ciphertext to TLS object */ - buf = reliable_get_buf_sequenced (ks->rec_reliable); - if (buf) - { - int status = 0; - if (buf->len) - { - status = key_state_write_ciphertext (&ks->ks_ssl, buf); - if (status == -1) - { - msg (D_TLS_ERRORS, - "TLS Error: Incoming Ciphertext -> TLS object write error"); - goto error; - } - } - else - { - status = 1; - } - if (status == 1) - { - reliable_mark_deleted (ks->rec_reliable, buf, true); - state_change = true; - dmsg (D_TLS_DEBUG, "Incoming Ciphertext -> TLS"); - } - } - - /* Read incoming plaintext from TLS object */ - buf = &ks->plaintext_read_buf; - if (!buf->len) + /* Write incoming ciphertext to TLS object */ + buf = reliable_get_buf_sequenced (ks->rec_reliable); + if (buf) + { + int status = 0; + if (buf->len) { - int status; - - ASSERT (buf_init (buf, 0)); - status = key_state_read_plaintext (&ks->ks_ssl, buf, TLS_CHANNEL_BUF_SIZE); - update_time (); + status = key_state_write_ciphertext (&ks->ks_ssl, buf); if (status == -1) { - msg (D_TLS_ERRORS, "TLS Error: TLS object -> incoming plaintext read error"); + msg (D_TLS_ERRORS, + "TLS Error: Incoming Ciphertext -> TLS object write error"); goto error; } - if (status == 1) - { - state_change = true; - dmsg (D_TLS_DEBUG, "TLS -> Incoming Plaintext"); - } -#if 0 /* show null plaintext reads */ - if (!status) - msg (M_INFO, "TLS plaintext read -> NULL return"); -#endif } - - /* Send Key */ - buf = &ks->plaintext_write_buf; - if (!buf->len && ((ks->state == S_START && !session->opt->server) || - (ks->state == S_GOT_KEY && session->opt->server))) + else { - if (session->opt->key_method == 1) - { - if (!key_method_1_write (buf, session)) - goto error; - } - else if (session->opt->key_method == 2) - { - if (!key_method_2_write (buf, session)) - goto error; - } - else - { - ASSERT (0); - } + status = 1; + } + if (status == 1) + { + reliable_mark_deleted (ks->rec_reliable, buf, true); + state_change = true; + dmsg (D_TLS_DEBUG, "Incoming Ciphertext -> TLS"); + } + } + + /* Read incoming plaintext from TLS object */ + buf = &ks->plaintext_read_buf; + if (!buf->len) + { + int status; + ASSERT (buf_init (buf, 0)); + status = key_state_read_plaintext (&ks->ks_ssl, buf, TLS_CHANNEL_BUF_SIZE); + update_time (); + if (status == -1) + { + msg (D_TLS_ERRORS, "TLS Error: TLS object -> incoming plaintext read error"); + goto error; + } + if (status == 1) + { state_change = true; - dmsg (D_TLS_DEBUG_MED, "STATE S_SENT_KEY"); - ks->state = S_SENT_KEY; + dmsg (D_TLS_DEBUG, "TLS -> Incoming Plaintext"); } + } - /* Receive Key */ - buf = &ks->plaintext_read_buf; - if (buf->len - && ((ks->state == S_SENT_KEY && !session->opt->server) - || (ks->state == S_START && session->opt->server))) + /* Send Key */ + buf = &ks->plaintext_write_buf; + if (!buf->len && ((ks->state == S_START && !session->opt->server) || + (ks->state == S_GOT_KEY && session->opt->server))) + { + if (session->opt->key_method == 1) { - if (session->opt->key_method == 1) - { - if (!key_method_1_read (buf, session)) - goto error; - } - else if (session->opt->key_method == 2) - { - if (!key_method_2_read (buf, multi, session)) - goto error; - } - else - { - ASSERT (0); - } + if (!key_method_1_write (buf, session)) + goto error; + } + else if (session->opt->key_method == 2) + { + if (!key_method_2_write (buf, session)) + goto error; + } + else + { + ASSERT (0); + } + + state_change = true; + dmsg (D_TLS_DEBUG_MED, "STATE S_SENT_KEY"); + ks->state = S_SENT_KEY; + } + /* Receive Key */ + buf = &ks->plaintext_read_buf; + if (buf->len + && ((ks->state == S_SENT_KEY && !session->opt->server) + || (ks->state == S_START && session->opt->server))) + { + if (session->opt->key_method == 1) + { + if (!key_method_1_read (buf, session)) + goto error; + } + else if (session->opt->key_method == 2) + { + if (!key_method_2_read (buf, multi, session)) + goto error; + } + else + { + ASSERT (0); + } + + state_change = true; + dmsg (D_TLS_DEBUG_MED, "STATE S_GOT_KEY"); + ks->state = S_GOT_KEY; + } + + /* Write outgoing plaintext to TLS object */ + buf = &ks->plaintext_write_buf; + if (buf->len) + { + int status = key_state_write_plaintext (&ks->ks_ssl, buf); + if (status == -1) + { + msg (D_TLS_ERRORS, + "TLS ERROR: Outgoing Plaintext -> TLS object write error"); + goto error; + } + if (status == 1) + { state_change = true; - dmsg (D_TLS_DEBUG_MED, "STATE S_GOT_KEY"); - ks->state = S_GOT_KEY; + dmsg (D_TLS_DEBUG, "Outgoing Plaintext -> TLS"); } + } - /* Write outgoing plaintext to TLS object */ - buf = &ks->plaintext_write_buf; - if (buf->len) + /* Outgoing Ciphertext to reliable buffer */ + if (ks->state >= S_START) + { + buf = reliable_get_buf_output_sequenced (ks->send_reliable); + if (buf) { - int status = key_state_write_plaintext (&ks->ks_ssl, buf); + int status = key_state_read_ciphertext (&ks->ks_ssl, buf, PAYLOAD_SIZE_DYNAMIC (&multi->opt.frame)); if (status == -1) { msg (D_TLS_ERRORS, - "TLS ERROR: Outgoing Plaintext -> TLS object write error"); + "TLS Error: Ciphertext -> reliable TCP/UDP transport read error"); goto error; } if (status == 1) { + reliable_mark_active_outgoing (ks->send_reliable, buf, P_CONTROL_V1); + INCR_GENERATED; state_change = true; - dmsg (D_TLS_DEBUG, "Outgoing Plaintext -> TLS"); - } - } - - /* Outgoing Ciphertext to reliable buffer */ - if (ks->state >= S_START) - { - buf = reliable_get_buf_output_sequenced (ks->send_reliable); - if (buf) - { - int status = key_state_read_ciphertext (&ks->ks_ssl, buf, PAYLOAD_SIZE_DYNAMIC (&multi->opt.frame)); - if (status == -1) - { - msg (D_TLS_ERRORS, - "TLS Error: Ciphertext -> reliable TCP/UDP transport read error"); - goto error; - } - if (status == 1) - { - reliable_mark_active_outgoing (ks->send_reliable, buf, P_CONTROL_V1); - INCR_GENERATED; - state_change = true; - dmsg (D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable"); - } + dmsg (D_TLS_DEBUG, "Outgoing Ciphertext -> Reliable"); } } } @@ -2532,11 +2773,11 @@ tls_process (struct tls_multi *multi, /* Send 1 or more ACKs (each received control packet gets one ACK) */ if (!to_link->len && !reliable_ack_empty (ks->rec_ack)) { - buf = &ks->ack_write_buf; - ASSERT (buf_init (buf, FRAME_HEADROOM (&multi->opt.frame))); - write_control_auth (session, ks, buf, to_link_addr, P_ACK_V1, + struct buffer buf = ks->ack_write_buf; + ASSERT (buf_init (&buf, FRAME_HEADROOM (&multi->opt.frame))); + write_control_auth (session, ks, &buf, to_link_addr, P_ACK_V1, RELIABLE_ACK_SIZE, false); - *to_link = *buf; + *to_link = buf; active = true; state_change = true; dmsg (D_TLS_DEBUG, "Dedicated ACK -> TCP/UDP"); @@ -2775,7 +3016,9 @@ bool tls_pre_decrypt (struct tls_multi *multi, const struct link_socket_actual *from, struct buffer *buf, - struct crypto_options *opt) + struct crypto_options **opt, + bool floated, + const uint8_t **ad_start) { struct gc_arena gc = gc_new (); bool ret = false; @@ -2819,18 +3062,29 @@ tls_pre_decrypt (struct tls_multi *multi, #ifdef ENABLE_DEF_AUTH && !ks->auth_deferred #endif - && link_socket_actual_match (from, &ks->remote_addr)) + && (floated || link_socket_actual_match (from, &ks->remote_addr))) { - /* return appropriate data channel decrypt key in opt */ - opt->key_ctx_bi = &ks->key; - opt->packet_id = multi->opt.replay ? &ks->packet_id : NULL; - opt->pid_persist = NULL; - opt->flags &= multi->opt.crypto_flags_and; - opt->flags |= multi->opt.crypto_flags_or; + if (!ks->crypto_options.key_ctx_bi.initialized) + { + msg (D_TLS_DEBUG_LOW, + "Key %s [%d] not initialized (yet), dropping packet.", + print_link_socket_actual (from, &gc), key_id); + goto error_lite; + } - ASSERT (buf_advance (buf, 1)); + /* return appropriate data channel decrypt key in opt */ + *opt = &ks->crypto_options; if (op == P_DATA_V2) { + *ad_start = BPTR(buf); + } + ASSERT (buf_advance (buf, 1)); + if (op == P_DATA_V1) + { + *ad_start = BPTR(buf); + } + else if (op == P_DATA_V2) + { if (buf->len < 4) { msg (D_TLS_ERRORS, "Protocol error: received P_DATA_V2 from %s but length is < 4", @@ -2848,23 +3102,6 @@ tls_pre_decrypt (struct tls_multi *multi, gc_free (&gc); return ret; } -#if 0 /* keys out of sync? */ - else - { - dmsg (D_TLS_ERRORS, "TLS_PRE_DECRYPT: [%d] dken=%d rkid=%d lkid=%d auth=%d def=%d match=%d", - i, - DECRYPT_KEY_ENABLED (multi, ks), - key_id, - ks->key_id, - ks->authenticated, -#ifdef ENABLE_DEF_AUTH - ks->auth_deferred, -#else - -1, -#endif - link_socket_actual_match (from, &ks->remote_addr)); - } -#endif } msg (D_TLS_ERRORS, @@ -2991,8 +3228,10 @@ tls_pre_decrypt (struct tls_multi *multi, management_set_state (management, OPENVPN_STATE_AUTH, NULL, - 0, - 0); + NULL, + NULL, + NULL, + NULL); } #endif @@ -3036,7 +3275,7 @@ tls_pre_decrypt (struct tls_multi *multi, goto error; } - if (!read_control_auth (buf, &session->tls_auth, from)) + if (!read_control_auth (buf, &session->tls_wrap, from)) goto error; /* @@ -3087,7 +3326,7 @@ tls_pre_decrypt (struct tls_multi *multi, if (op == P_CONTROL_SOFT_RESET_V1 && DECRYPT_KEY_ENABLED (multi, ks)) { - if (!read_control_auth (buf, &session->tls_auth, from)) + if (!read_control_auth (buf, &session->tls_wrap, from)) goto error; key_state_soft_reset (session); @@ -3104,7 +3343,7 @@ tls_pre_decrypt (struct tls_multi *multi, if (op == P_CONTROL_SOFT_RESET_V1) do_burst = true; - if (!read_control_auth (buf, &session->tls_auth, from)) + if (!read_control_auth (buf, &session->tls_wrap, from)) goto error; dmsg (D_TLS_DEBUG, @@ -3215,10 +3454,7 @@ tls_pre_decrypt (struct tls_multi *multi, done: buf->len = 0; - opt->key_ctx_bi = NULL; - opt->packet_id = NULL; - opt->pid_persist = NULL; - opt->flags &= multi->opt.crypto_flags_and; + *opt = NULL; gc_free (&gc); return ret; @@ -3297,18 +3533,11 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, { struct buffer newbuf = clone_buf (buf); - struct crypto_options co = tas->tls_auth_options; + struct tls_wrap_ctx tls_wrap_tmp = tas->tls_wrap; bool status; - /* - * We are in read-only mode at this point with respect to TLS - * control channel state. After we build a new client instance - * object, we will process this session-initiating packet for real. - */ - co.flags |= CO_IGNORE_PACKET_ID; - /* HMAC test, if --tls-auth was specified */ - status = read_control_auth (&newbuf, &co, from); + status = read_control_auth (&newbuf, &tls_wrap_tmp, from); free_buf (&newbuf); if (!status) goto error; @@ -3344,7 +3573,7 @@ tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, /* Choose the key with which to encrypt a data packet */ void tls_pre_encrypt (struct tls_multi *multi, - struct buffer *buf, struct crypto_options *opt) + struct buffer *buf, struct crypto_options **opt) { multi->save_ks = NULL; if (buf->len > 0) @@ -3356,6 +3585,7 @@ tls_pre_encrypt (struct tls_multi *multi, struct key_state *ks = multi->key_scan[i]; if (ks->state >= S_ACTIVE && ks->authenticated + && ks->crypto_options.key_ctx_bi.initialized #ifdef ENABLE_DEF_AUTH && !ks->auth_deferred #endif @@ -3373,11 +3603,7 @@ tls_pre_encrypt (struct tls_multi *multi, if (ks_select) { - opt->key_ctx_bi = &ks_select->key; - opt->packet_id = multi->opt.replay ? &ks_select->packet_id : NULL; - opt->pid_persist = NULL; - opt->flags &= multi->opt.crypto_flags_and; - opt->flags |= multi->opt.crypto_flags_or; + *opt = &ks_select->crypto_options; multi->save_ks = ks_select; dmsg (D_TLS_KEYSELECT, "TLS: tls_pre_encrypt: key_id=%d", ks_select->key_id); return; @@ -3392,36 +3618,48 @@ tls_pre_encrypt (struct tls_multi *multi, } buf->len = 0; - opt->key_ctx_bi = NULL; - opt->packet_id = NULL; - opt->pid_persist = NULL; - opt->flags &= multi->opt.crypto_flags_and; + *opt = NULL; } -/* Prepend the appropriate opcode to encrypted buffer prior to TCP/UDP send */ void -tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) +tls_prepend_opcode_v1 (const struct tls_multi *multi, struct buffer *buf) { - struct key_state *ks; - uint8_t *op; + struct key_state *ks = multi->save_ks; + uint8_t op; + + msg (D_TLS_DEBUG, __func__); + + ASSERT (ks); + + op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id; + ASSERT (buf_write_prepend (buf, &op, 1)); +} + +void +tls_prepend_opcode_v2 (const struct tls_multi *multi, struct buffer *buf) +{ + struct key_state *ks = multi->save_ks; uint32_t peer; - ks = multi->save_ks; + msg (D_TLS_DEBUG, __func__); + + ASSERT (ks); + + peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 + | (multi->peer_id & 0xFFFFFF)); + ASSERT (buf_write_prepend (buf, &peer, 4)); +} + +void +tls_post_encrypt (struct tls_multi *multi, struct buffer *buf) +{ + struct key_state *ks = multi->save_ks; multi->save_ks = NULL; + if (buf->len > 0) { ASSERT (ks); - if (!multi->opt.server && multi->use_peer_id) - { - peer = htonl(((P_DATA_V2 << P_OPCODE_SHIFT) | ks->key_id) << 24 | (multi->peer_id & 0xFFFFFF)); - ASSERT (buf_write_prepend (buf, &peer, 4)); - } - else - { - ASSERT (op = buf_prepend (buf, 1)); - *op = (P_DATA_V1 << P_OPCODE_SHIFT) | ks->key_id; - } ++ks->n_packets; ks->n_bytes += buf->len; } @@ -3494,6 +3732,70 @@ tls_rec_payload (struct tls_multi *multi, return ret; } +void +tls_update_remote_addr (struct tls_multi *multi, const struct link_socket_actual *addr) +{ + struct gc_arena gc = gc_new (); + int i, j; + + for (i = 0; i < TM_SIZE; ++i) + { + struct tls_session *session = &multi->session[i]; + + for (j = 0; j < KS_SIZE; ++j) + { + struct key_state *ks = &session->key[j]; + + if (!link_socket_actual_defined(&ks->remote_addr) || + link_socket_actual_match (addr, &ks->remote_addr)) + continue; + + dmsg (D_TLS_KEYSELECT, "TLS: tls_update_remote_addr from IP=%s to IP=%s", + print_link_socket_actual (&ks->remote_addr, &gc), + print_link_socket_actual (addr, &gc)); + + ks->remote_addr = *addr; + } + } + gc_free (&gc); +} + +int +tls_peer_info_ncp_ver(const char *peer_info) +{ + const char *ncpstr = peer_info ? strstr (peer_info, "IV_NCP=") : NULL; + if (ncpstr) + { + int ncp = 0; + int r = sscanf(ncpstr, "IV_NCP=%d", &ncp); + if (r == 1) + return ncp; + } + return 0; +} + +bool +tls_check_ncp_cipher_list(const char *list) { + bool unsupported_cipher_found = false; + + ASSERT (list); + + char * const tmp_ciphers = string_alloc (list, NULL); + const char *token = strtok (tmp_ciphers, ":"); + while (token) + { + if (!cipher_kt_get (translate_cipher_name_from_openvpn (token))) + { + msg (M_WARN, "Unsupported cipher in --ncp-ciphers: %s", token); + unsupported_cipher_found = true; + } + token = strtok (NULL, ":"); + } + free (tmp_ciphers); + + return 0 < strlen(list) && !unsupported_cipher_found; +} + /* * Dump a human-readable rendition of an openvpn packet * into a garbage collectable string which is returned. @@ -3594,4 +3896,4 @@ done: #else static void dummy(void) {} -#endif /* ENABLE_CRYPTO && ENABLE_SSL*/ +#endif /* ENABLE_CRYPTO */ |