Decouples struct key_state and struct crypto_options. No longer updating self-referential pointers!
Signed-off-by: Steffan Karger <stef...@karger.me> --- src/openvpn/crypto.c | 45 ++++++++++++++++++++++++--------------------- src/openvpn/crypto.h | 10 ++++------ src/openvpn/init.c | 11 +++++------ src/openvpn/openvpn.h | 2 -- src/openvpn/packet_id.h | 6 ++++++ src/openvpn/ssl.c | 38 +++++++++++++------------------------- src/openvpn/ssl_common.h | 2 -- 7 files changed, 52 insertions(+), 62 deletions(-) diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c index 9679fd0..db52182 100644 --- a/src/openvpn/crypto.c +++ b/src/openvpn/crypto.c @@ -85,8 +85,7 @@ memcmp_constant_time (const void *a, const void *b, size_t size) { void openvpn_encrypt (struct buffer *buf, struct buffer work, - const struct crypto_options *opt, - const struct frame* frame) + struct crypto_options *opt, const struct frame* frame) { struct gc_arena gc; gc_init (&gc); @@ -111,11 +110,11 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, if (opt->flags & CO_USE_IV) prng_bytes (iv_buf, iv_size); - /* Put packet ID in plaintext buffer or IV, depending on cipher mode */ - if (opt->packet_id) + /* Put packet ID in plaintext buffer */ + if (packet_id_initialized(&opt->packet_id)) { struct packet_id_net pin; - packet_id_alloc_outgoing (&opt->packet_id->send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); + packet_id_alloc_outgoing (&opt->packet_id.send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true)); } } @@ -124,10 +123,11 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, struct packet_id_net pin; struct buffer b; - ASSERT (opt->flags & CO_USE_IV); /* IV and packet-ID required */ - ASSERT (opt->packet_id); /* for this mode. */ + /* IV and packet-ID required for this mode. */ + ASSERT (opt->flags & CO_USE_IV); + ASSERT (packet_id_initialized(&opt->packet_id)); - packet_id_alloc_outgoing (&opt->packet_id->send, &pin, true); + packet_id_alloc_outgoing (&opt->packet_id.send, &pin, true); memset (iv_buf, 0, iv_size); buf_set_write (&b, iv_buf, iv_size); ASSERT (packet_id_write (&pin, &b, true, false)); @@ -189,10 +189,10 @@ openvpn_encrypt (struct buffer *buf, struct buffer work, } else /* No Encryption */ { - if (opt->packet_id) + if (packet_id_initialized(&opt->packet_id)) { struct packet_id_net pin; - packet_id_alloc_outgoing (&opt->packet_id->send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); + packet_id_alloc_outgoing (&opt->packet_id.send, &pin, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM)); ASSERT (packet_id_write (&pin, buf, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM), true)); } work = *buf; @@ -233,8 +233,7 @@ err: */ bool openvpn_decrypt (struct buffer *buf, struct buffer work, - const struct crypto_options *opt, - const struct frame* frame) + struct crypto_options *opt, const struct frame* frame) { static const char error_prefix[] = "Authenticate/Decrypt packet error"; struct gc_arena gc; @@ -246,6 +245,9 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, struct packet_id_net pin; bool have_pin = false; + dmsg (D_PACKET_CONTENT, "DECRYPT FROM: %s", + format_hex (BPTR (buf), BLEN (buf), 80, &gc)); + /* Verify the HMAC */ if (ctx->hmac) { @@ -325,7 +327,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, { if (cipher_kt_mode_cbc(cipher_kt)) { - if (opt->packet_id) + if (packet_id_initialized(&opt->packet_id)) { if (!packet_id_read (&pin, &work, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM))) CRYPT_ERROR ("error reading CBC packet-id"); @@ -336,8 +338,9 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, { struct buffer b; - ASSERT (opt->flags & CO_USE_IV); /* IV and packet-ID required */ - ASSERT (opt->packet_id); /* for this mode. */ + /* IV and packet-ID required for this mode. */ + ASSERT (opt->flags & CO_USE_IV); + ASSERT (packet_id_initialized(&opt->packet_id)); buf_set_read (&b, iv_buf, iv_size); if (!packet_id_read (&pin, &b, true)) @@ -353,7 +356,7 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, else { work = *buf; - if (opt->packet_id) + if (packet_id_initialized(&opt->packet_id)) { if (!packet_id_read (&pin, &work, BOOL_CAST (opt->flags & CO_PACKET_ID_LONG_FORM))) CRYPT_ERROR ("error reading packet-id"); @@ -363,12 +366,12 @@ openvpn_decrypt (struct buffer *buf, struct buffer work, if (have_pin) { - packet_id_reap_test (&opt->packet_id->rec); - if (packet_id_test (&opt->packet_id->rec, &pin)) + packet_id_reap_test (&opt->packet_id.rec); + if (packet_id_test (&opt->packet_id.rec, &pin)) { - packet_id_add (&opt->packet_id->rec, &pin); + packet_id_add (&opt->packet_id.rec, &pin); if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM)) - packet_id_persist_save_obj (opt->pid_persist, opt->packet_id); + packet_id_persist_save_obj (opt->pid_persist, &opt->packet_id); } else { @@ -688,7 +691,7 @@ key2_print (const struct key2* k, } void -test_crypto (const struct crypto_options *co, struct frame* frame) +test_crypto (struct crypto_options *co, struct frame* frame) { int i, j; struct gc_arena gc = gc_new (); diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h index 1f84284..aac50c4 100644 --- a/src/openvpn/crypto.h +++ b/src/openvpn/crypto.h @@ -211,7 +211,7 @@ struct crypto_options /**< OpenSSL cipher and HMAC contexts for * both sending and receiving * directions. */ - struct packet_id *packet_id; /**< Current packet ID state for both + struct packet_id packet_id; /**< Current packet ID state for both * sending and receiving directions. */ struct packet_id_persist *pid_persist; /**< Persistent packet ID state for @@ -311,8 +311,7 @@ void free_key_ctx_bi (struct key_ctx_bi *ctx); * error occurred. */ void openvpn_encrypt (struct buffer *buf, struct buffer work, - const struct crypto_options *opt, - const struct frame* frame); + struct crypto_options *opt, const struct frame* frame); /** @@ -347,8 +346,7 @@ void openvpn_encrypt (struct buffer *buf, struct buffer work, * an error occurred. */ bool openvpn_decrypt (struct buffer *buf, struct buffer work, - const struct crypto_options *opt, - const struct frame* frame); + struct crypto_options *opt, const struct frame* frame); /** @} name Functions for performing security operations on data channel packets */ @@ -397,7 +395,7 @@ void prng_bytes (uint8_t *output, int len); void prng_uninit (); -void test_crypto (const struct crypto_options *co, struct frame* f); +void test_crypto (struct crypto_options *co, struct frame* f); /* key direction functions */ diff --git a/src/openvpn/init.c b/src/openvpn/init.c index dcc3ccb..cb73a3d 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2076,16 +2076,15 @@ do_init_crypto_static (struct context *c, const unsigned int flags) /* Initialize packet ID tracking */ if (options->replay) { - packet_id_init (&c->c2.packet_id, + packet_id_init (&c->c2.crypto_options.packet_id, link_socket_proto_connection_oriented (options->ce.proto), options->replay_window, options->replay_time, "STATIC", 0); - c->c2.crypto_options.packet_id = &c->c2.packet_id; c->c2.crypto_options.pid_persist = &c->c1.pid_persist; c->c2.crypto_options.flags |= CO_PACKET_ID_LONG_FORM; packet_id_persist_load_obj (&c->c1.pid_persist, - c->c2.crypto_options.packet_id); + &c->c2.crypto_options.packet_id); } if (!key_ctx_bi_defined (&c->c1.ks.static_key)) @@ -3007,7 +3006,7 @@ static void do_close_packet_id (struct context *c) { #ifdef ENABLE_CRYPTO - packet_id_free (&c->c2.packet_id); + packet_id_free (&c->c2.crypto_options.packet_id); packet_id_persist_save (&c->c1.pid_persist); if (!(c->sig->signal_received == SIGUSR1)) packet_id_persist_close (&c->c1.pid_persist); @@ -3923,13 +3922,13 @@ test_crypto_thread (void *arg) test_crypto (&c->c2.crypto_options, &c->c2.frame); key_schedule_free (&c->c1.ks, true); - packet_id_free (&c->c2.packet_id); + packet_id_free (&c->c2.crypto_options.packet_id); context_gc_free (c); return NULL; } -#endif +#endif /* ENABLE_CRYPTO */ bool do_test_crypto (const struct options *o) diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h index 71adf48..3281fd7 100644 --- a/src/openvpn/openvpn.h +++ b/src/openvpn/openvpn.h @@ -361,8 +361,6 @@ struct context_2 * Channel Crypto module\endlink to * process data channel packet. */ - /* used to keep track of data channel packet sequence numbers */ - struct packet_id packet_id; struct event_timeout packet_id_persist_interval; #endif /* ENABLE_CRYPTO */ diff --git a/src/openvpn/packet_id.h b/src/openvpn/packet_id.h index 3ddaab6..5eb501d 100644 --- a/src/openvpn/packet_id.h +++ b/src/openvpn/packet_id.h @@ -258,6 +258,12 @@ bool packet_id_write (const struct packet_id_net *pin, struct buffer *buf, bool * Inline functions. */ +/** Is this struct packet_id initialized? */ +static inline bool packet_id_initialized (const struct packet_id *pid) +{ + return pid->rec.initialized; +} + /* are we in enabled state? */ static inline bool packet_id_persist_enabled (const struct packet_id_persist *p) diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index e3a745d..7f99ee9 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -780,13 +780,13 @@ 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->tcp_mode, + session->opt->replay_window, session->opt->replay_time, "SSL", + ks->key_id); + } - ks->crypto_options.packet_id = session->opt->replay ? &ks->packet_id : NULL; ks->crypto_options.pid_persist = NULL; ks->crypto_options.flags = session->opt->crypto_flags; ks->crypto_options.flags &= session->opt->crypto_flags_and; @@ -842,7 +842,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); @@ -857,13 +857,6 @@ key_state_free (struct key_state *ks, bool clear) /** @} addtogroup control_processor */ -/* - * Must be called if we move a tls_session in memory. - */ -static inline void tls_session_set_self_referential_pointers (struct tls_session* session) { - session->tls_auth.packet_id = &session->tls_auth_pid; -} - /** * Returns whether or not the server should check for username/password * @@ -936,18 +929,15 @@ 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); - /* initialize packet ID replay window for --tls-auth */ - packet_id_init (session->tls_auth.packet_id, + packet_id_init (&session->tls_auth.packet_id, session->opt->tcp_mode, session->opt->replay_window, session->opt->replay_time, "TLS_AUTH", 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_auth.pid_persist, &session->tls_auth.packet_id); key_state_init (session, &session->key[KS_PRIMARY]); @@ -974,8 +964,8 @@ 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_auth.packet_id)) + packet_id_free (&session->tls_auth.packet_id); for (i = 0; i < KS_SIZE; ++i) key_state_free (&session->key[i], false); @@ -1006,7 +996,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]); @@ -1274,7 +1263,7 @@ write_control_auth (struct tls_session *session, */ static bool read_control_auth (struct buffer *buf, - const struct crypto_options *co, + struct crypto_options *co, const struct link_socket_actual *from) { struct gc_arena gc = gc_new (); @@ -1702,7 +1691,6 @@ key_state_soft_reset (struct tls_session *session) ks->must_die = now + session->opt->transition_window; /* remaining lifetime of old key */ key_state_free (ks_lame, false); *ks_lame = *ks; - ks_lame->crypto_options.packet_id = &ks_lame->packet_id; key_state_init (session, ks); ks->session_id_remote = ks_lame->session_id_remote; @@ -2257,7 +2245,7 @@ tls_process (struct tls_multi *multi, && 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", diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index b40aec2..eaf4a91 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -160,7 +160,6 @@ struct key_state int initial_opcode; /* our initial P_ opcode */ struct session_id session_id_remote; /* peer's random session ID */ struct link_socket_actual remote_addr; /* peer's IP addr */ - struct packet_id packet_id; /* for data channel, to prevent replay attacks */ struct crypto_options crypto_options;/* data channel crypto options */ @@ -366,7 +365,6 @@ struct tls_session /* authenticate control packets */ struct crypto_options tls_auth; - struct packet_id tls_auth_pid; int initial_opcode; /* our initial P_ opcode */ struct session_id session_id; /* our random session ID */ -- 2.5.0