C How to use opencrypto in userspace?, documentation looks like suggesting errors.

There is plenty of affirmations in the documentation that opencrypto crypto(4) can be used to encrypt and decrypt data, certainly GELI claims to be using it, but the documentation does not look very useful, case stands there is no even en example on crypto(4).
I am doing some LUKS (scary) things in FreeBSD, and have to do some aes-xts-plain64 decryption, but the documentation is no helping.

I found crypto_session(9) which suggest some code like:
Code:
#include <stdint.h>
#include <unistd.h>
#include <crypto/cryptodev.h>

int main(int argc, char **argv) {
    struct crypto_session_params csp;
    csp.csp_mode = CSP_MODE_CIPHER; 
    csp.csp_flags = CSP_F_SEPARATE_OUTPUT; 
    csp.csp_cipher_alg = CRYPTO_AES_XTS;
    csp.csp_cipher_klen = 8;
    csp.csp_cipher_key = key_array;
    void *cses;
    (void) crypto_newsession(&cses, &csp, -1);
}
and so the #include <opencrypto/cryptodev.h>l/cmd] has to be actually [cmd]#include <crypto/cryptodev.h>, because there is no opencrypto in /usr/src.

Then when I try to compile such code with cc crypto.c -o crypto I get the following errors:
Code:
crypto.c:6:34: error: variable has incomplete type 'struct crypto_session_params'
    6 |     struct crypto_session_params csp;
      |                                  ^
crypto.c:6:12: note: forward declaration of 'struct crypto_session_params'
    6 |     struct crypto_session_params csp;
      |            ^
crypto.c:7:20: error: use of undeclared identifier 'CSP_MODE_CIPHER'
    7 |     csp.csp_mode = CSP_MODE_CIPHER; 
      |                    ^
crypto.c:8:21: error: use of undeclared identifier 'CSP_F_SEPARATE_OUTPUT'
    8 |     csp.csp_flags = CSP_F_SEPARATE_OUTPUT; 
      |                     ^
crypto.c:11:26: error: use of undeclared identifier 'key_array'
   11 |     csp.csp_cipher_key = key_array;
      |                          ^
crypto.c:13:12: warning: call to undeclared function 'crypto_newsession'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
   13 |     (void) crypto_newsession(&cses, &csp, -1);
      |            ^
1 warning and 4 errors generated.
but reading /usr/include/crypto/cryptodev.h there is clearly of those things and it does not appear to be behind a conditional.

Searching for more documentation with man -K crypto sees to only show those manual section 9 entries like crypto_session(9), an entire figurative oceon of openssl entries including some /usr/share/openssl/man/man3/EVP* from also openssl, which I think will use to do my decryiption and encryption tasks. After excluding /usr/share/openssl and making sure ports are not included the results which I got are more or less: (1) some apparently unrelated manual section 1 results, (2) nothing in manual section 2, (3) plenty of checksum subroutines in manual section 3 and SNMP protocol handling, (4) in manual section 4 the all unhelpfull opencrypto documentation, accelerators, a couple of tools which use cryptographic functions like ipsec and wifi, (5) in manual section 5 bhyve-config, libarchive-formats, and src compilation options, (6) in manual section 6 also nothing, (7) in manual section 7 crypto(7) also unhelpful, intro(7), mdoc(7), miscellaneous(7) and simd(7), (8) in manual section 8 also nothing, (9) in manual section 9 basically the crypto_* whilh give me the previous error.

Overall no very helpful documentation.

In other notes: What do you think of having a LUKS plugin for GELI/GEOM?
 
those are kernel only
you are supposed to use struct session2_op or struct session_op
you may look at /usr/src/crypto/openssl/engines/e_devcrypto.c
play with openssl engine stuff and see if it can do what you need

or /usr/src/tools/tools/crypto but stuff there does not compile. i made build but still every ioctl on /dev/crypto gets an invalid argument
 
Taking a quick look at /usr/include/crypto/cryptodev.h, the first few lines state

Code:
#ifndef _CRYPTO_CRYPTO_H_
#define _CRYPTO_CRYPTO_H_

#include <sys/ioccom.h>

#ifdef _KERNEL
#include <opencrypto/_cryptodev.h>
...
#endif

So it needs to be compiled with _KERNEL defined, and it will then try to load _cryptodev.h.

... which lives in /usr/src/sys/opencrypto

/usr/src/sys/opencrypto # ls
_cryptodev.h cryptosoft.c rmd160.h xform_comp.h
cbc_mac.c deflate.h xform.h xform_deflate.c
cbc_mac.h gfmult.c xform_aes_cbc.c xform_enc.h
criov.c gfmult.h xform_aes_icm.c xform_gmac.c
crypto.c gmac.c xform_aes_xts.c xform_null.c
cryptodeflate.c gmac.h xform_auth.h xform_poly1305.c
cryptodev.c ktls.h xform_cbc_mac.c xform_rmd160.c
cryptodev.h ktls_ocf.c xform_chacha20_poly1305.c xform_sha1.c
cryptodev_if.m rmd160.c xform_cml.c xform_sha2.c

