AES-CCM and AES-GCM in .NET Core on macOS Catalina

Since .NET Core 3.0 authenticated encryption modes CCM and GCM are available via System.Security.Cryptography.AesCcm and System.Security.Cryptography.AesGcm classes.

Linux and Windows implementations rely on system libraries, but macOS implementation uses OpenSSL library.

The Problem

Unfortunately, AesCcm or AesGcm don’t work out of box on macOS Catalina. Instantiating either will cause app to crash:

var aesGcm = new AesGcm(key); // crashes the app 

If you run the code above as a part of the unit test, you’ll get the following error message:

The active test run was aborted. Reason: Test host process crashed : No usable version of libssl was found

Further inspection of the crash report reveals that crash occurred in System.Security.Cryptography.Native.OpenSsl.dylib:

Thread 19 Crashed:
0   libsystem_kernel.dylib        	0x00007fff7267933a __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff72735e60 pthread_kill + 430
2   libsystem_c.dylib             	0x00007fff72600808 abort + 120
3   System.Security.Cryptography.Native.OpenSsl.dylib	0x00000001113817c5 0x111375000 + 51141
4   System.Security.Cryptography.Native.OpenSsl.dylib	0x000000011138175a 0x111375000 + 51034

The app crashed because it was unable to load the libssl. Since High Sierra, macOS ships with LibreSSL, yet these implementations work with OpenSSL only.

The Fix

Verifying the OpenSSL installation

Make sure that you have libssl from OpenSSL in your /usr/local/lib:

$ ls -la /usr/local/lib | grep libssl
.rwxr-xr-x 551k root  11 Apr 20:32 libssl.1.1.dylib
.rwxr-xr-x 557k root  11 Apr 19:59 libssl.3.dylib
.rw-r--r-- 790k root  11 Apr 20:32 libssl.a
lrwxr-xr-x   16 root  11 Apr 20:32 libssl.dylib -> libssl.1.1.dylib

The easiest way to install OpenSSL, if it’s not already present on your system, is by using homebrew:

brew install openssl


Next step is to explicitly tell macOS where to load the libraries from by setting the DYLD_LIBRARY_PATH environment variable.

export DYLD_LIBRARY_PATH=/usr/local/lib

If you’re using Jetbrains Rider, Microsoft Visual Studio or any other IDE, make sure to set the DYLD_LIBRARY_PATH in both Unit Test and Run/Debug configurations.

To configure the environment variables used by Unit Tests in Rider, go to Preferences, and then navigate to Build, Execution and Deploy > Unit Testing > Test Runner.

Don’t use the install_name_tool

Some articles suggest using the install_name_tool to set the rpath in System.Security.Cryptography.Native.OpenSsl.dylib. Note that this will modify the binary and render the signature invalid. As a result, macOS will crash any app trying to load the library. You’d have to disable the System Integrity Protection in order to use such modified library.

If you already modified the library using install_name_tool, re-install .NET Core.



comments powered by Disqus