Browse code

Workaround issue in LibreSSL crashing when enumerating digests/ciphers

OpenBSD/LibreSSL reimplemented EVP_get_cipherbyname/EVP_get_digestbyname
and broke calling EVP_get_cipherbynid/EVP_get_digestbyname with an
invalid nid in the process so that it would segfault.

Workaround but doing that NULL check in OpenVPN instead of leaving it
to the library.

Github: see also https://github.com/libressl/openbsd/issues/150

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

Arne Schwabe authored on 2024/05/09 07:05:40
Showing 1 changed files
... ...
@@ -386,7 +386,19 @@ show_available_ciphers(void)
386 386
 #else
387 387
     for (int nid = 0; nid < 10000; ++nid)
388 388
     {
389
+#if defined(LIBRESSL_VERSION_NUMBER)
390
+        /* OpenBSD/LibreSSL reimplemented EVP_get_cipherbyname and broke
391
+         * calling EVP_get_cipherbynid with an invalid nid in the process
392
+         * so that it would segfault. */
393
+        const EVP_CIPHER *cipher = NULL;
394
+        const char *name = OBJ_nid2sn(nid);
395
+        if (name)
396
+        {
397
+            cipher = EVP_get_cipherbyname(name);
398
+        }
399
+#else  /* if defined(LIBRESSL_VERSION_NUMBER) */
389 400
         const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
401
+#endif
390 402
         /* We cast the const away so we can keep the function prototype
391 403
          * compatible with EVP_CIPHER_do_all_provided */
392 404
         collect_ciphers((EVP_CIPHER *) cipher, &cipher_list);
... ...
@@ -440,7 +452,19 @@ show_available_digests(void)
440 440
 #else
441 441
     for (int nid = 0; nid < 10000; ++nid)
442 442
     {
443
+        /* OpenBSD/LibreSSL reimplemented EVP_get_digestbyname and broke
444
+         * calling EVP_get_digestbynid with an invalid nid in the process
445
+         * so that it would segfault. */
446
+#ifdef LIBRESSL_VERSION_NUMBER
447
+        const EVP_MD *digest = NULL;
448
+        const char *name = OBJ_nid2sn(nid);
449
+        if (name)
450
+        {
451
+            digest = EVP_get_digestbyname(name);
452
+        }
453
+#else  /* ifdef LIBRESSL_VERSION_NUMBER */
443 454
         const EVP_MD *digest = EVP_get_digestbynid(nid);
455
+#endif
444 456
         if (digest)
445 457
         {
446 458
             /* We cast the const away so we can keep the function prototype
... ...
@@ -448,7 +472,7 @@ show_available_digests(void)
448 448
             print_digest((EVP_MD *)digest, NULL);
449 449
         }
450 450
     }
451
-#endif
451
+#endif /* if OPENSSL_VERSION_NUMBER >= 0x30000000L */
452 452
     printf("\n");
453 453
 }
454 454