[Openvpn-devel,v2,5/9] Remove key-method 1

Message ID 20200717134739.21168-5-arne@rfc2549.org
State Superseded
Headers show
Series [Openvpn-devel,1/9] Indicate that a client is in pull mode in IV_PROTO | expand

Commit Message

Arne Schwabe July 17, 2020, 3:47 a.m. UTC
Key-method 1 is only needed to talk to pre OpenVPN 2.0 clients.

Patch V2: Fix style. Make V1 op codes illegal, remove all code handling
          v1 op codes and give a good warning message if we encounter
          them in the legal op codes pre-check.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
---
 doc/doxygen/doc_control_processor.h |   6 +-
 doc/doxygen/doc_key_generation.h    |   6 +-
 doc/doxygen/doc_protocol_overview.h |   2 +-
 src/openvpn/forward.c               |   2 +-
 src/openvpn/helper.c                |   5 -
 src/openvpn/init.c                  |   1 -
 src/openvpn/options.c               |  35 +----
 src/openvpn/options.h               |   4 -
 src/openvpn/ssl.c                   | 230 ++++------------------------
 src/openvpn/ssl.h                   |  19 +--
 src/openvpn/ssl_common.h            |   1 -
 11 files changed, 42 insertions(+), 269 deletions(-)

Comments

David Sommerseth July 20, 2020, 3:16 a.m. UTC | #1
On 17/07/2020 15:47, Arne Schwabe wrote:
> Key-method 1 is only needed to talk to pre OpenVPN 2.0 clients.
> 
> Patch V2: Fix style. Make V1 op codes illegal, remove all code handling
>           v1 op codes and give a good warning message if we encounter
>           them in the legal op codes pre-check.
> 
> Signed-off-by: Arne Schwabe <arne@rfc2549.org>
> ---
>  doc/doxygen/doc_control_processor.h |   6 +-
>  doc/doxygen/doc_key_generation.h    |   6 +-
>  doc/doxygen/doc_protocol_overview.h |   2 +-
>  src/openvpn/forward.c               |   2 +-
>  src/openvpn/helper.c                |   5 -
>  src/openvpn/init.c                  |   1 -
>  src/openvpn/options.c               |  35 +----
>  src/openvpn/options.h               |   4 -
>  src/openvpn/ssl.c                   | 230 ++++------------------------
>  src/openvpn/ssl.h                   |  19 +--
>  src/openvpn/ssl_common.h            |   1 -
>  11 files changed, 42 insertions(+), 269 deletions(-)

[...snip...]

> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
> index 00b97352..4144217d 100644
> --- a/src/openvpn/ssl.c
> +++ b/src/openvpn/ssl.c

[...snip...]

> @@ -2225,52 +2205,6 @@ read_string_alloc(struct buffer *buf)
>      return str;
>  }
>  
> -/*
> - * Handle the reading and writing of key data to and from
> - * the TLS control channel (cleartext).
> - */

Is it needed to remove this comment?  Or move it after the push_peer_info()
function?