So I think you need to have /usr/src/sys on your include path, and you also need to compile with _KERNEL defined.
So crudely something like
$ cc -D_KERNEL -I/usr/src/sys ...
- is part of what you need.

But presumably there is a standard method for compiling code in the kernel, probably the developers manual tells you how do that.
 
Pasting your code sample into test.c and then compiling it with

$ cc -c -I /usr/src/sys -D_KERNEL test.c

gets a bit further, but then barfs on another missing include file, but clearly I am not using the full list of arguments required, that remains to be discovered. Need to have a good read through the kernel sections of the developers manual to discover what else is required. If you are lucky there may be a wrapper script or a base makefile somewhere that sets up all the include paths and definitions needed for kernel programming.

In file included from test.c:3:
In file included from /usr/include/crypto/cryptodev.h:72:
In file included from /usr/src/sys/sys/libkern.h:40:
In file included from /usr/src/sys/sys/systm.h:102:
/usr/src/sys/sys/kpilite.h:31:10: fatal error: 'offset.inc' file not found
31 | #include "offset.inc"
| ^~~~~~~~~~~~
1 error generated.
 
you can't build userland progs with -D_KERNEL
Fine, so he needs to read the developers manual to figure out how he's meant to compile it. Or find some example code that uses the same library and copy what they've done to compile it. There must be a test suite for that library somewhere, find that and study it's makefile to discover how it is compiled, for example.
 
openssl has support for /dev/crypto but does not seem to work.
everything i tried reverts to userland ciphers (openssl speed has 0 kernel time)
there are a bunch of failed ioctls on /dev/crypto in truss' output
 
i have the cryptodev and sysctl-ed it to allow software emulation for userland programs
Code:
~$ openssl engine -v -pre DUMP_INFO devcrypto
(devcrypto) /dev/crypto engine
Information about ciphers supported by the /dev/crypto engine:
CIOCGSESSINFO (session info call) unavailable
Cipher DES-CBC, NID=31, /dev/crypto info: id=1, CIOCGSESSION (session open call) failed
Cipher DES-EDE3-CBC, NID=44, /dev/crypto info: id=2, CIOCGSESSION (session open call) failed
Cipher BF-CBC, NID=91, /dev/crypto info: id=3, CIOCGSESSION (session open call) failed
Cipher CAST5-CBC, NID=108, /dev/crypto info: id=4, CIOCGSESSION (session open call) failed
Cipher AES-128-CBC, NID=419, /dev/crypto info: id=11, driver=aesni0 (software)
Cipher AES-192-CBC, NID=423, /dev/crypto info: id=11, driver=aesni0 (software)
Cipher AES-256-CBC, NID=427, /dev/crypto info: id=11, driver=aesni0 (software)
Cipher RC4, NID=5, /dev/crypto info: id=12, CIOCGSESSION (session open call) failed
Cipher CAMELLIA-128-CBC, NID=751, /dev/crypto info: id=21, driver=cryptosoft0 (software)
Cipher CAMELLIA-192-CBC, NID=752, /dev/crypto info: id=21, driver=cryptosoft0 (software)
Cipher CAMELLIA-256-CBC, NID=753, /dev/crypto info: id=21, driver=cryptosoft0 (software)
 
well i've got it to work somehow
assuming no crypto accel hw you need to
sysctl kern.cryptodevallowsoft=1
then for openssl you need to set engine to permit software drivers
unfortunately you can't do that (or i don't know how) without a config file
$(openssl speed) versions from 14.x do not permit a config file but 15.1 works
Code:
time  openssl speed -engine devcrypto -config ~/o.cnf aes-256-cbc
Using configuration from /home/titus/o.cnf
Engine "devcrypto" set.
Doing aes-256-cbc ops for 3s on 16 size blocks: 3372904 aes-256-cbc ops in 0.30s
Doing aes-256-cbc ops for 3s on 64 size blocks: 3259398 aes-256-cbc ops in 0.24s
Doing aes-256-cbc ops for 3s on 256 size blocks: 2799448 aes-256-cbc ops in 0.27s
Doing aes-256-cbc ops for 3s on 1024 size blocks: 1780360 aes-256-cbc ops in 0.12s
Doing aes-256-cbc ops for 3s on 8192 size blocks: 405980 aes-256-cbc ops in 0.02s
Doing aes-256-cbc ops for 3s on 16384 size blocks: 216982 aes-256-cbc ops in 0.01s
version: 3.5.6
built on: reproducible build, date unspecified
options: bn(64,64)
compiler: clang
CPUINFO: OPENSSL_armcap=0xbd
The 'numbers' are in 1000s of bytes per second processed.
type             16 bytes     64 bytes    256 bytes   1024 bytes   8192 bytes  16384 bytes
aes-256-cbc     181781.77k   861322.21k  2620923.20k 15557023.06k 212850442.24k 455044235.26k

