Bug 273506 - main [so: 15] aarch64&amd64 kyua python use can fail with: "/usr/lib/ossl-modules/legacy.so: Undefined symbol \"MD4_Update\"", '\000' <repeats 449 times>
Summary: main [so: 15] aarch64&amd64 kyua python use can fail with: "/usr/lib/ossl-mod...
Status: Closed Overcome By Events
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: Li-Wen Hsu
URL:
Keywords:
Depends on:
Blocks: 14.0r
  Show dependency treegraph
 
Reported: 2023-09-02 00:58 UTC by Mark Millard
Modified: 2023-09-19 19:19 UTC (History)
8 users (show)

See Also:


Attachments
0001-libcrypto-try-to-fix-the-legacy-provider-on-aarch64.patch (1.23 KB, patch)
2023-09-05 12:20 UTC, Pierre Pronchery
no flags Details | Diff
0001-libcrypto-link-engines-and-the-legacy-provider-to-li.patch (155.91 KB, patch)
2023-09-15 16:59 UTC, Pierre Pronchery
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Millard 2023-09-02 00:58:29 UTC
[openssl3 related failures are not clear to me for system vs. ports.
Pick Base System for this initially.]

On aarch64 [and armv7 via aarch64 chroot] after recent port progressions
to openssl3 kyua that invovles python gets:

# /usr/bin/kyua test -k /usr/tests/Kyuafile examples/test_examples.py
examples/test_examples.py:__test_cases_list__  ->  broken: Test program did not exit cleanly  [0.002s]

[By contrast, amd64 worked fine.]

Doing this in a form that exposes the error report about
legacy support:

