Servers.

oqsprovider on FreeBSD

Building oqsprovider

My naive approach was to simply follow the provided instructions:

$ git clone https://github.com/open-quantum-safe/oqs-provider
$ cd oqs-provider
$ cmake -DOPENSSL_ROOT_DIR=/usr/local -S . -B _build
[... narrative output ...]
-- Configuring done
-- Generating done
-- Build files have been written to: /home/cromwell/oqs-provider/_build
$ cmake --build _build
[... initial compilation steps ...]

However, this resulted in many errors about dynamic relocation:

[... earlier successful compilation steps ...]
[ 64%] Building C object oqsprov/CMakeFiles/oqsprovider.dir/oqs_endecoder_common.c.o
[ 68%] Building C object oqsprov/CMakeFiles/oqsprovider.dir/oqs_decode_der2key.c.o
[ 72%] Building C object oqsprov/CMakeFiles/oqsprovider.dir/oqsprov_bio.c.o
[ 76%] Linking C shared library ../lib/oqsprovider.so
ld: error: can't create dynamic relocation R_X86_64_32S against local symbol in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
>>> defined in ../install/lib/libqsc_key_encoder.a(encoding_qsc.c.o)
>>> referenced by encoding_qsc.c
>>>               encoding_qsc.c.o:(qsc_encoding_by_name_oid) in archive ../install/lib/libqsc_key_encoder.a

ld: error: can't create dynamic relocation R_X86_64_64 against symbol: Dilithium_R3_4x4_encodings in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
>>> defined in ../install/lib/libqsc_key_encoder.a(encoding_dilithium.c.o)
>>> referenced by encoding_qsc.c
>>>               encoding_qsc.c.o:(qsc_encodings) in archive ../install/lib/libqsc_key_encoder.a

ld: error: can't create dynamic relocation R_X86_64_64 against symbol: Dilithium_R3_6x5_encodings in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
>>> defined in ../install/lib/libqsc_key_encoder.a(encoding_dilithium.c.o)
>>> referenced by encoding_qsc.c
>>>               encoding_qsc.c.o:(qsc_encodings) in archive ../install/lib/libqsc_key_encoder.a

[... many continuing errors ...]

ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error code 1

Stop.

The output tells us to use the -fPIC option which creates position-independent code (hence PIC) suitable for dynamic linking and avoiding any limit on the size of the global offset table.

I eventually figured out that the problem came from FreeBSD including the Clang C compiler. In this situation with everything being invoked through cmake, the suggested workarounds were specific to the GCC compiler collection and its gcc and g++. I also had GCC installed, but it wasn't being used by the above process.

