[Openvpn-devel,6/7] Fix allowing/showing unsupported ciphers and digests

Message ID 20220512121429.2096164-7-arne@rfc2549.org
State Accepted
Headers show
Series Improve OpenSSL 3.0 support in OpenVPN 2.5 | expand

Commit Message

Arne Schwabe May 12, 2022, 2:14 a.m. UTC
This is a minimal version to hide the non-supported ciphers in these
show-cipher/show-digests listings. It also adds code to the kt_md_get/
kt_cipher_get functions to error out early instead of getting an ugly
backtrace with OpenSSL errors later when actually trying to use the ciphers.

This allows make check to work again on with OpenSSL 3.0.

The changes are kept minimal to  avoid pulling in all the other refactoring
for OpenSSL 3.0.

This commit is partly cherry-picked from ab3f32b9.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
---
 src/openvpn/crypto_openssl.c | 50 +++++++++++++++++++++++++++++++++---
 1 file changed, 47 insertions(+), 3 deletions(-)

Comments

Gert Doering May 12, 2022, 9:23 p.m. UTC | #1
Acked-by: Gert Doering <gert@greenie.muc.de>

Code is close enough to the master version, and it nicely does what it
says ("openvpn --providers legacy --show-ciphers" vs. "--show-ciphers").

While this fixes the "cipher loopback test", it now breaks 
tls_crypt_testdriver, as that one expects BF-CBC to be universally
available...

Unsupported cipher in --data-ciphers: BF-CBC
Unsupported cipher in --data-ciphers: BF-CBC
[  ERROR   ] --- Test failed with exception: Segmentation fault(11)

.. to be fixed in 7/7.

(Breakage only in 3.0.x builds, of course, 1.1.x builds are fine)

Fixed one spurious newline, and another uncrustify complaint
introduced by crypto_unload_provider().

Your patch has been applied to the release/2.5 branch.

commit 3690939126cf84b166157bad96e724caea61346d
Author: Arne Schwabe
Date:   Thu May 12 14:14:28 2022 +0200

     Fix allowing/showing unsupported ciphers and digests

     Signed-off-by: Arne Schwabe <arne@rfc2549.org>
     Acked-by: Gert Doering <gert@greenie.muc.de>
     Message-Id: <20220512121429.2096164-7-arne@rfc2549.org>
     URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg24334.html
     Signed-off-by: Gert Doering <gert@greenie.muc.de>


--
kind regards,

Gert Doering

Patch

diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
index beeaee4b7..ad6c9353a 100644
--- a/src/openvpn/crypto_openssl.c
+++ b/src/openvpn/crypto_openssl.c
@@ -339,7 +339,11 @@  show_available_ciphers(void)
                        || cipher_kt_mode_aead(cipher)
                        ))
         {
-            cipher_list[num_ciphers++] = cipher;
+            /* Check explicit availibility (for OpenSSL 3.0) */
+            if (cipher_kt_get(cipher_kt_name(cipher)))
+            {
+                cipher_list[num_ciphers++] = cipher;
+            }
         }
         if (num_ciphers == (sizeof(cipher_list)/sizeof(*cipher_list)))
         {
@@ -371,6 +375,13 @@  show_available_ciphers(void)
     printf("\n");
 }
 
+void
+print_digest(EVP_MD *digest, void *unused)
+{
+    printf("%s %d bit digest size\n", EVP_MD_name(digest),
+           EVP_MD_size(digest) * 8);
+}
+
 void
 show_available_digests(void)
 {
@@ -384,16 +395,22 @@  show_available_digests(void)
            "the --auth option.\n\n");
 #endif
 
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    EVP_MD_do_all_provided(NULL, print_digest, NULL);
+#else
     for (nid = 0; nid < 10000; ++nid)
     {
+
         const EVP_MD *digest = EVP_get_digestbynid(nid);
         if (digest)
         {
-            printf("%s %d bit digest size\n",
-                   OBJ_nid2sn(nid), EVP_MD_size(digest) * 8);
+            /* We cast the const away so we can keep the function prototype
+             * compatible with EVP_MD_do_all_provided */
+            print_digest((EVP_MD *)digest, NULL);
         }
     }
     printf("\n");
+#endif
 }
 
 void
@@ -624,6 +641,19 @@  cipher_kt_get(const char *ciphername)
     ciphername = translate_cipher_name_from_openvpn(ciphername);
     cipher = EVP_get_cipherbyname(ciphername);
 
+    /* This is a workaround for OpenSSL 3.0 to infer if the cipher is valid
+     * without doing all the refactoring that OpenVPN 2.6 has. This will
+     * not support custom algorithm from providers but at least ignore
+     * algorithms that are not available without providers (legacy) */
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    EVP_CIPHER *tmpcipher = EVP_CIPHER_fetch(NULL, ciphername, NULL);
+    if (!tmpcipher)
+    {
+        cipher = NULL;
+    }
+    EVP_CIPHER_free(tmpcipher);
+#endif
+
     if (NULL == cipher)
     {
         crypto_msg(D_LOW, "Cipher algorithm '%s' not found", ciphername);
@@ -924,6 +954,20 @@  md_kt_get(const char *digest)
     const EVP_MD *md = NULL;
     ASSERT(digest);
     md = EVP_get_digestbyname(digest);
+
+    /* This is a workaround for OpenSSL 3.0 to infer if the digest is valid
+     * without doing all the refactoring that OpenVPN 2.6 has. This will
+     * not support custom algorithm from providers but at least ignore
+     * algorithms that are not available without providers (legacy) */
+#if OPENSSL_VERSION_NUMBER >= 0x30000000L
+    EVP_MD *tmpmd = EVP_MD_fetch(NULL, digest, NULL);
+    if (!tmpmd)
+    {
+        md = NULL;
+    }
+    EVP_MD_free(tmpmd);
+#endif
+
     if (!md)
     {
         crypto_msg(M_FATAL, "Message hash algorithm '%s' not found", digest);