# env PYTHONPATH=/usr/tests /usr/local/bin/python3.9 /usr/local/bin/pytest -vv -p no:cacheprovider -s --atf --confcutdir=/usr/tests --atf-file=/tmp/kyua.dabz6H/2/result.atf /usr/tests/examples/test_examples.py::TestExampleSimple::test_with_cleanup
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/_pytest/main.py", line 266, in wrap_session
INTERNALERROR>     config._do_configure()
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/_pytest/config/__init__.py", line 1054, in _do_configure
INTERNALERROR>     self.hook.pytest_configure.call_historic(kwargs=dict(config=self))
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/pluggy/_hooks.py", line 452, in call_historic
INTERNALERROR>     res = self._hookexec(self.name, self._hookimpls, kwargs, False)
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/pluggy/_manager.py", line 112, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/pluggy/_callers.py", line 116, in _multicall
INTERNALERROR>     raise exception.with_traceback(exception.__traceback__)
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/pluggy/_callers.py", line 80, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/pytest_twisted.py", line 516, in pytest_configure
INTERNALERROR>     reactor_installers[config.getoption("reactor")]()
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/pytest_twisted.py", line 435, in init_default_reactor
INTERNALERROR>     import twisted.internet.default
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/internet/default.py", line 55, in <module>
INTERNALERROR>     install = _getInstallFunction(platform)
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/internet/default.py", line 47, in _getInstallFunction
INTERNALERROR>     from twisted.internet.pollreactor import install
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/internet/pollreactor.py", line 29, in <module>
INTERNALERROR>     from twisted.internet import posixbase
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/internet/posixbase.py", line 16, in <module>
INTERNALERROR>     from twisted.internet import error, tcp, udp
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/internet/tcp.py", line 38, in <module>
INTERNALERROR>     from twisted.internet._newtls import (
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/internet/_newtls.py", line 18, in <module>
INTERNALERROR>     from twisted.protocols.tls import TLSMemoryBIOFactory, TLSMemoryBIOProtocol
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/twisted/protocols/tls.py", line 42, in <module>
INTERNALERROR>     from OpenSSL.SSL import Connection, Error, SysCallError, WantReadError, ZeroReturnError
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/OpenSSL/__init__.py", line 8, in <module>
INTERNALERROR>     from OpenSSL import SSL, crypto
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/OpenSSL/SSL.py", line 9, in <module>
INTERNALERROR>     from OpenSSL._util import (
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/OpenSSL/_util.py", line 6, in <module>
INTERNALERROR>     from cryptography.hazmat.bindings.openssl.binding import Binding
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 167, in <module>
INTERNALERROR>     Binding.init_static_locks()
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 134, in init_static_locks
INTERNALERROR>     cls._ensure_ffi_initialized()
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 123, in _ensure_ffi_initialized
INTERNALERROR>     _legacy_provider_error(cls._legacy_provider_loaded)
INTERNALERROR>   File "/usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 43, in _legacy_provider_error
INTERNALERROR>     raise RuntimeError(
INTERNALERROR> RuntimeError: OpenSSL 3.0's legacy provider failed to load. This is a fatal error by default, but cryptography supports running without legacy algorithms by setting the environment variable CRYPTOGRAPHY_OPENSSL_NO_LEGACY. If you did not expect this error, you have likely made a mistake with your OpenSSL configuration.

For reference:

# uname -apKU
FreeBSD CA78C-WDK23-ZFS 15.0-CURRENT FreeBSD 15.0-CURRENT aarch64 1500000 #13 main-n265027-2f06449d6429-dirty: Fri Aug 25 09:20:31 PDT 2023     root@CA78C-WDK23-ZFS:/usr/obj/BUILDs/main-CA78C-nodbg-clang/usr/main-src/arm64.aarch64/sys/GENERIC-NODBG-CA78C arm64 aarch64 1500000 1500000

# ~/fbsd-based-on-what-commit.sh -C /usr/ports/
8f7f59bbc250 (HEAD -> main, freebsd/main, freebsd/HEAD) sysutils/bmd-plugin-hookcmd: add new ports.
Author:     Vanilla I. Shu <vanilla@FreeBSD.org>
Commit:     Vanilla I. Shu <vanilla@FreeBSD.org>
CommitDate: 2023-09-01 02:54:14 +0000
branch: main
merge-base: 8f7f59bbc2504672483c7840638c7fc171e1b9f5
merge-base: CommitDate: 2023-09-01 02:54:14 +0000
n632086 (--first-parent --count for merge-base)
Comment 1 Mark Millard 2023-09-02 01:13:49 UTC
(In reply to Mark Millard from comment #0)

Note: I normally try to submit based on snapshot builds
and packages from the servers. At this point that
combination is not available for me to try. So,
unfortunately, this report is currently just based
on my personal builds.

If it ends up being that others can not replicate the
behaviors, my personal build/install context would be
a question.

But I figured that, with stable/14 and main being so
close still, early reporting was better than waiting.
Comment 2 Mark Millard 2023-09-02 02:23:37 UTC
(In reply to Mark Millard from comment #1)

Looks like the code in question is:

    @classmethod
    def _ensure_ffi_initialized(cls) -> None:
        with cls._init_lock:
            if not cls._lib_loaded:
                cls.lib = build_conditional_library(
                    _openssl.lib, CONDITIONAL_NAMES
                )
                cls._lib_loaded = True
                # As of OpenSSL 3.0.0 we must register a legacy cipher provider
                # to get RC2 (needed for junk asymmetric private key
                # serialization), RC4, Blowfish, IDEA, SEED, etc. These things
                # are ugly legacy, but we aren't going to get rid of them
                # any time soon.
                if cls.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER:
                    if not os.environ.get("CRYPTOGRAPHY_OPENSSL_NO_LEGACY"):
                        cls._legacy_provider = cls.lib.OSSL_PROVIDER_load(
                            cls.ffi.NULL, b"legacy"
                        )
                        cls._legacy_provider_loaded = (
                            cls._legacy_provider != cls.ffi.NULL
                        )
                        _legacy_provider_error(cls._legacy_provider_loaded)

So cls.lib.OSSL_PROVIDER_load(cls.ffi.NULL, b"legacy") is what did
not work overall.

(I'm no phython or python library expert.)
Comment 3 Mark Millard 2023-09-02 07:04:20 UTC
(In reply to Mark Millard from comment #2)

A gdb bsed session showed for

116	    ptr = dlopen(filename, flags);
117	    if (ptr == NULL) {
118	        ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
119	                       "filename(%s): %s", filename, dlerror());

from:

#0  dlfcn_load (dso=0x41039fa0) at /usr/main-src/crypto/openssl/crypto/dso/dso_dlfcn.c:109
#1  0x00000000432bd910 in DSO_load (dso=0x41039fa0, filename=<optimized out>, filename@entry=0x411a5f40 "/usr/lib/ossl-modules/legacy.so", meth=<optimized out>, flags=<optimized out>, 
    flags@entry=-67840) at /usr/main-src/crypto/openssl/crypto/dso/dso_lib.c:151
#2  0x0000000043238fb4 in provider_init (prov=0x411b51c0) at /usr/main-src/crypto/openssl/crypto/provider_core.c:900
#3  provider_activate (prov=prov@entry=0x411b51c0, lock=0, lock@entry=1, upcalls=1) at /usr/main-src/crypto/openssl/crypto/provider_core.c:1128
#4  0x00000000432389c8 in ossl_provider_activate (prov=0x411b51c0, upcalls=258, upcalls@entry=1, aschild=aschild@entry=-67680) at /usr/main-src/crypto/openssl/crypto/provider_core.c:1257
#5  0x0000000043236a14 in OSSL_PROVIDER_try_load (libctx=0x0, name=0x43cbb9e0 "legacy", retain_fallbacks=0, retain_fallbacks@entry=-67616) at /usr/main-src/crypto/openssl/crypto/provider.c:31
#6  0x0000000043236ad4 in OSSL_PROVIDER_load (libctx=<optimized out>, name=<optimized out>) at /usr/main-src/crypto/openssl/crypto/provider.c:56
#7  0x00000000441d9170 in _cffi_f_OSSL_PROVIDER_load (self=<optimized out>, args=<optimized out>)
. . .

that:

(gdb) n
116	    ptr = dlopen(filename, flags);
(gdb) n
117	    if (ptr == NULL) {
(gdb) print ptr
$53 = (void *) 0x0
(gdb) n
118	        ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
(gdb) print filename
$54 = 0x411a5f80 "/usr/lib/ossl-modules/legacy.so"
(gdb) s
ERR_new () at /usr/main-src/crypto/openssl/crypto/err/err_blocks.c:20
20	    es = ossl_err_get_state_int();
(gdb) n
21	    if (es == NULL)
(gdb) n
25	    err_get_slot(es);
(gdb) n
26	    err_clear(es, es->top, 0);
(gdb) n
27	}
(gdb) n
dlfcn_load (dso=0x41039fa0) at /usr/main-src/crypto/openssl/crypto/dso/dso_dlfcn.c:119
119	                       "filename(%s): %s", filename, dlerror());
(gdb) n
118	        ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
(gdb) s
ERR_set_error (lib=37, reason=103, fmt=0x4315a088 "filename(%s): %s") at /usr/main-src/crypto/openssl/crypto/err/err_blocks.c:44
44	    va_start(args, fmt);
(gdb) n
45	    ERR_vset_error(lib, reason, fmt, args);
(gdb) n
44	    va_start(args, fmt);
(gdb) n
45	    ERR_vset_error(lib, reason, fmt, args);
(gdb) n
47	}
(gdb) n
dlfcn_load (dso=0x41039fa0) at /usr/main-src/crypto/openssl/crypto/dso/dso_dlfcn.c:136
136	    OPENSSL_free(filename);

A rerun looking in dlerror shows:

(gdb) print curthread->dlerror_msg
$56 = "/usr/lib/ossl-modules/legacy.so: Undefined symbol \"MD4_Update\"", '\000' <repeats 449 times>
Comment 4 Mark Millard 2023-09-02 07:45:10 UTC
(In reply to Mark Millard from comment #3)

In an armv7 chroot on aarch64 I see the same error message:

(gdb) n
207	in /usr/main-src/lib/libthr/thread/thr_rtld.c
(gdb) print curthread->dlerror_msg
$1 = "/usr/lib/ossl-modules/legacy.so: Undefined symbol \"MD4_Update\"", '\000' <repeats 449 times>
(gdb) bt
#0  _thr_dlerror_loc () at /usr/main-src/lib/libthr/thread/thr_rtld.c:207
#1  0x420ce65c in dlfcn_load (dso=0x40a477b0) at /usr/main-src/crypto/openssl/crypto/dso/dso_dlfcn.c:119
#2  0x420cf1c8 in DSO_load (dso=0x40a477b0, filename=<optimized out>, filename@entry=0x40a15380 "/usr/lib/ossl-modules/legacy.so", meth=<optimized out>, flags=<optimized out>)
    at /usr/main-src/crypto/openssl/crypto/dso/dso_lib.c:151
#3  0x42044838 in provider_init (prov=0x40a320e0) at /usr/main-src/crypto/openssl/crypto/provider_core.c:900
#4  provider_activate (prov=prov@entry=0x40a320e0, lock=0, upcalls=1) at /usr/main-src/crypto/openssl/crypto/provider_core.c:1128
#5  0x420441bc in ossl_provider_activate (prov=0x40a320e0, upcalls=0, aschild=<optimized out>) at /usr/main-src/crypto/openssl/crypto/provider_core.c:1257
#6  0x420420dc in OSSL_PROVIDER_try_load (libctx=0x0, name=0x429144b0 "legacy", retain_fallbacks=0) at /usr/main-src/crypto/openssl/crypto/provider.c:31
#7  0x420421b4 in OSSL_PROVIDER_load (libctx=<optimized out>, name=<optimized out>) at /usr/main-src/crypto/openssl/crypto/provider.c:56
#8  0x42b6dac8 in _cffi_f_OSSL_PROVIDER_load (self=<optimized out>, args=<optimized out>)
    at /wrkdirs/usr/ports/security/py-cryptography/work-py39/cryptography-41.0.3/src/rust/target/release/build/cryptography-cffi-d217061ce7ef51ba/out/_openssl.c:16595
. . .
Comment 5 Mark Millard 2023-09-02 15:58:47 UTC
(In reply to Mark Millard from comment #3)

Comparing amd64 vs. aarch64 dlopen usage there is loading of
.../cryptography/hazmat/bindings/_rust.abi3.so :

aarch64:

[Detaching after fork from child process 4088]

Breakpoint 1.1, dlopen (name=name@entry=0x43c37620 "libc.so.7", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 1.1, dlopen (name=name@entry=0x43cc50d0 "/usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 1.1, dlopen (name=name@entry=0x43cc3440 "/usr/local/lib/python3.9/site-packages/_cffi_backend.cpython-39.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 1.1, dlopen (name=name@entry=0x411a5f80 "/usr/lib/ossl-modules/legacy.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.
INTERNALERROR> Traceback (most recent call last):
. . .

But for amd64 there is not:

[Detaching after fork from child process 7327]

Breakpoint 2.1, dlopen (name=name@entry=0x8025f1bc0 "libc.so.7", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.
========================================================================================= test session starts ==========================================================================================
platform freebsd15 -- Python 3.9.17, pytest-7.4.0, pluggy-1.2.0 -- /usr/local/bin/python3.9
rootdir: /usr
collecting ... 
Breakpoint 2.1, dlopen (name=name@entry=0x8026d1710 "/usr/local/lib/python3.9/lib-dynload/_pickle.cpython-39.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 2.1, dlopen (name=name@entry=0x8026d48a0 "/usr/local/lib/python3.9/lib-dynload/_multiprocessing.cpython-39.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.
collected 1 item                                                                                                                                                                                       

../../../tests/examples/test_examples.py::TestExampleSimple::test_with_cleanup TEST BODY
PASSED

========================================================================================== 1 passed in 7.48s ===========================================================================================
[Inferior 1 (process 7326) exited normally]
Comment 6 Mark Millard 2023-09-02 16:26:51 UTC
(In reply to Mark Millard from comment #5)

amd64 did not have:

devel/py-pytest-twisted
devel/py-twisted
net/py-dpkt
security/nist-kat
security/openvpn

installed.

After adding those amd64 fails like aarch64: again the use
of .../cryptography/hazmat/bindings/_rust.abi3.so leads to the problem.

[Detaching after fork from child process 98729]

Breakpoint 1.1, dlopen (name=name@entry=0x803239710 "libc.so.7", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 1.1, dlopen (name=name@entry=0x8032c80d0 "/usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 1.1, dlopen (name=name@entry=0x8032c7440 "/usr/local/lib/python3.9/site-packages/_cffi_backend.cpython-39.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.

Breakpoint 1.1, dlopen (name=name@entry=0x80219d080 "/usr/lib/ossl-modules/legacy.so", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
3662		return (rtld_dlopen(name, -1, mode));
(gdb) c
Continuing.
INTERNALERROR> Traceback (most recent call last):
. . .
Comment 7 Mark Millard 2023-09-02 21:35:55 UTC
Just before the failing dlopen of:

/usr/lib/ossl-modules/legacy.so

things look like:

(gdb) info functions MD4.*
All functions matching regular expression "MD4.*":

File /usr/main-src/crypto/openssl/crypto/md4/md4_dgst.c:
29:	int MD4_Init(MD4_CTX *);

File /usr/main-src/crypto/openssl/crypto/md4/md4_one.c:
25:	unsigned char *MD4(const unsigned char *, size_t, unsigned char *);

File /usr/main-src/crypto/openssl/include/crypto/md32_common.h:
191:	int MD4_Final(unsigned char *, MD4_CTX *);
186:	void MD4_Transform(MD4_CTX *, const unsigned char *);
128:	int MD4_Update(MD4_CTX *, const void *, size_t);

File /usr/main-src/lib/libmd/md4c.c:
171:	void __MD4Final(unsigned char *, MD4_CTX *);
95:	void __MD4Init(MD4_CTX *);
149:	void __MD4Pad(MD4_CTX *);
112:	void __MD4Update(MD4_CTX *, const void *, unsigned int);
171:	void _libmd_MD4Final(unsigned char *, MD4_CTX *);
95:	void _libmd_MD4Init(MD4_CTX *);
149:	void _libmd_MD4Pad(MD4_CTX *);
112:	void _libmd_MD4Update(MD4_CTX *, const void *, unsigned int);
187:	static void MD4Transform(UINT4 *, const unsigned char *);

File md4hl.c:
115:	char *_libmd_MD4Data(const void *, unsigned int, char *);
26:	char *_libmd_MD4End(MD4_CTX *, char *);
46:	char *_libmd_MD4Fd(int, char *);
52:	char *_libmd_MD4FdChunk(int, char *, off_t, off_t);
93:	char *_libmd_MD4File(const char *, char *);
99:	char *_libmd_MD4FileChunk(const char *, char *, off_t, off_t);

Non-debugging symbols:
0x0000000040654360  __MD4Init@plt
0x0000000040654370  __MD4Update@plt
0x0000000040654380  __MD4Final@plt
0x0000000040654390  __MD4Pad@plt
0x0000000041e59650  _libmd_MD4Init@plt
0x0000000041e59660  _libmd_MD4Update@plt
0x0000000041e59670  _libmd_MD4Pad@plt
0x0000000041e59680  _libmd_MD4Final@plt
0x0000000041e59710  _libmd_MD4FdChunk@plt
0x00000000434416b0  MD4_Init@plt
0x00000000434416c0  MD4_Update@plt
0x00000000434416d0  MD4_Final@plt
(gdb) info dll
From                To                  Syms Read   Shared Object Library
0x0000000040245e20  0x000000004025b9a4  Yes         /libexec/ld-elf.so.1
0x00000000403f1780  0x00000000405b3c78  Yes         /usr/local/lib/libpython3.9.so.1.0
0x000000004064c040  0x0000000040654210  Yes         /lib/libcrypt.so.5
0x0000000040689720  0x000000004069ffc4  Yes         /usr/local/lib/libintl.so.8
0x00000000406d3ab0  0x00000000406d3cd8  Yes         /usr/lib/libdl.so.1
0x000000004070bae0  0x0000000040715b54  Yes         /lib/libutil.so.9
0x000000004075fc60  0x0000000040787fa8  Yes         /lib/libm.so.5
0x00000000407c6400  0x00000000407d96f8  Yes         /lib/libthr.so.3
0x0000000040899540  0x00000000409cf7dc  Yes         /lib/libc.so.7
0x0000000040ca7ba0  0x0000000040ca8868  Yes         /usr/local/lib/python3.9/lib-dynload/_heapq.cpython-39.so
0x0000000040cd9d30  0x0000000040cd9ff4  Yes         /usr/local/lib/python3.9/lib-dynload/_opcode.cpython-39.so
0x0000000040d0eca0  0x0000000040d11460  Yes         /usr/local/lib/python3.9/lib-dynload/_csv.cpython-39.so
0x0000000040d46180  0x0000000040d48ef4  Yes         /usr/local/lib/python3.9/lib-dynload/binascii.cpython-39.so
0x0000000040d80180  0x0000000040d8f5a8  Yes         /lib/libz.so.6
0x0000000040dc3e20  0x0000000040dc6ed0  Yes         /usr/local/lib/python3.9/lib-dynload/zlib.cpython-39.so
0x0000000041d34480  0x0000000041d3534c  Yes         /usr/local/lib/python3.9/lib-dynload/_bz2.cpython-39.so
0x0000000041d68aa0  0x0000000041d7684c  Yes         /usr/lib/libbz2.so.4
0x0000000041dac180  0x0000000041dae7f0  Yes         /usr/local/lib/python3.9/lib-dynload/_lzma.cpython-39.so
0x0000000041df0040  0x0000000041e0c6bc  Yes         /usr/lib/liblzma.so.5
0x0000000041e46020  0x0000000041e595ec  Yes         /lib/libmd.so.6
0x0000000041e8cba0  0x0000000041e8d464  Yes         /usr/local/lib/python3.9/lib-dynload/grp.cpython-39.so
0x0000000041ec3a80  0x0000000041ec78f4  Yes         /usr/local/lib/python3.9/lib-dynload/_struct.cpython-39.so
0x0000000041f3b7a0  0x0000000041f3c26c  Yes         /usr/local/lib/python3.9/lib-dynload/_bisect.cpython-39.so
0x0000000042076dc0  0x000000004207a1c8  Yes         /usr/local/lib/python3.9/lib-dynload/unicodedata.cpython-39.so
0x00000000420ee280  0x00000000420ef790  Yes         /usr/local/lib/python3.9/lib-dynload/_posixsubprocess.cpython-39.so
0x0000000042124d00  0x0000000042127090  Yes         /usr/local/lib/python3.9/lib-dynload/select.cpython-39.so
0x000000004219e600  0x00000000421a3210  Yes         /usr/local/lib/python3.9/lib-dynload/math.cpython-39.so
0x00000000421d58c0  0x00000000421d59e4  Yes         /usr/local/lib/python3.9/lib-dynload/_uuid.cpython-39.so
0x00000000423c9440  0x00000000423cdc4c  Yes         /usr/local/lib/python3.9/lib-dynload/_json.cpython-39.so
0x0000000042780be0  0x0000000042781b34  Yes         /usr/local/lib/python3.9/lib-dynload/_random.cpython-39.so
0x00000000427b4720  0x00000000427b76c0  Yes         /usr/local/lib/python3.9/lib-dynload/_sha512.cpython-39.so
0x0000000042879f80  0x000000004288ffbc  Yes         /usr/local/lib/python3.9/lib-dynload/_decimal.cpython-39.so
0x00000000428d15e0  0x00000000428f4794  Yes         /usr/local/lib/libmpdec.so.3
0x0000000042a2ef60  0x0000000042a3bb48  Yes         /usr/local/lib/python3.9/lib-dynload/_datetime.cpython-39.so
0x0000000042af5340  0x0000000042afda2c  Yes         /usr/local/lib/python3.9/lib-dynload/_elementtree.cpython-39.so
0x0000000042b3cae0  0x0000000042b5f3f0  Yes         /usr/local/lib/python3.9/lib-dynload/pyexpat.cpython-39.so
0x0000000042c20520  0x0000000042c29544  Yes         /usr/local/lib/python3.9/site-packages/greenlet/_greenlet.cpython-39.so
0x0000000042ce0e60  0x0000000042d5780c  Yes         /lib/libc++.so.1
0x0000000042da2ce0  0x0000000042daec48  Yes         /lib/libcxxrt.so.1
0x0000000042deb9c0  0x0000000042df8a60  Yes         /lib/libgcc_s.so.1
0x0000000042ea5100  0x0000000042eac764  Yes         /usr/local/lib/python3.9/lib-dynload/_socket.cpython-39.so
0x0000000042f25700  0x0000000042f2a524  Yes         /usr/local/lib/python3.9/lib-dynload/array.cpython-39.so
0x0000000042f7aa80  0x0000000042f844c0  Yes         /usr/local/lib/python3.9/lib-dynload/_ssl.cpython-39.so
0x0000000042ffc0c0  0x000000004304fcf8  Yes         /usr/lib/libssl.so.30
0x0000000043229000  0x0000000043439878  Yes         /lib/libcrypto.so.30
0x000000004358f8f0  0x000000004358fa40  Yes         /usr/local/lib/python3.9/lib-dynload/_contextvars.cpython-39.so
0x00000000435c7600  0x00000000435cd004  Yes         /usr/local/lib/python3.9/lib-dynload/_asyncio.cpython-39.so
0x00000000437836a0  0x00000000437868d8  Yes         /usr/local/lib/python3.9/site-packages/zope/interface/_zope_interface_coptimizations.cpython-39.so
0x0000000043843020  0x0000000043852c74  Yes         /usr/local/lib/python3.9/lib-dynload/_pickle.cpython-39.so
0x000000004394b660  0x000000004394f47c  Yes         /usr/local/lib/python3.9/lib-dynload/_hashlib.cpython-39.so
0x0000000043984a20  0x000000004398a888  Yes         /usr/local/lib/python3.9/lib-dynload/_blake2.cpython-39.so
0x0000000043a7e280  0x0000000043a7efa8  Yes         /usr/local/lib/python3.9/lib-dynload/fcntl.cpython-39.so
0x0000000043b31ce0  0x0000000043b325a4  Yes         /usr/local/lib/python3.9/lib-dynload/_queue.cpython-39.so
0x0000000043baea40  0x0000000043bbd35c  Yes         /usr/local/lib/python3.9/lib-dynload/_ctypes.cpython-39.so
0x0000000043bf43a0  0x0000000043bf8afc  Yes         /usr/local/lib/libffi.so.8
0x0000000044114c80  0x00000000442a1ba8  Yes         /usr/local/lib/python3.9/site-packages/cryptography/hazmat/bindings/_rust.abi3.so
0x0000000044308540  0x000000004431efdc  Yes         /usr/local/lib/python3.9/site-packages/_cffi_backend.cpython-39.so
(gdb) info addr MD4_Update
Symbol "MD4_Update" is a function at address 0x4336a880.

(So, in the /lib/libcrypto.so.30 address range.)
Comment 8 Mark Millard 2023-09-03 00:52:03 UTC
Looking at the dlopen of /lib/libcrypto.so.30 shows mode=2, i.e.:

mode=(RTLD_NOW|RTLD_LOCAL)

The RTLD_LOCAL means that MD4_Update and the like are not
available for the later dlopen of /usr/lib/ossl-modules/legacy.so
to bind to. 

The backtrace at that point looks like:

(gdb) bt
#0  dlopen (name=name@entry=0x410480c0 "/lib/libcrypto.so.30", mode=2) at /usr/main-src/libexec/rtld-elf/rtld.c:3662
#1  0x00000000432bce88 in dlfcn_load (dso=0x41039000) at /usr/main-src/crypto/openssl/crypto/dso/dso_dlfcn.c:116
#2  0x00000000432bd910 in DSO_load (dso=0x0, dso@entry=0xffffffff5f80, filename=<optimized out>, filename@entry=0x41048020 "/lib/libcrypto.so.30", meth=<optimized out>, flags=<optimized out>, 
    flags@entry=4) at /usr/main-src/crypto/openssl/crypto/dso/dso_lib.c:151
#3  0x00000000432bdeec in DSO_dsobyaddr (addr=0x434bca40, flags=flags@entry=4) at /usr/main-src/crypto/openssl/crypto/dso/dso_lib.c:323
#4  0x000000004322e280 in ossl_init_load_crypto_nodelete () at /usr/main-src/crypto/openssl/crypto/init.c:162
#5  ossl_init_load_crypto_nodelete_ossl_ () at /usr/main-src/crypto/openssl/crypto/init.c:128
#6  0x00000000407d123c in _thr_once (once_control=0x434bcaa0, init_routine=0x4322e240 <ossl_init_load_crypto_nodelete_ossl_>) at /usr/main-src/lib/libthr/thread/thr_once.c:96
#7  0x000000004323b79c in CRYPTO_THREAD_run_once (once=0x410480c0, init=0x2) at /usr/main-src/crypto/openssl/crypto/threads_pthread.c:156
#8  0x000000004322de28 in OPENSSL_init_crypto (opts=opts@entry=64, settings=0x0, settings@entry=0xffffffff60a0) at /usr/main-src/crypto/openssl/crypto/init.c:539
#9  0x0000000043378b08 in OBJ_obj2nid (a=a@entry=0xffffffff60e0) at /usr/main-src/crypto/openssl/crypto/objects/obj_dat.c:340
#10 0x0000000043245748 in ossl_c2i_ASN1_OBJECT (a=a@entry=0x0, pp=pp@entry=0xffffffff6170, len=8) at /usr/main-src/crypto/openssl/crypto/asn1/a_object.c:272
#11 0x0000000043245658 in d2i_ASN1_OBJECT (a=0x0, a@entry=0xffffffff61a0, pp=pp@entry=0xffffffff61a8, length=<optimized out>, length@entry=10)
    at /usr/main-src/crypto/openssl/crypto/asn1/a_object.c:235
#12 0x0000000043378c74 in OBJ_txt2obj (s=s@entry=0x42ed2920 "1.3.6.1.5.5.7.3.1", no_name=<optimized out>) at /usr/main-src/crypto/openssl/crypto/objects/obj_dat.c:407
#13 0x0000000042f84148 in _ssl_txt2obj_impl (txt=0x42ed2920 "1.3.6.1.5.5.7.3.1", name=<optimized out>, module=<optimized out>)
    at /wrkdirs/usr/ports/lang/python39/work/Python-3.9.17/Modules/_ssl.c:5542
#14 _ssl_txt2obj (module=<optimized out>, args=0xffffffff6238, nargs=<optimized out>, kwnames=<optimized out>) at Modules/clinic/_ssl.c.h:1312
#15 0x0000000040473f48 in cfunction_vectorcall_FASTCALL_KEYWORDS (func=0x42ee7220, args=0x42ba3ae8, nargsf=9223372036854775809, kwnames=0x42e6f7c0) at Objects/methodobject.c:446
#16 0x0000000040501780 in call_function (tstate=tstate@entry=0x4104c780, pp_stack=pp_stack@entry=0xffffffff63b0, oparg=<optimized out>, kwnames=kwnames@entry=0x42e6f7c0)
    at ./Include/cpython/abstract.h:119
#17 0x00000000404feb8c in _PyEval_EvalFrameDefault (tstate=<optimized out>, f=0x42ba3950, throwflag=<optimized out>) at Python/ceval.c:3537
#18 0x00000000405023c0 in _PyEval_EvalFrame (tstate=0x4104c780, f=0x42ba3950, throwflag=0) at ./Include/internal/pycore_ceval.h:40
#19 _PyEval_EvalCode (tstate=0x4104c780, _co=0x42e80920, globals=<optimized out>, locals=locals@entry=0xffffffff6540, args=<optimized out>, argcount=<optimized out>, kwnames=0x0, kwargs=0x43517668, 
    kwcount=0, kwstep=1, defs=0x0, defcount=0, kwdefs=0x0, closure=0x435259a0, name=0x41622570, qualname=0x42ed2760) at Python/ceval.c:4329
#20 0x0000000040433570 in _PyFunction_Vectorcall (func=<optimized out>, stack=0x14, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/call.c:396
#21 0x00000000404fee00 in do_call_core (tstate=0x4104c780, func=0x4352d820, callargs=0x43517640, kwdict=0x0) at Python/ceval.c:4673
#22 _PyEval_EvalFrameDefault (tstate=<optimized out>, f=0x411ee810, throwflag=<optimized out>) at Python/ceval.c:3582
. . .

The mode value comes from dlfcn_load in:

/usr/main-src/crypto/openssl/crypto/dso/dso_dlfcn.c

static int dlfcn_load(DSO *dso)
{
    void *ptr = NULL;
    /* See applicable comments in dso_dl.c */
    char *filename = DSO_convert_filename(dso, NULL);
    int flags = DLOPEN_FLAG;
    int saveerrno = get_last_sys_error();

    if (filename == NULL) {
        ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
        goto err;
    }
# ifdef RTLD_GLOBAL
    if (dso->flags & DSO_FLAG_GLOBAL_SYMBOLS)
        flags |= RTLD_GLOBAL;
# endif
# ifdef _AIX
    if (filename[strlen(filename) - 1] == ')')
        flags |= RTLD_MEMBER;
# endif
    ptr = dlopen(filename, flags);
. . .

So far I've not found that would lead to

dso->flags & DSO_FLAG_GLOBAL_SYMBOLS

being non-zero.

Thus the failures would result: /usr/lib/ossl-modules/legacy.so use
is designed for RTLD_GLOBAL use for /lib/libcrypto.so.30 .
Comment 9 Mark Millard 2023-09-03 01:49:32 UTC
The following crude patch leads to kyua's python use working
for examples/test_examples.py :

# git -C /usr/main-src/ diff crypto/openssl/crypto/init.c
diff --git a/crypto/openssl/crypto/init.c b/crypto/openssl/crypto/init.c
index cacf637c89f8..77f693fcfa05 100644
--- a/crypto/openssl/crypto/init.c
+++ b/crypto/openssl/crypto/init.c
@@ -159,7 +159,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
         if (!err_shelve_state(&err))
             return 0;
 
-        dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
+        dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE|DSO_FLAG_GLOBAL_SYMBOLS);
         /*
          * In case of No!, it is uncertain our exit()-handlers can still be
          * called. After dlclose() the whole library might have been unloaded
Comment 10 Pierre Pronchery 2023-09-05 12:20:22 UTC
Created attachment 244659 [details]
0001-libcrypto-try-to-fix-the-legacy-provider-on-aarch64.patch

Can you try this on a aarch64 host?

One way to test if it works:

# echo test | openssl md4 -provider legacy
MD4(stdin)= 36d729ab4ff7260da6fb010ef5747bb3
Comment 11 Pierre Pronchery 2023-09-05 13:08:29 UTC
(In reply to Pierre Pronchery from comment #10)

In hindsight Mark's patch from comment #9 looks right, unlike mine.
Comment 12 David Horn 2023-09-05 13:15:51 UTC
See Also (Comment 17):  https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=273505#c17

The patch from Mark Millard also solves the problem with base openssl 3 on stable/14 amd64 that I was having with security/py-cryptography (and friends) unable to load legacy provider.

Please review and commit to stable/14 and -CURRENT when possible.  I will re-test all of my failcase ports once committed to stable/14.

-_Thanks!
Comment 13 Mark Millard 2023-09-06 03:09:05 UTC
(In reply to Mark Millard from comment #9)

I'll note that I consider my patch as crude, in that I've
no clue if there are upstream or downstream compatibility
criteria to be met. The change might need some #if...#endif
logic to be more selective about when it is used vs. not,
for example.

There is also the below from src/crypto/README:

QUOTE
This directory is for the EXACT same use as src/contrib, except it
holds crypto sources.  In other words, this holds raw sources obtained
from various third party vendors, with FreeBSD patches applied.  No
compilation is done from this directory, it is all done from the
src/secure directory.  The separation between src/contrib and src/crypto
is the result of an old USA law, which made these sources export
controlled, so they had to be kept separate.
END QUOTE

So there might be even more about handling the source code changes
that I simply am unaware of.
Comment 14 Dimitry Andric freebsd_committer freebsd_triage 2023-09-06 12:36:26 UTC
Related: bug 273528 (I believe this has the same root cause)
Comment 15 Mark Millard 2023-09-06 18:59:57 UTC
It does not look like some variant of the patch will make it
into later-today's 15 snapshot and tomorrow's 14 snapshot.

And it is only a couple of days until releng/14.0 by the
current schedule. (With the new openzfs imports looking
successful at removing the deadlocks and data corruptions,
I'd guess that the schedule likely will hold.) So, likely
the -> stable/14 -> releng/14.0 sequence will be separate
steps after releng/14.0 is created.
Comment 16 Enji Cooper freebsd_committer freebsd_triage 2023-09-07 01:05:36 UTC
(In reply to Dimitry Andric from comment #14)

It isn’t. The problem in this bug is that the armv7 isn’t being compiled/linked in to libcrypto and some CFLAGS in the Makefile are set, stating that the ASM implementations should be used (I ran into a similar problem with clang 6.x and amd64 backporting OpenSSL 3 for $work.
Comment 17 Mark Millard 2023-09-07 12:58:14 UTC
(In reply to Enji Cooper from comment #16)

The problem this submital reports exists without armv7 being
involved (just an aarch64 context, for example). It  also
exists for armv7.

I am confused by your note. Can you explain how you expect
RTLD_NOW|RTLD_LOCAL to work for dlopen of /lib/libcrypto.so.30
when the later, separate dlopen of /usr/lib/ossl-modules/legacy.so
occurs and needs access to what is implemented in
/lib/libcrypto.so.30 ? I.e., what specific changes would make the
RTLD_LOCAL appropriate?
Comment 18 David Horn 2023-09-09 13:57:16 UTC
@emaste @jkim @lwhsu:

Can we mark this bug as blocks 14.0-RELEASE via Blocks: 271607

This is multi-architecture impactful OpenSSL3 base issue that breaks py-cryptography.  Assignee likely needs and update as well.
Comment 19 Mark Millard 2023-09-09 18:56:18 UTC
(In reply to David Horn from comment #18)

I'll note that kyua uses various ports if they are installed
and some of those ports fail in their use by kyua because of
this problem.

In other words: this issue ends up limiting system testing
via kyua, including for tier 1 architectures.

That makes it more likely to be considered a blocking issue,
or so I would expect.
Comment 20 Mark Millard 2023-09-09 23:45:33 UTC
I adjusted the "Component" to not be just "arm" (as amd64 is verified
to have the problem, for example), picking "bin" (a.k.a. "All other
sources").

Version is messier as all the following would have the issue:

releng/14.0 (no selection matches yet)
stable/14 (14.0-STABLE)
main (15.0-CURRENT and CURRENT both match now?)

I've left it at CURRENT for now.
Comment 21 Li-Wen Hsu freebsd_committer freebsd_triage 2023-09-11 21:46:06 UTC
I also checked the legacy.so from Debian and Ubuntu packages, there is also no MD4_Update, but only MD4_Init and MD4_Final.

So I think we should find out who is try to resolve MD4_Update symbol?
Comment 22 Mark Millard 2023-09-11 22:45:01 UTC
(In reply to Li-Wen Hsu from comment #21)

Which are you saying for the linux examples analogous to:
doing a dlopen of /usr/lib/ossl-modules/legacy.so . . .

A) There is no reference to MD4_Update
   in the equivalent of /usr/lib/ossl-modules/legacy.so ?

B) There is no definition of MD4_Update
   in the equivalent of /usr/lib/ossl-modules/legacy.so ?

C) Both (A) and (B).

For FreeBSD:

# nm /usr/lib/ossl-modules/legacy.so | grep MD4
                 U MD4_Final
                 U MD4_Init
                 U MD4_Update

So it is the combination: (B) but not (A)

I will note that more (non MD4) names could have the type of
issue. The dlopen failure only would report the first missing
symbol before giving up: The general type of problem may repeat.
Comment 23 Mark Millard 2023-09-11 22:52:31 UTC
(In reply to Li-Wen Hsu from comment #21)

FYI:

# objdump --dynamic-reloc /usr/lib/ossl-modules/legacy.so | grep MD4
000000000003c7d8 R_AARCH64_ABS64          MD4_Update
000000000004d938 R_AARCH64_JUMP_SLOT      MD4_Final
000000000004d940 R_AARCH64_JUMP_SLOT      MD4_Init
Comment 24 Mark Millard 2023-09-11 23:07:24 UTC
(In reply to Mark Millard from comment #23)

FYI, suggesting some other names that may be similar in
what happens for them (the R_AARCH64_ABS64 ones):

# objdump --dynamic-reloc /usr/lib/ossl-modules/legacy.so | grep _Update
000000000003c7d8 R_AARCH64_ABS64          MD4_Update
000000000003c868 R_AARCH64_ABS64          WHIRLPOOL_Update
000000000003c8f8 R_AARCH64_ABS64          RIPEMD160_Update
000000000004d8d8 R_AARCH64_JUMP_SLOT      MD5_Update

Other suffixes than _Update might also prove interesting.
Comment 25 Mark Millard 2023-09-11 23:20:55 UTC
(In reply to Mark Millard from comment #24)

The .meta file for legacy.so.full shows:

CMD cc -target aarch64-unknown-freebsd15.0 --sysroot=/usr/obj/BUILDs/main-CA72-nodbg-clang/usr/main-src/arm64.aarch64/tmp -B/usr/obj/BUILDs/main-CA72-nodbg-clang/usr/main-src/arm64.aarch64/tmp/usr/bin
  -Wl,-zrelro   -fstack-protector-strong -shared -Wl,-x -Wl,--fatal-warnings -Wl,--warn-shared-textrel  -o legacy.so.full -Wl,-soname,legacy.so legacyprov.pico prov_running.pico ciphercommon.pico ciph
ercommon_hw.pico ciphercommon_block.pico ciphercommon_gcm.pico ciphercommon_gcm_hw.pico ciphercommon_ccm.pico ciphercommon_ccm_hw.pico cipher_desx.pico cipher_desx_hw.pico cipher_des.pico cipher_des_h
w.pico cipher_tdes_common.pico cipher_blowfish.pico cipher_blowfish_hw.pico cipher_cast5.pico cipher_cast5_hw.pico cipher_rc2.pico cipher_rc2_hw.pico cipher_rc4.pico cipher_rc4_hw.pico cipher_rc4_hmac
_md5.pico cipher_rc4_hmac_md5_hw.pico cipher_seed.pico cipher_seed_hw.pico digestcommon.pico md4_prov.pico wp_prov.pico ripemd_prov.pico pbkdf1.pico record/tls_pad.pico provider_err.pico provider_ctx.
pico provider_util.pico

Towards the end of that it shows:

md4_prov.pico wp_prov.pico ripemd_prov.pico

which are likely tied to MD4_* WHIRLPOOL_* RIPEMD160_* naming.
Comment 26 Mark Millard 2023-09-12 00:07:17 UTC
(In reply to Mark Millard from comment #25)


FYI on Fedora Linux 38 (Server Edition) :

# objdump --dynamic-reloc /usr/lib64/ossl-modules/legacy.so | grep MD4
000000000003f970 R_AARCH64_ABS64   MD4_Update@OPENSSL_3.0.0
000000000003fd60 R_AARCH64_JUMP_SLOT  MD4_Update@OPENSSL_3.0.0
000000000003fe60 R_AARCH64_JUMP_SLOT  MD4_Final@OPENSSL_3.0.0
000000000003ffa0 R_AARCH64_JUMP_SLOT  MD4_Init@OPENSSL_3.0.0

# objdump --dynamic-reloc /usr/lib64/ossl-modules/legacy.so | grep _Update
000000000003f850 R_AARCH64_ABS64   RIPEMD160_Update@OPENSSL_3.0.0
000000000003f8e0 R_AARCH64_ABS64   WHIRLPOOL_Update@OPENSSL_3.0.0
000000000003f970 R_AARCH64_ABS64   MD4_Update@OPENSSL_3.0.0
000000000003fa00 R_AARCH64_ABS64   MD2_Update@OPENSSL_3.0.0
000000000003fd60 R_AARCH64_JUMP_SLOT  MD4_Update@OPENSSL_3.0.0
000000000003feb8 R_AARCH64_JUMP_SLOT  RIPEMD160_Update@OPENSSL_3.0.0
000000000003ff20 R_AARCH64_JUMP_SLOT  WHIRLPOOL_Update@OPENSSL_3.0.0
000000000003ff68 R_AARCH64_JUMP_SLOT  MD2_Update@OPENSSL_3.0.0
Comment 27 Mark Millard 2023-09-12 00:31:55 UTC
(In reply to Mark Millard from comment #26)

And also on on Fedora Linux 38 (Server Edition) :

# objdump --dynamic-syms /usr/lib64/ossl-modules/legacy.so | grep _Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) RIPEMD160_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) WHIRLPOOL_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD2_Update
Comment 28 Mark Millard 2023-09-12 01:00:28 UTC
(In reply to Mark Millard from comment #27)

openSUSE Tumbleweed (which I was also overdue to update):

# objdump --dynamic-syms /usr/lib64/ossl-modules/legacy.so | grep _Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) RIPEMD160_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) WHIRLPOOL_Update

# objdump --dynamic-reloc /usr/lib64/ossl-modules/legacy.so | grep _Update
000000000002f8d0 R_AARCH64_ABS64   RIPEMD160_Update@OPENSSL_3.0.0
000000000002f960 R_AARCH64_ABS64   WHIRLPOOL_Update@OPENSSL_3.0.0
000000000002f9f0 R_AARCH64_ABS64   MD4_Update@OPENSSL_3.0.0
000000000002fd70 R_AARCH64_JUMP_SLOT  MD4_Update@OPENSSL_3.0.0
000000000002feb8 R_AARCH64_JUMP_SLOT  RIPEMD160_Update@OPENSSL_3.0.0
000000000002ff30 R_AARCH64_JUMP_SLOT  WHIRLPOOL_Update@OPENSSL_3.0.0

# objdump --dynamic-syms /usr/lib64/ossl-modules/legacy.so | grep MD4
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Final
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Init

# objdump --dynamic-reloc /usr/lib64/ossl-modules/legacy.so | grep MD4
000000000002f9f0 R_AARCH64_ABS64   MD4_Update@OPENSSL_3.0.0
000000000002fd70 R_AARCH64_JUMP_SLOT  MD4_Update@OPENSSL_3.0.0
000000000002fe68 R_AARCH64_JUMP_SLOT  MD4_Final@OPENSSL_3.0.0
000000000002ffa8 R_AARCH64_JUMP_SLOT  MD4_Init@OPENSSL_3.0.0
Comment 29 Enji Cooper freebsd_committer freebsd_triage 2023-09-12 18:46:15 UTC
MD4_Update is a legacy OpenSSL symbol which no longer exists in 3.x, as noted in the docs.
```
$ grep -r HASH_UPDATE crypto/openssl/
crypto/openssl/CHANGES.md:   - Avoid size_t integer overflow in HASH_UPDATE (md32_common.h).
crypto/openssl/crypto/md5/md5_local.h:#define HASH_UPDATE             MD5_Update
crypto/openssl/crypto/sm3/sm3_local.h:#define HASH_UPDATE             ossl_sm3_update
crypto/openssl/crypto/md4/md4_local.h:#define HASH_UPDATE             MD4_Update
crypto/openssl/crypto/ripemd/rmd_local.h:#define HASH_UPDATE             RIPEMD160_Update
crypto/openssl/crypto/sha/sha_local.h:#define HASH_UPDATE                     SHA1_Update
crypto/openssl/crypto/sha/sha256.c:#define HASH_UPDATE             SHA256_Update
crypto/openssl/include/crypto/md32_common.h: *      HASH_UPDATE.
crypto/openssl/include/crypto/md32_common.h: * HASH_UPDATE
crypto/openssl/include/crypto/md32_common.h: *      #define HASH_UPDATE             MD5_Update
crypto/openssl/include/crypto/md32_common.h:#ifndef HASH_UPDATE
crypto/openssl/include/crypto/md32_common.h:# error "HASH_UPDATE must be defined!"
crypto/openssl/include/crypto/md32_common.h:int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
crypto/openssl/apps/enc.c:                /* not needed if HASH_UPDATE() is fixed : */
$ grep -r md32_common.h crypto/openssl/
crypto/openssl/providers/fips-sources.checksums:162812058c69f65a824906193057cd3edeabc22f51a4220aea7cb9064379a9b6  include/crypto/md32_common.h
crypto/openssl/providers/fips.module.sources:include/crypto/md32_common.h
crypto/openssl/CHANGES.md:   - Avoid size_t integer overflow in HASH_UPDATE (md32_common.h).
crypto/openssl/crypto/md5/md5_local.h:#include "crypto/md32_common.h"
crypto/openssl/crypto/sm3/sm3_local.h:#include "crypto/md32_common.h"
crypto/openssl/crypto/md4/md4_local.h:#include "crypto/md32_common.h"
crypto/openssl/crypto/ripemd/rmd_local.h:#include "crypto/md32_common.h"
crypto/openssl/crypto/sha/sha512.c: *   implementations, ../md32_common.h;
crypto/openssl/crypto/sha/sha_local.h:#include "crypto/md32_common.h"
crypto/openssl/crypto/sha/sha256.c:#include "crypto/md32_common.h"
crypto/openssl/crypto/sha/sha1dgst.c:/* The implementation is in ../md32_common.h */
$
```
crypto/openssl/include/crypto/md32_common.h defines the implementation: https://github.com/openssl/openssl/blob/ff3d5bc2eadaede933f3a64bbf041253e1b52976/include/crypto/md32_common.h#L128 .

This is defined via md4_dgst.c, which is compiled/linked into libcrypto.

I agree with lwhsu -- we need to understand what libraries are being linked into the application/loaded libraries on aarch64.
Comment 30 Mark Millard 2023-09-12 19:18:33 UTC
(In reply to Enji Cooper from comment #29)

The problem has been demonstated on amd64 via kyua use
with the supporting ports installed. See comment #6 .

The problem is in no way aarch64 or armv7 specific.
Comment 31 Mark Millard 2023-09-12 19:26:53 UTC
(In reply to Mark Millard from comment #30)

In case it is unclear: having the supporting ports around
leads to the dlopen of /usr/lib/ossl-modules/legacy.so .
Absent some of them, no dlopen of /usr/lib/ossl-modules/legacy.so
happens for kyua use.
Comment 32 Mark Millard 2023-09-12 19:33:13 UTC
Looking for th e md4 example:

# grep -r md4_prov /usr/main-src/ 
/usr/main-src/crypto/openssl/providers/implementations/digests/build.info:  SOURCE[$MD4_GOAL]=md4_prov.c
/usr/main-src/secure/lib/libcrypto/modules/legacy/Makefile:SRCS+=	md4_prov.c wp_prov.c ripemd_prov.c
/usr/main-src/secure/lib/libcrypto/Makefile:SRCS+=	md4_prov.c

The other *_prov.c are probably similar.
Comment 33 Mark Millard 2023-09-12 19:40:09 UTC
(In reply to Enji Cooper from comment #29)

THe exact commit that enabled the likes of md4_prov being included was:

https://cgit.freebsd.org/src/commit/?id=87e08018b175e564b6a19ee41bc65af66f55e078

Quoting:

libcrypto: add missing symbols to the legacy provider
OpenSSL 3 supports a modular architecture, allowing different providers
to bring specific implementations of cryptographical algorithms. One
such provider, "legacy", ships with OpenSSL 3 directly, and groups
obsoleted algorithms that can still optionally be used anyway.

The import of OpenSSL 3.0.9 was building this provider incorrectly,
missing symbols required for proper operation.

Sponsored by:	The FreeBSD Foundation
Pull Request:	https://github.com/freebsd/freebsd-src/pull/787
Comment 34 Mark Millard 2023-09-12 20:00:58 UTC
I'll note that I've always listed this as tied to getting
kyua tests to run correctly. In my view, if the kyua test
suite requires any of the optional legacy providers, then
the legacy providers should be present in the build (unless
the test suite is going to be reworked in time for the
release).

But, if the legacy providers are included and things are
handled such that the issue does not block the kyua tests
that involve legacy providers, other things will also be
working outside kyua. So there is a wider interest being
covered as well.
Comment 35 Mark Millard 2023-09-13 09:05:17 UTC
FYI: The ports to have installed for the kyua testsuite to
use are listed at (as things are now):

https://github.com/freebsd/freebsd-ci/blob/master/scripts/build/build-test_image-head.sh#L69-L84

The one listed at line 105 is amd64 only, although ports it
depends on can be installed on aarch64, presuming one does a
"kldload linux64" beforehand.

For armv7, tcptestsuite can not be installed because it depends
on a port that fails to build (compiler rejection for alignment
issues). The linux stuff associated with line 105 does not
apply as well.

Testing kyua's testsuite for hitting the issue of dlopen
failing for /usr/lib/ossl-modules/legacy.so should be
done with the ports installed that apply. (Some may not
contribute to if a dlopen of /usr/lib/ossl-modules/legacy.so
is attempted vs. not. So a more selective list is possible.)

Per comment #6 : With the ports having been installed first,
amd64 has dlopen attempted for /usr/lib/ossl-modules/legacy.so
during a run of the testsuite --and the attempt fails.
Comment 36 Pierre Pronchery 2023-09-15 16:59:01 UTC
Created attachment 244895 [details]
0001-libcrypto-link-engines-and-the-legacy-provider-to-li.patch

The most efficient way to ship OpenSSL's legacy provider module and
engines is to have them link to libcrypto.so. This can break the build
since they are created in a sub-directory of secure/lib/libcrypto, and
may be ready to link before libcrypto.so is available.

This commit introduces a LIBCRYPTO_WITHOUT_SUBDIRS define, ensuring
libcrypto.so builds in its usual early phase without any OpenSSL
provider module or engines. They are then completed as expected later.
Comment 37 Mark Millard 2023-09-16 04:51:53 UTC
(In reply to Pierre Pronchery from comment #36)

QUOTE
This commit introduces a LIBCRYPTO_WITHOUT_SUBDIRS define, ensuring
libcrypto.so builds in its usual early phase without any OpenSSL
provider module or engines.
END QUOTE

Is this instead of something like my crude patch? In addition to?

I'll note that, without your patch, libcrypto.so is what
contains the definitions for the likes of MD4_Update that
are from the likes of md4_prov.c (with my patch the dlopen
of libcrypto.so also publishes such definitions):

# objdump -rRtT /usr/lib/libcrypto.so | grep MD4
00000000002eb010 g     F .text	0000000000000024 MD4_Init
00000000002ea880 g     F .text	0000000000000108 MD4_Update
00000000002eaf40 g     F .text	00000000000000cc MD4_Final
00000000002eaf30 g     F .text	0000000000000008 MD4_Transform
00000000002eb040 g     F .text	00000000000000b0 MD4
00000000002eaf30 g    DF .text	0000000000000008  OPENSSL_1_1_0 MD4_Transform
00000000002ea880 g    DF .text	0000000000000108  OPENSSL_1_1_0 MD4_Update
00000000002eb010 g    DF .text	0000000000000024  OPENSSL_1_1_0 MD4_Init
00000000002eaf40 g    DF .text	00000000000000cc  OPENSSL_1_1_0 MD4_Final
00000000002eb040 g    DF .text	00000000000000b0  OPENSSL_1_1_0 MD4
000000000040df30 R_AARCH64_ABS64          MD4_Update
000000000043afb8 R_AARCH64_JUMP_SLOT      MD4_Init
000000000043afc0 R_AARCH64_JUMP_SLOT      MD4_Update
000000000043afc8 R_AARCH64_JUMP_SLOT      MD4_Final

If libcrypto.so is produced before md4_prov.o is even generated,
that would no longer be true and some other file would need
to end up holding the related definitions.
Comment 38 Mark Millard 2023-09-16 04:59:30 UTC
(In reply to Mark Millard from comment #37)

FYI, on Fedora server 38:

# objdump -rRtT /lib64/libcrypto.so | grep MD4
00000000001b8510 g    DF .text  0000000000000044  OPENSSL_3.0.0 MD4_Init
00000000001b82e0 g    DF .text  0000000000000134  OPENSSL_3.0.0 MD4_Update
00000000001b8414 g    DF .text  000000000000001c  OPENSSL_3.0.0 MD4_Transform
00000000001b8430 g    DF .text  00000000000000dc  OPENSSL_3.0.0 MD4_Final
00000000001b8554 g    DF .text  00000000000000bc  OPENSSL_3.0.0 MD4
Comment 39 Mark Millard 2023-09-16 05:06:45 UTC
(In reply to Mark Millard from comment #38)

openSUSE Tumbleweed basically agrees with Fedora 38 server:

# objdump -rRtT /lib64/libcrypto.so.3 | grep MD4
00000000001b60a0 g    DF .text  0000000000000030  OPENSSL_3.0.0 MD4_Init
00000000001b5e80 g    DF .text  0000000000000134  OPENSSL_3.0.0 MD4_Update
00000000001b5fb4 g    DF .text  000000000000000c  OPENSSL_3.0.0 MD4_Transform
00000000001b5fc0 g    DF .text  00000000000000dc  OPENSSL_3.0.0 MD4_Final
00000000001b60d0 g    DF .text  00000000000000b8  OPENSSL_3.0.0 MD4
Comment 40 Mark Millard 2023-09-16 05:15:02 UTC
(In reply to Mark Millard from comment #39)

On Tumbleweed:

# ldd /usr/lib64/ossl-modules/legacy.so
        linux-vdso.so.1 (0x0000ffff8f9c7000)
        libcrypto.so.3 => /lib64/libcrypto.so.3 (0x0000ffff8f530000)
        libc.so.6 => /lib64/libc.so.6 (0x0000ffff8f310000)
        /lib/ld-linux-aarch64.so.1 (0x0000ffff8f98a000)
        libz.so.1 => /lib64/libz.so.1 (0x0000ffff8f2d0000)
Comment 41 Mark Millard 2023-09-16 05:19:29 UTC
(In reply to Mark Millard from comment #40)

And back to Fedora 38 server:

# ldd /usr/lib64/ossl-modules/legacy.so
        linux-vdso.so.1 (0x0000ffff989f1000)
        libcrypto.so.3 => /lib64/libcrypto.so.3 (0x0000ffff98530000)
        libc.so.6 => /lib64/libc.so.6 (0x0000ffff98360000)
        /lib/ld-linux-aarch64.so.1 (0x0000ffff989a4000)
        libz.so.1 => /lib64/libz.so.1 (0x0000ffff98310000)
Comment 42 Mark Millard 2023-09-16 08:07:00 UTC
(In reply to Mark Millard from comment #41)

I added debian 12 (bookworm) to my collection of compare/contrast
OS's:

# objdump -rRtT /usr/lib/aarch64-linux-gnu/libcrypto.so.3 | grep MD4
0000000000215750 g    DF .text  0000000000000038  OPENSSL_3.0.0 MD4_Init
0000000000215db4 g    DF .text  0000000000000160  OPENSSL_3.0.0 MD4_Update
0000000000215f14 g    DF .text  0000000000000008  OPENSSL_3.0.0 MD4_Transform
0000000000215f20 g    DF .text  00000000000000e4  OPENSSL_3.0.0 MD4_Final
0000000000216010 g    DF .text  00000000000000c8  OPENSSL_3.0.0 MD4
0000000000449f90 R_AARCH64_JUMP_SLOT  MD4_Update@@OPENSSL_3.0.0
000000000044e9d8 R_AARCH64_JUMP_SLOT  MD4_Final@@OPENSSL_3.0.0
000000000044f018 R_AARCH64_JUMP_SLOT  MD4_Init@@OPENSSL_3.0.0

# objdump -rRtT /usr/lib/aarch64-linux-gnu/ossl-modules/legacy.so | grep MD4
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Update
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Final
0000000000000000      DF *UND*  0000000000000000 (OPENSSL_3.0.0) MD4_Init
000000000002f8f0 R_AARCH64_ABS64   MD4_Update@OPENSSL_3.0.0
000000000002fd60 R_AARCH64_JUMP_SLOT  MD4_Update@OPENSSL_3.0.0
000000000002fe60 R_AARCH64_JUMP_SLOT  MD4_Final@OPENSSL_3.0.0
000000000002ff90 R_AARCH64_JUMP_SLOT  MD4_Init@OPENSSL_3.0.0

# ldd /usr/lib/aarch64-linux-gnu/ossl-modules/legacy.so
        linux-vdso.so.1 (0x0000ffff97bba000)
        libcrypto.so.3 => /lib/aarch64-linux-gnu/libcrypto.so.3 (0x0000ffff976e0000)
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff97530000)
        /lib/ld-linux-aarch64.so.1 (0x0000ffff97b7d000)
Comment 43 Mark Millard 2023-09-16 16:50:48 UTC
(In reply to Pierre Pronchery from comment #36)

I clearly misinterpreted the wording (amd64 example
with my crude patch removed and the committed change
included):

# objdump -rRtT /usr/lib/libcrypto.so | grep MD4
0000000000310c70 g     F .text	000000000000002c MD4_Init
0000000000310470 g     F .text	000000000000011c MD4_Update
0000000000310bb0 g     F .text	00000000000000b7 MD4_Final
0000000000310ba0 g     F .text	000000000000000f MD4_Transform
0000000000310ca0 g     F .text	0000000000000099 MD4
0000000000310ba0 g    DF .text	000000000000000f  OPENSSL_1_1_0 MD4_Transform
0000000000310bb0 g    DF .text	00000000000000b7  OPENSSL_1_1_0 MD4_Final
0000000000310470 g    DF .text	000000000000011c  OPENSSL_1_1_0 MD4_Update
0000000000310c70 g    DF .text	000000000000002c  OPENSSL_1_1_0 MD4_Init
0000000000310ca0 g    DF .text	0000000000000099  OPENSSL_1_1_0 MD4
000000000044a9e8 R_X86_64_64              MD4_Update
0000000000468e58 R_X86_64_JUMP_SLOT       MD4_Init
0000000000468e60 R_X86_64_JUMP_SLOT       MD4_Update
0000000000468e68 R_X86_64_JUMP_SLOT       MD4_Final

# objdump -rRtT /usr/lib/ossl-modules/legacy.so | grep MD4
0000000000000000       F *UND*	0000000000000000 MD4_Final
0000000000000000       F *UND*	0000000000000000 MD4_Init
0000000000000000       F *UND*	0000000000000000 MD4_Update
0000000000000000      DF *UND*	0000000000000000 (OPENSSL_1_1_0) MD4_Final
0000000000000000      DF *UND*	0000000000000000 (OPENSSL_1_1_0) MD4_Init
0000000000000000      DF *UND*	0000000000000000 (OPENSSL_1_1_0) MD4_Update
000000000001e498 R_X86_64_64              MD4_Update
00000000000205e8 R_X86_64_JUMP_SLOT       MD4_Final
00000000000205f0 R_X86_64_JUMP_SLOT       MD4_Init

# ldd /usr/lib/ossl-modules/legacy.so
/usr/lib/ossl-modules/legacy.so:
	libcrypto.so.30 => /lib/libcrypto.so.30 (0x22a6b78e8000)
	libc.so.7 => /lib/libc.so.7 (0x22a6b705e000)
	libthr.so.3 => /lib/libthr.so.3 (0x22a6b8147000)

So: "instead of" my crude patch.
Comment 44 Mark Millard 2023-09-16 17:20:07 UTC
(In reply to Mark Millard from comment #43)

The basic test worked. And now on aarch64 I've done
similarly and its test worked (with the relevant ports/packages
installed that currently build for main --but scapy does not
build now for main because net/py-libdnet is broken by the
removal of DIOCGETRULE in main):

# /usr/bin/kyua test -k /usr/tests/Kyuafile examples/test_examples.py
examples/test_examples.py:TestExampleSimple::test_get_properties  ->  skipped: comment me to run the test  [1.024s]
examples/test_examples.py:TestExampleSimple::test_one  ->  skipped: comment me to run the test  [0.681s]
examples/test_examples.py:TestExampleSimple::test_parametrize[AF_INET6]  ->  skipped: comment me to run the test  [0.683s]
examples/test_examples.py:TestExampleSimple::test_parametrize[AF_INET]  ->  skipped: comment me to run the test  [0.686s]
examples/test_examples.py:TestExampleSimple::test_parametrize[FAMILY_39]  ->  skipped: comment me to run the test  [0.679s]
examples/test_examples.py:TestExampleSimple::test_syscall_failure  ->  skipped: comment me to run the test  [0.685s]
examples/test_examples.py:TestExampleSimple::test_two  ->  skipped: Current architecture 'aarch64' not supported  [0.001s]
examples/test_examples.py:TestExampleSimple::test_with_cleanup  ->  passed  [1.024s]
examples/test_examples.py:TestExampleSimplest::test_one  ->  skipped: comment me to run the test  [0.686s]
examples/test_examples.py:TestVnetDual1::test_ifstat  ->  skipped: comment me to run the test  [0.841s]
examples/test_examples.py:TestVnetSimple::test_ping  ->  skipped: comment me to run the test  [1.024s]
examples/test_examples.py:TestVnetSimple::test_topology  ->  skipped: comment me to run the test  [1.027s]

Results file id is usr_tests.20230916-165732-736186
Results saved to /usr/home/root/.kyua/store/results.usr_tests.20230916-165732-736186.db

12/12 passed (0 failed)
Comment 45 Ed Maste freebsd_committer freebsd_triage 2023-09-19 14:06:47 UTC
Mark can you confirm that this is fixed now?
Comment 46 Mark Millard 2023-09-19 14:51:01 UTC
(In reply to Ed Maste from comment #45)

The context is a little messy, but summary: This looks to work.

Details . . .

net/libdnet was failing to build on main, in turn blocking net/scapy .
A commit was made intending to have it use net/libpfctl but I'm now
having different build failure in poudriere-devel during configure
in the net/libnet build tied to not resolving -lpfctl .

So I've yet to make it back to a normal, full kyua test suite run based
on standard materials.

However, the likes of:

# /usr/bin/kyua test -k /usr/tests/Kyuafile examples/test_examples.py

works and an earlier draft patch for net/libdnet worked for allowing
a run with net/scapy used on aarch64.
Comment 47 Mark Millard 2023-09-19 19:19:14 UTC
The commits for a fix were tracked against another bugzilla
report, a more overall longer term one.

So count this submittal as an example of: Overcome By Events.