real    0m18.016s
user    0m0.961s
sys    0m17.001s

Code:
 cat ~/o.cnf
# Declare the top-level configuration
openssl_conf = openssl_init

[openssl_init]
engines = engine_section

[engine_section]
# Replace 'your_engine_id' with your actual engine ID (e.g., qatengine, cryptodev)
devcrypto = engine_configuration

[engine_configuration]
# Equivalent to a '-pre' command (runs before initialization)
#dynamic_path = /usr/lib/engines-1.1/your_engine.so

# Equivalent to '-post' commands (arbitrary control commands sent after initialization)
USE_SOFTDRIVERS = 1
CIPHERS = AES-256-CBC

# Tell OpenSSL to use this engine for all algorithms by default
default_algorithms = ALL
 
also /usr/src/tools/tools/crypto you can build cryptotest on 14.x or cryptocheck on 15.x
remove anything else from the PROGS line in the makefile to build
for 14.x apply this patch
Diff:
--- cryptotest.c.orig    2026-10-27 14:58:03.599320000 +0200
+++ cryptotest.c    2026-10-27 14:57:03.948706000 +0200
@@ -406,7 +406,7 @@
     close(fd);
 }

-#ifdef __FreeBSD__
+#ifdef X__FreeBSD__
 void
 resetstats()
 {
@@ -477,7 +477,7 @@
         size_t tlen = sizeof (otiming);
         int timing = 1;

-        resetstats();
+        // resetstats();
         if (sysctlbyname("debug.crypto_timing", &otiming, &tlen,
                 &timing, sizeof (timing)) < 0)
             perror("debug.crypto_timing");
@@ -512,7 +512,7 @@
             size, (double)nops*size / t,
             (double)nops*size / t * 8 / 1024 / 1024);
     }
-#ifdef __FreeBSD__
+#ifdef X__FreeBSD__
     if (profile) {
         struct cryptostats stats;
         size_t slen = sizeof (stats);

make CFLAGS=-Wno-error clean all
Code:
time /usr/obj/usr/src/amd64.amd64/tools/tools/crypto/cryptotest -d soft -a aes256 2400000 256
   5.356 sec, 4800000 aes256       crypts,     256 bytes, 229436553 byte/sec,  1750.5 Mb/sec

real    0m5.357s
user    0m0.163s
sys    0m5.189s
 
Yeah sorry I just had a typo in my post, the file I was looking at was /usr/include/crypto/cryptodev.h. There is no /usr/include/cryptodev.h. I've corrected it.
If you read the file well, it starts with:
Code:
#ifndef _CRYPTO_CRYPTO_H_
#define _CRYPTO_CRYPTO_H_

#include <sys/ioccom.h>

#ifdef _KERNEL
#include <opencrypto/_cryptodev.h>
#include <sys/_task.h>
#include <sys/libkern.h>
#include <sys/time.h>
#endif
As you see the ifdef clearly terminates in 5 lines fater the #ifdef _KERNEL, thus your argument does not apply.
 
The first compilation error you listed is because it has failed to find the definition of struct crypto_session_params. If you read /usr/include/crypto/cryptodev.h carefully you will find that structure is also defined (at line 332) within a #ifdef _KERNEL conditional block. The start of the relevent conditional block is on line 315 and the end of the block is on line 735, at least, on my 14.5-release-p2 install. There is only one definition (thankfully) of struct crypto_session_params in the file, so user space code must somehow be compiled using the same definition as the kernel. Just pray that there isn't a separate 'user-space' definition of that structure hiding somewhere in another file... 😂
 

Attachments

The first compilation error you listed is because it has failed to find the definition of struct crypto_session_params. If you read /usr/include/crypto/cryptodev.h carefully you will find that structure is also defined within a #ifdef _KERNEL conditional block. The start of the relevent conditional block is on line 315 and the end of the block is on 735, at least, on my 14.5-release-p2 install.
Looks like you are right, the ifdef block almost got confused because a regular if block, one can just define [/cmd]#define _KERNEL[/cmd] before importing it?
 
That's what the -D_KERNEL in my suggested cc arguments was for. But that is clearly not a complete list of everything you need to compile the sample program. I suggest have a look at how covacat has built the cryptotest test program (or cryptocheck on 15.x), that he mentioned a few posts back in this thread, he has given some hints on how he got it to build. The cryptotest/check makefile probably gives you a template you can copy for other programs using the crypto library. I haven't looked at it myself, but you may find you don't need to specify the -D_KERNEL explicitily, it may be hidden somewhere lower down in the code stack; assuming there is only one set of definitions, you will have to keep your fingers crossed that is the case.
 
Back
Top