> -static bool
> -key_method_1_write(struct buffer *buf, struct tls_session *session)
> -{
[...snip...]
> -}
> -
>  static bool
>  push_peer_info(struct buffer *buf, struct tls_session *session)
>  {
> @@ -2312,7 +2246,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
>           * push request, also signal that the client wants
>           * to get push-reply messages without without requiring a round
>           * trip for a push request message*/
> -        if(session->opt->pull)
> +        if (session->opt->pull)
>          {
>              iv_proto |= IV_PROTO_REQUEST_PUSH;
>          }
> @@ -2394,7 +2328,6 @@ key_method_2_write(struct buffer *buf, struct tls_session *session)

[...snip...]

> @@ -3470,14 +3316,12 @@ tls_pre_decrypt(struct tls_multi *multi,
>              }
>  
>              /* hard reset ? */
> -            if (is_hard_reset(op, 0))
> +            if (is_hard_reset_method2(op))
>              {
>                  /* verify client -> server or server -> client connection */
> -                if (((op == P_CONTROL_HARD_RESET_CLIENT_V1
> -                      || op == P_CONTROL_HARD_RESET_CLIENT_V2
> +                if (((op == P_CONTROL_HARD_RESET_CLIENT_V2
>                        || op == P_CONTROL_HARD_RESET_CLIENT_V3) && !multi->opt.server)
> -                    || ((op == P_CONTROL_HARD_RESET_SERVER_V1
> -                         || op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
> +                    || ((op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
>                  {
>                      msg(D_TLS_ERRORS,
>                          "TLS Error: client->client or server->server connection attempted from %s",
> @@ -3542,19 +3386,11 @@ tls_pre_decrypt(struct tls_multi *multi,
>               * Initial packet received.
>               */
>  
> -            if (i == TM_SIZE && is_hard_reset(op, 0))
> +            if (i == TM_SIZE && is_hard_reset_method2(op))
>              {
>                  struct tls_session *session = &multi->session[TM_ACTIVE];
>                  struct key_state *ks = &session->key[KS_PRIMARY];
>  
> -                if (!is_hard_reset(op, multi->opt.key_method))
> -                {
> -                    msg(D_TLS_ERRORS, "TLS ERROR: initial packet local/remote key_method mismatch, local key_method=%d, op=%s",
> -                        multi->opt.key_method,
> -                        packet_opcode_name(op));
> -                    goto error;
> -                }
> -
>                  /*
>                   * If we have no session currently in progress, the initial packet will
>                   * open a new session in TM_ACTIVE rather than TM_UNTRUSTED.
> @@ -3594,7 +3430,7 @@ tls_pre_decrypt(struct tls_multi *multi,
>                  }
>              }
>  
> -            if (i == TM_SIZE && is_hard_reset(op, 0))
> +            if (i == TM_SIZE && is_hard_reset_method2(op))

Do we need this if() block?  Considering it is exactly the same if() statement
as the previous if() block.  I would suggest merging them, but you might hit a
challenge with reuse of struct tls_session *session, where one is referring to
TM_ACTIVE vs TM_UNTRUSTED.

>              {
>                  /*
>                   * No match with existing sessions,
> @@ -3614,14 +3450,6 @@ tls_pre_decrypt(struct tls_multi *multi,
>                      goto error;
>                  }
>  
> -                if (!is_hard_reset(op, multi->opt.key_method))
> -                {
> -                    msg(D_TLS_ERRORS, "TLS ERROR: new session local/remote key_method mismatch, local key_method=%d, op=%s",
> -                        multi->opt.key_method,
> -                        packet_opcode_name(op));
> -                    goto error;
> -                }
> -
>                  if (!read_control_auth(buf, &session->tls_wrap, from,
>                                         session->opt))
>                  {

I had already started my own approach of removing --key-method when I was made
aware of this patch.  Considering the size of it, my own barely tested changes
is about 90% similar to this patch.  But this patch has some improvements I
didn't consider in my work.

I've done a quick 'make check' as well, and it works fine.  There are just a
couple of minor things to consider, otherwise I will happily ACK this patch.
Arne Schwabe July 20, 2020, 3:22 a.m. UTC | #2
Am 20.07.20 um 15:16 schrieb David Sommerseth:
> On 17/07/2020 15:47, Arne Schwabe wrote:
>> Key-method 1 is only needed to talk to pre OpenVPN 2.0 clients.
>>
>> Patch V2: Fix style. Make V1 op codes illegal, remove all code handling
>>           v1 op codes and give a good warning message if we encounter
>>           them in the legal op codes pre-check.
>>
>> Signed-off-by: Arne Schwabe <arne@rfc2549.org>
>> ---
>>  doc/doxygen/doc_control_processor.h |   6 +-
>>  doc/doxygen/doc_key_generation.h    |   6 +-
>>  doc/doxygen/doc_protocol_overview.h |   2 +-
>>  src/openvpn/forward.c               |   2 +-
>>  src/openvpn/helper.c                |   5 -
>>  src/openvpn/init.c                  |   1 -
>>  src/openvpn/options.c               |  35 +----
>>  src/openvpn/options.h               |   4 -
>>  src/openvpn/ssl.c                   | 230 ++++------------------------
>>  src/openvpn/ssl.h                   |  19 +--
>>  src/openvpn/ssl_common.h            |   1 -
>>  11 files changed, 42 insertions(+), 269 deletions(-)
> 
> [...snip...]
> 
>> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
>> index 00b97352..4144217d 100644
>> --- a/src/openvpn/ssl.c
>> +++ b/src/openvpn/ssl.c
> 
> [...snip...]
> 
>> @@ -2225,52 +2205,6 @@ read_string_alloc(struct buffer *buf)
>>      return str;
>>  }
>>  
>> -/*
>> - * Handle the reading and writing of key data to and from
>> - * the TLS control channel (cleartext).
>> - */
> 
> Is it needed to remove this comment?  Or move it after the push_peer_info()
> function?

Yeah, we can move the comment.

> 
>> -static bool
>> -key_method_1_write(struct buffer *buf, struct tls_session *session)
>> -{
> [...snip...]
>> -}
>> -
>>  static bool
>>  push_peer_info(struct buffer *buf, struct tls_session *session)
>>  {
>> @@ -2312,7 +2246,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
>>           * push request, also signal that the client wants
>>           * to get push-reply messages without without requiring a round
>>           * trip for a push request message*/
>> -        if(session->opt->pull)
>> +        if (session->opt->pull)
>>          {
>>              iv_proto |= IV_PROTO_REQUEST_PUSH;
>>          }
>> @@ -2394,7 +2328,6 @@ key_method_2_write(struct buffer *buf, struct tls_session *session)
> 
> [...snip...]
> 
>> @@ -3470,14 +3316,12 @@ tls_pre_decrypt(struct tls_multi *multi,
>>              }
>>  
>>              /* hard reset ? */
>> -            if (is_hard_reset(op, 0))
>> +            if (is_hard_reset_method2(op))
>>              {
>>                  /* verify client -> server or server -> client connection */
>> -                if (((op == P_CONTROL_HARD_RESET_CLIENT_V1
>> -                      || op == P_CONTROL_HARD_RESET_CLIENT_V2
>> +                if (((op == P_CONTROL_HARD_RESET_CLIENT_V2
>>                        || op == P_CONTROL_HARD_RESET_CLIENT_V3) && !multi->opt.server)
>> -                    || ((op == P_CONTROL_HARD_RESET_SERVER_V1
>> -                         || op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
>> +                    || ((op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
>>                  {
>>                      msg(D_TLS_ERRORS,
>>                          "TLS Error: client->client or server->server connection attempted from %s",
>> @@ -3542,19 +3386,11 @@ tls_pre_decrypt(struct tls_multi *multi,
>>               * Initial packet received.
>>               */
>>  
>> -            if (i == TM_SIZE && is_hard_reset(op, 0))
>> +            if (i == TM_SIZE && is_hard_reset_method2(op))
>>              {
>>                  struct tls_session *session = &multi->session[TM_ACTIVE];
>>                  struct key_state *ks = &session->key[KS_PRIMARY];
>>  
>> -                if (!is_hard_reset(op, multi->opt.key_method))
>> -                {
>> -                    msg(D_TLS_ERRORS, "TLS ERROR: initial packet local/remote key_method mismatch, local key_method=%d, op=%s",
>> -                        multi->opt.key_method,
>> -                        packet_opcode_name(op));
>> -                    goto error;
>> -                }
>> -
>>                  /*
>>                   * If we have no session currently in progress, the initial packet will
>>                   * open a new session in TM_ACTIVE rather than TM_UNTRUSTED.
>> @@ -3594,7 +3430,7 @@ tls_pre_decrypt(struct tls_multi *multi,
>>                  }
>>              }
>>  
>> -            if (i == TM_SIZE && is_hard_reset(op, 0))
>> +            if (i == TM_SIZE && is_hard_reset_method2(op))
> 
> Do we need this if() block?  Considering it is exactly the same if() statement
> as the previous if() block.  I would suggest merging them, but you might hit a
> challenge with reuse of struct tls_session *session, where one is referring to
> TM_ACTIVE vs TM_UNTRUSTED.

That is something that might be possible but I would consider outside of
patch. The first block actually modifies i (i = TM_ACTIVE;), so that
needs a separate patch with an explaination why/how we simplify the
logic here.

Arne
David Sommerseth July 20, 2020, 8:49 a.m. UTC | #3
On 20/07/2020 15:22, Arne Schwabe wrote:
> Am 20.07.20 um 15:16 schrieb David Sommerseth:
>> On 17/07/2020 15:47, Arne Schwabe wrote:
>>> Key-method 1 is only needed to talk to pre OpenVPN 2.0 clients.
>>>
>>> Patch V2: Fix style. Make V1 op codes illegal, remove all code handling
>>>           v1 op codes and give a good warning message if we encounter
>>>           them in the legal op codes pre-check.
>>>
>>> Signed-off-by: Arne Schwabe <arne@rfc2549.org>
>>> ---
>>>  doc/doxygen/doc_control_processor.h |   6 +-
>>>  doc/doxygen/doc_key_generation.h    |   6 +-
>>>  doc/doxygen/doc_protocol_overview.h |   2 +-
>>>  src/openvpn/forward.c               |   2 +-
>>>  src/openvpn/helper.c                |   5 -
>>>  src/openvpn/init.c                  |   1 -
>>>  src/openvpn/options.c               |  35 +----
>>>  src/openvpn/options.h               |   4 -
>>>  src/openvpn/ssl.c                   | 230 ++++------------------------
>>>  src/openvpn/ssl.h                   |  19 +--
>>>  src/openvpn/ssl_common.h            |   1 -
>>>  11 files changed, 42 insertions(+), 269 deletions(-)
>>
>> [...snip...]
>>
>>> diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
>>> index 00b97352..4144217d 100644
>>> --- a/src/openvpn/ssl.c
>>> +++ b/src/openvpn/ssl.c
>>
>> [...snip...]
>>
>>> @@ -2225,52 +2205,6 @@ read_string_alloc(struct buffer *buf)
>>>      return str;
>>>  }
>>>  
>>> -/*
>>> - * Handle the reading and writing of key data to and from
>>> - * the TLS control channel (cleartext).
>>> - */
>>
>> Is it needed to remove this comment?  Or move it after the push_peer_info()
>> function?
> 
> Yeah, we can move the comment.

Yes, please ... Since it's not a bad comment, I don't like loosing helpful
pointers in comments :)

>>
>>> -static bool
>>> -key_method_1_write(struct buffer *buf, struct tls_session *session)
>>> -{
>> [...snip...]
>>> -}
>>> -
>>>  static bool
>>>  push_peer_info(struct buffer *buf, struct tls_session *session)
>>>  {
>>> @@ -2312,7 +2246,7 @@ push_peer_info(struct buffer *buf, struct tls_session *session)
>>>           * push request, also signal that the client wants
>>>           * to get push-reply messages without without requiring a round
>>>           * trip for a push request message*/
>>> -        if(session->opt->pull)
>>> +        if (session->opt->pull)
>>>          {
>>>              iv_proto |= IV_PROTO_REQUEST_PUSH;
>>>          }
>>> @@ -2394,7 +2328,6 @@ key_method_2_write(struct buffer *buf, struct tls_session *session)
>>
>> [...snip...]
>>
>>> @@ -3470,14 +3316,12 @@ tls_pre_decrypt(struct tls_multi *multi,
>>>              }
>>>  
>>>              /* hard reset ? */
>>> -            if (is_hard_reset(op, 0))
>>> +            if (is_hard_reset_method2(op))
>>>              {
>>>                  /* verify client -> server or server -> client connection */
>>> -                if (((op == P_CONTROL_HARD_RESET_CLIENT_V1
>>> -                      || op == P_CONTROL_HARD_RESET_CLIENT_V2
>>> +                if (((op == P_CONTROL_HARD_RESET_CLIENT_V2
>>>                        || op == P_CONTROL_HARD_RESET_CLIENT_V3) && !multi->opt.server)
>>> -                    || ((op == P_CONTROL_HARD_RESET_SERVER_V1
>>> -                         || op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
>>> +                    || ((op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
>>>                  {
>>>                      msg(D_TLS_ERRORS,
>>>                          "TLS Error: client->client or server->server connection attempted from %s",
>>> @@ -3542,19 +3386,11 @@ tls_pre_decrypt(struct tls_multi *multi,
>>>               * Initial packet received.
>>>               */
>>>  
>>> -            if (i == TM_SIZE && is_hard_reset(op, 0))
>>> +            if (i == TM_SIZE && is_hard_reset_method2(op))
>>>              {
>>>                  struct tls_session *session = &multi->session[TM_ACTIVE];
>>>                  struct key_state *ks = &session->key[KS_PRIMARY];
>>>  
>>> -                if (!is_hard_reset(op, multi->opt.key_method))
>>> -                {
>>> -                    msg(D_TLS_ERRORS, "TLS ERROR: initial packet local/remote key_method mismatch, local key_method=%d, op=%s",
>>> -                        multi->opt.key_method,
>>> -                        packet_opcode_name(op));
>>> -                    goto error;
>>> -                }
>>> -
>>>                  /*
>>>                   * If we have no session currently in progress, the initial packet will
>>>                   * open a new session in TM_ACTIVE rather than TM_UNTRUSTED.
>>> @@ -3594,7 +3430,7 @@ tls_pre_decrypt(struct tls_multi *multi,
>>>                  }
>>>              }
>>>  
>>> -            if (i == TM_SIZE && is_hard_reset(op, 0))
>>> +            if (i == TM_SIZE && is_hard_reset_method2(op))
>>
>> Do we need this if() block?  Considering it is exactly the same if() statement
>> as the previous if() block.  I would suggest merging them, but you might hit a
>> challenge with reuse of struct tls_session *session, where one is referring to
>> TM_ACTIVE vs TM_UNTRUSTED.
> 
> That is something that might be possible but I would consider outside of
> patch. The first block actually modifies i (i = TM_ACTIVE;), so that
> needs a separate patch with an explaination why/how we simplify the
> logic here.

Alright, I can see the argument of not touching it now.

Could we then just add a comment to these two sections for now, indicating why
they have been kept separate despite the if() statement being identical?
Something like "This section processes {TM_ACTIVE, TM_UNTRUSTED} sessions" and
elaborate a little bit around that, which may help refactoring this code later on.

Patch

diff --git a/doc/doxygen/doc_control_processor.h b/doc/doxygen/doc_control_processor.h
index f87324cc..1bbf2d2d 100644
--- a/doc/doxygen/doc_control_processor.h
+++ b/doc/doxygen/doc_control_processor.h
@@ -175,11 +175,7 @@ 
  *    appropriate messages to be sent.
  *
  * @par Functions which control data channel key generation
- *  - Key method 1 key exchange functions:
- *     - \c key_method_1_write(), generates and processes key material to
- *       be sent to the remote OpenVPN peer.
- *     - \c key_method_1_read(), processes key material received from the
- *       remote OpenVPN peer.
+ *  - Key method 1 key exchange functions were removed from OpenVPN 2.5
  *  - Key method 2 key exchange functions:
  *     - \c key_method_2_write(), generates and processes key material to
  *       be sent to the remote OpenVPN peer.
diff --git a/doc/doxygen/doc_key_generation.h b/doc/doxygen/doc_key_generation.h
index efe61155..4bb9c708 100644
--- a/doc/doxygen/doc_key_generation.h
+++ b/doc/doxygen/doc_key_generation.h
@@ -131,11 +131,7 @@  S_ACTIVE                                                            S_ACTIVE
  * control_processor Control Channel Processor module's\endlink \c
  * tls_process() function and control the %key generation and exchange
  * process as follows:
- * - %Key method 1:
- *   - \c key_method_1_write(): generate random material locally, and load
- *     as "sending" keys.
- *   - \c key_method_1_read(): read random material received from remote
- *     peer, and load as "receiving" keys.
+ * - %Key method 1 has been removed in OpenVPN 2.5
  * - %Key method 2:
  *   - \c key_method_2_write(): generate random material locally, and if
  *     in server mode generate %key expansion.
diff --git a/doc/doxygen/doc_protocol_overview.h b/doc/doxygen/doc_protocol_overview.h
index 3f48b18a..08212223 100644
--- a/doc/doxygen/doc_protocol_overview.h
+++ b/doc/doxygen/doc_protocol_overview.h
@@ -150,7 +150,7 @@ 
  *
  * @subsection network_protocol_control_plaintext Structure of plaintext control channel messages
  *
- *  - %Key method 1:
+ *  - %Key method 1 (support removed in OpenVPN 2.5):
  *     - Cipher %key length in bytes (1 byte).
  *     - Cipher %key (n bytes).
  *     - HMAC %key length in bytes (1 byte).
diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 5c4370a8..698451d1 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -1100,7 +1100,7 @@  process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
                                 floated, &ad_start))
             {
                 /* Restore pre-NCP frame parameters */
-                if (is_hard_reset(opcode, c->options.key_method))
+                if (is_hard_reset_method2(opcode))
                 {
                     c->c2.frame = c->c2.frame_initial;
 #ifdef ENABLE_FRAGMENT
diff --git a/src/openvpn/helper.c b/src/openvpn/helper.c
index 6e9cc63c..a1d03070 100644
--- a/src/openvpn/helper.c
+++ b/src/openvpn/helper.c
@@ -490,11 +490,6 @@  helper_client_server(struct options *o)
      */
     if (o->client)
     {
-        if (o->key_method != 2)
-        {
-            msg(M_USAGE, "--client requires --key-method 2");
-        }
-
         o->pull = true;
         o->tls_client = true;
     }
diff --git a/src/openvpn/init.c b/src/openvpn/init.c
index e9c01629..b96d1471 100644
--- a/src/openvpn/init.c
+++ b/src/openvpn/init.c
@@ -2852,7 +2852,6 @@  do_init_crypto_tls(struct context *c, const unsigned int flags)
     to.ssl_ctx = c->c1.ks.ssl_ctx;
     to.key_type = c->c1.ks.key_type;
     to.server = options->tls_server;
-    to.key_method = options->key_method;
     to.replay = options->replay;
     to.replay_window = options->replay_window;
     to.replay_time = options->replay_time;
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 15173db2..0025c526 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -881,7 +881,6 @@  init_options(struct options *o, const bool init_gc)
 #ifdef ENABLE_PREDICTION_RESISTANCE
     o->use_prediction_resistance = false;
 #endif
-    o->key_method = 2;
     o->tls_timeout = 2;
     o->renegotiate_bytes = -1;
     o->renegotiate_seconds = 3600;
@@ -1715,7 +1714,6 @@  show_settings(const struct options *o)
 
     SHOW_BOOL(tls_server);
     SHOW_BOOL(tls_client);
-    SHOW_INT(key_method);
     SHOW_STR(ca_file);
     SHOW_STR(ca_path);
     SHOW_STR(dh_file);
@@ -2376,10 +2374,6 @@  options_postprocess_verify_ce(const struct options *options, const struct connec
         {
             msg(M_USAGE, "--ccd-exclusive must be used with --client-config-dir");
         }
-        if (options->key_method != 2)
-        {
-            msg(M_USAGE, "--mode server requires --key-method 2");
-        }
         if (options->auth_token_generate && !options->renegotiate_seconds)
         {
             msg(M_USAGE, "--auth-gen-token needs a non-infinite "
@@ -2546,13 +2540,6 @@  options_postprocess_verify_ce(const struct options *options, const struct connec
             "may accept clients which do not present a certificate");
     }
 
-    if (options->key_method == 1)
-    {
-        msg(M_WARN, "WARNING: --key-method 1 is deprecated and will be removed "
-            "in OpenVPN 2.5.  By default --key-method 2 will be used if not set "
-            "in the configuration file, which is the recommended approach.");
-    }
-
     const int tls_version_max =
         (options->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT)
         & SSLF_TLS_VERSION_MAX_MASK;
@@ -2794,7 +2781,6 @@  options_postprocess_verify_ce(const struct options *options, const struct connec
         MUST_BE_UNDEF(push_peer_info);
         MUST_BE_UNDEF(tls_exit);
         MUST_BE_UNDEF(crl_file);
-        MUST_BE_UNDEF(key_method);
         MUST_BE_UNDEF(ns_cert_type);
         MUST_BE_UNDEF(remote_cert_ku[0]);
         MUST_BE_UNDEF(remote_cert_eku);
@@ -3823,10 +3809,7 @@  options_string(const struct options *o,
              * tls-auth/tls-crypt does not match.  Removing tls-auth here would
              * break stuff, so leaving that in place. */
 
-            if (o->key_method > 1)
-            {
-                buf_printf(&out, ",key-method %d", o->key_method);
-            }
+            buf_printf(&out, ",key-method %d", KEY_METHOD_2);
         }
 
         if (remote)
@@ -8477,22 +8460,6 @@  add_option(struct options *options,
         VERIFY_PERMISSION(OPT_P_GENERAL);
         options->tls_crypt_v2_verify_script = p[1];
     }
-    else if (streq(p[0], "key-method") && p[1] && !p[2])
-    {
-        int key_method;
-
-        VERIFY_PERMISSION(OPT_P_GENERAL);
-        key_method = atoi(p[1]);
-        if (key_method < KEY_METHOD_MIN || key_method > KEY_METHOD_MAX)
-        {
-            msg(msglevel, "key_method parameter (%d) must be >= %d and <= %d",
-                key_method,
-                KEY_METHOD_MIN,
-                KEY_METHOD_MAX);
-            goto err;
-        }
-        options->key_method = key_method;
-    }
     else if (streq(p[0], "x509-track") && p[1] && !p[2])
     {
         VERIFY_PERMISSION(OPT_P_GENERAL);
diff --git a/src/openvpn/options.h b/src/openvpn/options.h
index 1b038c91..3546bab3 100644
--- a/src/openvpn/options.h
+++ b/src/openvpn/options.h
@@ -572,10 +572,6 @@  struct options
 #ifdef ENABLE_CRYPTOAPI
     const char *cryptoapi_cert;
 #endif
-
-    /* data channel key exchange method */
-    int key_method;
-
     /* Per-packet timeout on control channel */
     int tls_timeout;
 
diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
index 00b97352..4144217d 100644
--- a/src/openvpn/ssl.c
+++ b/src/openvpn/ssl.c
@@ -861,23 +861,12 @@  print_key_id(struct tls_multi *multi, struct gc_arena *gc)
 }
 
 bool
-is_hard_reset(int op, int key_method)
+is_hard_reset_method2(int op)
 {
-    if (!key_method || key_method == 1)
+    if (op == P_CONTROL_HARD_RESET_CLIENT_V2 || op == P_CONTROL_HARD_RESET_SERVER_V2
+        || op == P_CONTROL_HARD_RESET_CLIENT_V3)
     {
-        if (op == P_CONTROL_HARD_RESET_CLIENT_V1 || op == P_CONTROL_HARD_RESET_SERVER_V1)
-        {
-            return true;
-        }
-    }
-
-    if (!key_method || key_method >= 2)
-    {
-        if (op == P_CONTROL_HARD_RESET_CLIENT_V2 || op == P_CONTROL_HARD_RESET_SERVER_V2
-            || op == P_CONTROL_HARD_RESET_CLIENT_V3)
-        {
-            return true;
-        }
+        return true;
     }
 
     return false;
@@ -1097,23 +1086,14 @@  tls_session_init(struct tls_multi *multi, struct tls_session *session)
     }
 
     /* Are we a TLS server or client? */
-    ASSERT(session->opt->key_method >= 1);
-    if (session->opt->key_method == 1)
+    if (session->opt->server)
     {
-        session->initial_opcode = session->opt->server ?
-                                  P_CONTROL_HARD_RESET_SERVER_V1 : P_CONTROL_HARD_RESET_CLIENT_V1;
+        session->initial_opcode = P_CONTROL_HARD_RESET_SERVER_V2;
     }
-    else /* session->opt->key_method >= 2 */
+    else
     {
-        if (session->opt->server)
-        {
-            session->initial_opcode = P_CONTROL_HARD_RESET_SERVER_V2;
-        }
-        else
-        {
-            session->initial_opcode = session->opt->tls_crypt_v2 ?
-                                      P_CONTROL_HARD_RESET_CLIENT_V3 : P_CONTROL_HARD_RESET_CLIENT_V2;
-        }
+        session->initial_opcode = session->opt->tls_crypt_v2 ?
+                                  P_CONTROL_HARD_RESET_CLIENT_V3 : P_CONTROL_HARD_RESET_CLIENT_V2;
     }
 
     /* Initialize control channel authentication parameters */
@@ -1993,9 +1973,9 @@  tls_session_update_crypto_params(struct tls_session *session,
     }
     else
     {
-      /* Very hacky workaround and quick fix for frame calculation
-       * different when adjusting frame size when the original and new cipher
-       * are identical to avoid a regression with client without NCP */
+        /* Very hacky workaround and quick fix for frame calculation
+         * different when adjusting frame size when the original and new cipher
+         * are identical to avoid a regression with client without NCP */
         return tls_session_generate_data_channel_keys(session);
     }
 
@@ -2225,52 +2205,6 @@  read_string_alloc(struct buffer *buf)
     return str;
 }
 
-/*
- * Handle the reading and writing of key data to and from
- * the TLS control channel (cleartext).
- */
-
-static bool
-key_method_1_write(struct buffer *buf, struct tls_session *session)
-{
-    struct key key;
-    struct key_state *ks = &session->key[KS_PRIMARY];      /* primary key */
-
-    ASSERT(session->opt->key_method == 1);
-    ASSERT(buf_init(buf, 0));
-
-    generate_key_random(&key, &session->opt->key_type);
-    if (!check_key(&key, &session->opt->key_type))
-    {
-        msg(D_TLS_ERRORS, "TLS Error: Bad encrypting key generated");
-        return false;
-    }
-
-    if (!write_key(&key, &session->opt->key_type, buf))
-    {
-        msg(D_TLS_ERRORS, "TLS Error: write_key failed");
-        return false;
-    }
-
-    init_key_ctx(&ks->crypto_options.key_ctx_bi.encrypt, &key,
-                 &session->opt->key_type, OPENVPN_OP_ENCRYPT,
-                 "Data Channel Encrypt");
-    secure_memzero(&key, sizeof(key));
-
-    /* send local options string */
-    {
-        const char *local_options = local_options_string(session);
-        const int optlen = strlen(local_options) + 1;
-        if (!buf_write(buf, local_options, optlen))
-        {
-            msg(D_TLS_ERRORS, "TLS Error: KM1 write options failed");
-            return false;
-        }
-    }
-
-    return true;
-}
-
 static bool
 push_peer_info(struct buffer *buf, struct tls_session *session)
 {
@@ -2312,7 +2246,7 @@  push_peer_info(struct buffer *buf, struct tls_session *session)
          * push request, also signal that the client wants
          * to get push-reply messages without without requiring a round
          * trip for a push request message*/
-        if(session->opt->pull)
+        if (session->opt->pull)
         {
             iv_proto |= IV_PROTO_REQUEST_PUSH;
         }
@@ -2394,7 +2328,6 @@  key_method_2_write(struct buffer *buf, struct tls_session *session)
 {
     struct key_state *ks = &session->key[KS_PRIMARY];      /* primary key */
 
-    ASSERT(session->opt->key_method == 2);
     ASSERT(buf_init(buf, 0));
 
     /* write a uint32 0 */
@@ -2404,7 +2337,7 @@  key_method_2_write(struct buffer *buf, struct tls_session *session)
     }
 
     /* write key_method + flags */
-    if (!buf_write_u8(buf, (session->opt->key_method & KEY_METHOD_MASK)))
+    if (!buf_write_u8(buf, KEY_METHOD_2))
     {
         goto error;
     }
@@ -2506,73 +2439,11 @@  error:
     return false;
 }
 
-static bool
-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 */
-
-    ASSERT(session->opt->key_method == 1);
-
-    if (!session->verified)
-    {
-        msg(D_TLS_ERRORS,
-            "TLS Error: Certificate verification failed (key-method 1)");
-        goto error;
-    }
-
-    status = read_key(&key, &session->opt->key_type, buf);
-    if (status != 1)
-    {
-        msg(D_TLS_ERRORS,
-            "TLS Error: Error reading data channel key from plaintext buffer");
-        goto error;
-    }
-
-    if (!check_key(&key, &session->opt->key_type))
-    {
-        msg(D_TLS_ERRORS, "TLS Error: Bad decrypting key received from peer");
-        goto error;
-    }
-
-    if (buf->len < 1)
-    {
-        msg(D_TLS_ERRORS, "TLS Error: Missing options string");
-        goto error;
-    }
-
-#ifdef ENABLE_OCC
-    /* compare received remote options string
-     * with our locally computed options string */
-    if (!session->opt->disable_occ
-        && !options_cmp_equal_safe((char *) BPTR(buf), session->opt->remote_options, buf->len))
-    {
-        options_warning_safe((char *) BPTR(buf), session->opt->remote_options, buf->len);
-    }
-#endif
-
-    buf_clear(buf);
-
-    init_key_ctx(&ks->crypto_options.key_ctx_bi.decrypt, &key,
-                 &session->opt->key_type, OPENVPN_OP_DECRYPT,
-                 "Data Channel Decrypt");
-    secure_memzero(&key, sizeof(key));
-    ks->authenticated = KS_AUTH_TRUE;
-    return true;
-
-error:
-    buf_clear(buf);
-    secure_memzero(&key, sizeof(key));
-    return false;
-}
-
 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 */
 
-    int key_method_flags;
     bool username_status, password_status;
 
     struct gc_arena gc = gc_new();
@@ -2582,8 +2453,6 @@  key_method_2_read(struct buffer *buf, struct tls_multi *multi, struct tls_sessio
     /* allocate temporary objects */
     ALLOC_ARRAY_CLEAR_GC(options, char, TLS_OPTIONS_LEN, &gc);
 
-    ASSERT(session->opt->key_method == 2);
-
     /* discard leading uint32 */
     if (!buf_advance(buf, 4))
     {
@@ -2593,7 +2462,7 @@  key_method_2_read(struct buffer *buf, struct tls_multi *multi, struct tls_sessio
     }
 
     /* get key method */
-    key_method_flags = buf_read_u8(buf);
+    int key_method_flags = buf_read_u8(buf);
     if ((key_method_flags & KEY_METHOD_MASK) != 2)
     {
         msg(D_TLS_ERRORS,
@@ -3003,23 +2872,9 @@  tls_process(struct tls_multi *multi,
         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 (!key_method_2_write(buf, session))
             {
-                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);
+                goto error;
             }
 
             state_change = true;
@@ -3033,23 +2888,9 @@  tls_process(struct tls_multi *multi,
             && ((ks->state == S_SENT_KEY && !session->opt->server)
                 || (ks->state == S_START && session->opt->server)))
         {
-            if (session->opt->key_method == 1)
+            if (!key_method_2_read(buf, multi, session))
             {
-                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);
+                goto error;
             }
 
             state_change = true;
@@ -3463,6 +3304,11 @@  tls_pre_decrypt(struct tls_multi *multi,
             /* verify legal opcode */
             if (op < P_FIRST_OPCODE || op > P_LAST_OPCODE)
             {
+                if (op == P_CONTROL_HARD_RESET_CLIENT_V1
+                    || op == P_CONTROL_HARD_RESET_SERVER_V1)
+                {
+                    msg(D_TLS_ERRORS, "Peer tried unsupported key-method 1");
+                }
                 msg(D_TLS_ERRORS,
                     "TLS Error: unknown opcode received from %s op=%d",
                     print_link_socket_actual(from, &gc), op);
@@ -3470,14 +3316,12 @@  tls_pre_decrypt(struct tls_multi *multi,
             }
 
             /* hard reset ? */
-            if (is_hard_reset(op, 0))
+            if (is_hard_reset_method2(op))
             {
                 /* verify client -> server or server -> client connection */
-                if (((op == P_CONTROL_HARD_RESET_CLIENT_V1
-                      || op == P_CONTROL_HARD_RESET_CLIENT_V2
+                if (((op == P_CONTROL_HARD_RESET_CLIENT_V2
                       || op == P_CONTROL_HARD_RESET_CLIENT_V3) && !multi->opt.server)
-                    || ((op == P_CONTROL_HARD_RESET_SERVER_V1
-                         || op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
+                    || ((op == P_CONTROL_HARD_RESET_SERVER_V2) && multi->opt.server))
                 {
                     msg(D_TLS_ERRORS,
                         "TLS Error: client->client or server->server connection attempted from %s",
@@ -3542,19 +3386,11 @@  tls_pre_decrypt(struct tls_multi *multi,
              * Initial packet received.
              */
 
-            if (i == TM_SIZE && is_hard_reset(op, 0))
+            if (i == TM_SIZE && is_hard_reset_method2(op))
             {
                 struct tls_session *session = &multi->session[TM_ACTIVE];
                 struct key_state *ks = &session->key[KS_PRIMARY];
 
-                if (!is_hard_reset(op, multi->opt.key_method))
-                {
-                    msg(D_TLS_ERRORS, "TLS ERROR: initial packet local/remote key_method mismatch, local key_method=%d, op=%s",
-                        multi->opt.key_method,
-                        packet_opcode_name(op));
-                    goto error;
-                }
-
                 /*
                  * If we have no session currently in progress, the initial packet will
                  * open a new session in TM_ACTIVE rather than TM_UNTRUSTED.
@@ -3594,7 +3430,7 @@  tls_pre_decrypt(struct tls_multi *multi,
                 }
             }
 
-            if (i == TM_SIZE && is_hard_reset(op, 0))
+            if (i == TM_SIZE && is_hard_reset_method2(op))
             {
                 /*
                  * No match with existing sessions,
@@ -3614,14 +3450,6 @@  tls_pre_decrypt(struct tls_multi *multi,
                     goto error;
                 }
 
-                if (!is_hard_reset(op, multi->opt.key_method))
-                {
-                    msg(D_TLS_ERRORS, "TLS ERROR: new session local/remote key_method mismatch, local key_method=%d, op=%s",
-                        multi->opt.key_method,
-                        packet_opcode_name(op));
-                    goto error;
-                }
-
                 if (!read_control_auth(buf, &session->tls_wrap, from,
                                        session->opt))
                 {
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
index 86fb6853..b4ce407c 100644
--- a/src/openvpn/ssl.h
+++ b/src/openvpn/ssl.h
@@ -66,8 +66,10 @@ 
 /* indicates key_method >= 2 and client-specific tls-crypt key */
 #define P_CONTROL_HARD_RESET_CLIENT_V3 10    /* initial key from client, forget previous state */
 
-/* define the range of legal opcodes */
-#define P_FIRST_OPCODE                 1
+/* define the range of legal opcodes
+ * Since we do no longer support key-method 1 we consider
+ * the v1 op codes invalid */
+#define P_FIRST_OPCODE                 3
 #define P_LAST_OPCODE                  10
 
 /*
@@ -109,11 +111,7 @@ 
 /* Default field in X509 to be username */
 #define X509_USERNAME_FIELD_DEFAULT "CN"
 
-/*
- * Range of key exchange methods
- */
-#define KEY_METHOD_MIN 1
-#define KEY_METHOD_MAX 2
+#define KEY_METHOD_2  2
 
 /* key method taken from lower 4 bits */
 #define KEY_METHOD_MASK 0x0F
@@ -585,12 +583,11 @@  void show_tls_performance_stats(void);
 void extract_x509_field_test(void);
 
 /**
- * Given a key_method, return true if opcode represents the required form of
- * hard_reset.
+ * Given a key_method, return true if opcode represents the one of the
+ * hard_reset op codes for key-method 2
  *
- * If key_method == 0, return true if any form of hard reset is used.
  */
-bool is_hard_reset(int op, int key_method);
+bool is_hard_reset_method2(int op);
 
 void delayed_auth_pass_purge(void);
 
diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h
index e0b3ee56..d904c31f 100644
--- a/src/openvpn/ssl_common.h
+++ b/src/openvpn/ssl_common.h
@@ -262,7 +262,6 @@  struct tls_options
 #endif
 
     /* from command line */
-    int key_method;
     bool replay;
     bool single_session;
 #ifdef ENABLE_OCC