$ which cc
/usr/bin/cc
$ cc --version
FreeBSD clang version 16.0.6 (https://github.com/llvm/llvm-project.git llvmorg-16.0.6-0-g7cbf1a259152)
Target: x86_64-unknown-freebsd14.0
Thread model: posix
InstalledDir: /usr/bin
$ which gcc
/usr/local/bin/gcc
$ gcc --version
gcc (FreeBSD Ports Collection) 12.2.0

Here is what worked for me.

$ cd
$ rm -r oqs-provider
$ git clone https://github.com/open-quantum-safe/oqs-provider
$ cd oqs-provider
$ export CC=/usr/local/bin/gcc
$ export CFLAGS="-fPIC"
$ cmake -DOPENSSL_ROOT_DIR=/usr/local -S . -B _build
-- The C compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/local/bin/gcc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Creating Release build
-- Build will store public keys in PKCS#8 structures
-- Build will include external encoding library for SPKI/PKCS#8
-- Found OpenSSL: /usr/local/lib/libcrypto.so (found suitable version "3.1.4", minimum required is "3.0")
-- Building commit 0e46745 in /home/cromwell/oqs-provider
CMake Warning at test/CMakeLists.txt:35 (message):
  OpenSSL source build directory
  '/home/cromwell/oqs-provider/test/../openssl' not present.  Some dependent
  tests will be skipped.

-- Configuring done
-- Generating done
-- Build files have been written to: /home/cromwell/oqs-provider/_build
$ cmake --build _build
[... many earlier compilation steps ...]
[ 64%] Building C object oqsprov/CMakeFiles/oqsprovider.dir/oqs_endecoder_common.c.o
[ 68%] Building C object oqsprov/CMakeFiles/oqsprovider.dir/oqs_decode_der2key.c.o
[ 72%] Building C object oqsprov/CMakeFiles/oqsprovider.dir/oqsprov_bio.c.o
[ 76%] Linking C shared library ../lib/oqsprovider.so
[ 76%] Built target oqsprovider
[ 80%] Building C object test/CMakeFiles/oqs_test_signatures.dir/oqs_test_signatures.c.o
[ 84%] Building C object test/CMakeFiles/oqs_test_signatures.dir/test_common.c.o
[ 88%] Linking C executable oqs_test_signatures
[ 88%] Built target oqs_test_signatures
[ 92%] Building C object test/CMakeFiles/oqs_test_kems.dir/oqs_test_kems.c.o
[ 96%] Building C object test/CMakeFiles/oqs_test_kems.dir/test_common.c.o
[100%] Linking C executable oqs_test_kems
[100%] Built target oqs_test_kems

That finished in just about ten seconds! Now I can install it:

$ sudo cmake --install _build
-- Install configuration: ""
-- Installing: /usr/local/lib/oqsprovider.so.0.5.0-dev
-- Installing: /usr/local/lib/oqsprovider.so.1
-- Set runtime path of "/usr/local/lib/oqsprovider.so.0.5.0-dev" to ""
-- Installing: /usr/local/lib/oqsprovider.so

Notice that the oqsprovider.so shared library is also linked to use the libcrypto.so shared library created when I built OpenSSL.

$ ls -l /usr/local/lib/oqsprovider.so*
lrwxr-xr-x  1 root  wheel       16 Apr  2 17:27 /usr/local/lib/oqsprovider.so -> oqsprovider.so.1
-rwxr-xr-x  1 root  wheel  5939096 Apr  2 17:21 /usr/local/lib/oqsprovider.so.0.5.0-dev
lrwxr-xr-x  1 root  wheel       24 Apr  2 17:27 /usr/local/lib/oqsprovider.so.1 -> oqsprovider.so.0.5.0-dev
$ file /usr/local/lib/oqsprovider.so.0.5.0-dev
/usr/local/lib/oqsprovider.so.0.5.0-dev: ELF 64-bit LSB shared object, x86-64, version 1 (FreeBSD), dynamically linked, for FreeBSD 13.1, with debug_info, not stripped
$ ldd /usr/local/lib/oqsprovider.so.0.5.0-dev
/usr/local/lib/oqsprovider.so.0.5.0-dev:
        libcrypto.so.3 => /usr/local/lib/libcrypto.so.3 (0x1a4f365cb000)
        libc.so.7 => /lib/libc.so.7 (0x1a4f33538000)
        libthr.so.3 => /lib/libthr.so.3 (0x1a4f32b7f000)

Configuring OpenSSL to use oqsprovider

The openssl program is configured by the file /etc/ssl/openssl.cnf. The original file contains this section in lines 53 through 72:

[...52 lines deleted...]
[openssl_init]
providers = provider_sect

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
# fips = fips_sect

# If no providers are activated explicitly, the default one is activated implicitly.
# See man 7 OSSL_PROVIDER-default for more details.
#
# If you add a section explicitly activating any other provider(s), you most
# probably need to explicitly activate the default provider, otherwise it
# becomes unavailable in openssl.  As a consequence applications depending on
# OpenSSL may not work correctly which could lead to significant system
# problems including inability to remotely access the system.
[default_sect]
# activate = 1

[...more lines deleted...]

We need to change it as follows, with changes highlighted:

[...52 lines deleted...]
[openssl_init]
providers = provider_sect

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
# fips = fips_sect
oqs = oqs_sect

# If no providers are activated explicitly, the default one is activated implicitly.
# See man 7 OSSL_PROVIDER-default for more details.
#
# If you add a section explicitly activating any other provider(s), you most
# probably need to explicitly activate the default provider, otherwise it
# becomes unavailable in openssl.  As a consequence applications depending on
# OpenSSL may not work correctly which could lead to significant system
# problems including inability to remotely access the system.
[default_sect]
activate = 1

[oqs_sect]
module = /usr/local/lib/oqsprovider.so
activate = 1

[...more lines deleted...]

Notice that I have:

  1. Added oqs to the list of providers, to be defined in a following [oqs_sect] section.
  2. Explicitly enabled the default provider, as strongly suggested.
  3. Created a new [oqs_sect] section which specifies the newly built oqsprovider.so shared library and then activates it.

The diff command should show you these changes:

$ diff /etc/ssl/openssl.cnf.dist /etc/ssl/openssl.cnf
61a62
> oqs = oqs_sect
72c73
< # activate = 1
---
> activate = 1
73a75,77
> [oqs_sect]
> module = /usr/local/lib/oqsprovider.so
> activate = 1

Now openssl supports the Open Quantum Safe provider!

$ openssl list -providers
Providers:
  default
    name: OpenSSL Default Provider
    version: 3.1.1
    status: active
  oqs
    name: OpenSSL OQS Provider
    version: 0.5.0-dev
    status: active
$ openssl list -key-exchange-algorithms
  ECDH @ default
  { 1.3.101.110, X25519 } @ default
  { 1.3.101.111, X448 } @ default
  { 1.2.840.113549.1.3.1, DH, dhKeyAgreement } @ default
  TLS1-PRF @ default
  HKDF @ default
  { 1.3.6.1.4.1.11591.4.11, id-scrypt, SCRYPT } @ default
$ openssl list -kem-algorithms | sort
  bikel1 @ oqs
  bikel3 @ oqs
  bikel5 @ oqs
  frodo1344aes @ oqs
  frodo1344shake @ oqs
  frodo640aes @ oqs
  frodo640shake @ oqs
  frodo976aes @ oqs
  frodo976shake @ oqs
  hqc128 @ oqs
  hqc192 @ oqs
  hqc256 @ oqs
  kyber1024 @ oqs
  kyber512 @ oqs
  kyber768 @ oqs
  kyber90s1024 @ oqs
  kyber90s512 @ oqs
  kyber90s768 @ oqs
  p256_bikel1 @ oqs
  p256_frodo640aes @ oqs
  p256_frodo640shake @ oqs
  p256_hqc128 @ oqs
  p256_kyber512 @ oqs
  p256_kyber90s512 @ oqs
  p384_bikel3 @ oqs
  p384_frodo976aes @ oqs
  p384_frodo976shake @ oqs
  p384_hqc192 @ oqs
  p384_kyber768 @ oqs
  p384_kyber90s768 @ oqs
  p521_bikel5 @ oqs
  p521_frodo1344aes @ oqs
  p521_frodo1344shake @ oqs
  p521_hqc256 @ oqs
  p521_kyber1024 @ oqs
  p521_kyber90s1024 @ oqs
  x25519_bikel1 @ oqs
  x25519_frodo640aes @ oqs
  x25519_frodo640shake @ oqs
  x25519_hqc128 @ oqs
  x25519_kyber512 @ oqs
  x25519_kyber90s512 @ oqs
  x448_bikel3 @ oqs
  x448_frodo976aes @ oqs
  x448_frodo976shake @ oqs
  x448_hqc192 @ oqs
  x448_kyber768 @ oqs
  x448_kyber90s768 @ oqs
  { 1.2.840.113549.1.1.1, 2.5.8.1.1, RSA, rsaEncryption } @ default