Browse code

Implement optional cipher in --data-ciphers prefixed with ?

This allows to use the same configuration multiple platforms/ssl libraries
and include optional algorithms that are not available on all platforms

For example "AES-256-GCM:AES-128-GCM:?CHACHA20-POLY1305" can be used to
emulate the default behaviour of OpenVPN 2.6.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20211201180727.2496903-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg23279.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 766044507497c41f0319159c37992788ecb681e6)

Arne Schwabe authored on 2021/12/02 03:07:19
Showing 4 changed files
... ...
@@ -1,3 +1,12 @@
1
+Overview of changes in 2.5.9
2
+============================
3
+
4
+New features
5
+------------
6
+- Optional ciphers in ``--data-ciphers``
7
+  Ciphers in ``--data-ciphers`` can now be prefixed with a ``?`` to mark
8
+  those as optional and only use them if the SSL library supports them.
9
+
1 10
 Overview of changes in 2.5.8
2 11
 ============================
3 12
 
... ...
@@ -184,6 +184,13 @@ configured in a compatible way between both the local and remote side.
184 184
   supported by the client will be pushed to clients that support cipher
185 185
   negotiation.
186 186
 
187
+  Starting with OpenVPN 2.5.9 a cipher can be prefixed with a :code:`?` to mark
188
+  it as optional. This allows including ciphers in the list that may not be
189
+  available on all platforms.
190
+  E.g. :code:`AES-256-GCM:AES-128-GCM:?CHACHA20-POLY1305` would only enable
191
+  Chacha20-Poly1305 if the underlying SSL library (and its configuration)
192
+  supports it.
193
+
187 194
   Cipher negotiation is enabled in client-server mode only. I.e. if
188 195
   ``--mode`` is set to 'server' (server-side, implied by setting
189 196
   ``--server`` ), or if ``--pull`` is specified (client-side, implied by
... ...
@@ -108,7 +108,18 @@ mutate_ncp_cipher_list(const char *list, struct gc_arena *gc)
108 108
          * (and translate_cipher_name_from_openvpn/
109 109
          * translate_cipher_name_to_openvpn) also normalises the cipher name,
110 110
          * e.g. replacing AeS-128-gCm with AES-128-GCM
111
+         *
112
+         * ciphers that have ? in front of them are considered optional and
113
+         * OpenVPN will only warn if they are not found (and remove them from
114
+         * the list)
111 115
          */
116
+
117
+        bool optional = false;
118
+        if (token[0] == '?')
119
+        {
120
+            token++;
121
+            optional = true;
122
+        }
112 123
         const cipher_kt_t *ktc = cipher_kt_get(token);
113 124
         if (strcmp(token, "none") == 0)
114 125
         {
... ...
@@ -120,8 +131,9 @@ mutate_ncp_cipher_list(const char *list, struct gc_arena *gc)
120 120
         }
121 121
         if (!ktc && strcmp(token, "none") != 0)
122 122
         {
123
-            msg(M_WARN, "Unsupported cipher in --data-ciphers: %s", token);
124
-            error_found = true;
123
+            const char* optstr = optional ? "optional ": "";
124
+            msg(M_WARN, "Unsupported %scipher in --data-ciphers: %s", optstr, token);
125
+            error_found = !optional;
125 126
         }
126 127
         else
127 128
         {
... ...
@@ -74,6 +74,17 @@ test_check_ncp_ciphers_list(void **state)
74 74
         assert_ptr_equal(mutate_ncp_cipher_list(bf_chacha, &gc), NULL);
75 75
     }
76 76
 
77
+    /* Check that optional ciphers work */
78
+    assert_string_equal(mutate_ncp_cipher_list("AES-256-GCM:?vollbit:AES-128-GCM", &gc),
79
+                        aes_ciphers);
80
+
81
+    /* Check that optional ciphers work */
82
+    assert_string_equal(mutate_ncp_cipher_list("?AES-256-GCM:?AES-128-GCM", &gc),
83
+                        aes_ciphers);
84
+
85
+    /* All unsupported should still yield an empty list */
86
+    assert_ptr_equal(mutate_ncp_cipher_list("?kugelfisch:?grasshopper", &gc), NULL);
87
+
77 88
     /* For testing that with OpenSSL 1.1.0+ that also accepts ciphers in
78 89
      * a different spelling the normalised cipher output is the same */
79 90
     bool have_chacha_mixed_case = cipher_kt_get("ChaCha20-Poly1305");