# LUKS2 Disk Encryption with wolfSSL as the Kernel Crypto Backend

This guide covers the **kernel-side** half of the Full Linux FIPS story.
The userspace half (wolfSSL + wolfProvider through apt or dnf) is in
the per-distro HOWTOs:

- [HOWTO-debian.md](HOWTO-debian.md)
- [HOWTO-fedora.md](HOWTO-fedora.md)
- [HOWTO-el.md](HOWTO-el.md)

This document is technical instructions for building and loading
wolfSSL's Linux kernel module, `libwolfssl.ko`.  It is not a
presales artifact and is not part of the FIPS-eval evaluation channel.
For FIPS 140-3 validated kernel cryptography, production licensing,
and Operational Environment (OE) work, contact
<facts@wolfssl.com> — see the bottom of this document.

`libwolfssl.ko` is wolfSSL's Linux kernel module.  When loaded, it registers
wolfSSL's cryptographic implementations into the kernel crypto API, where
dm-crypt (and any other in-kernel consumer) can use them in preference to the
kernel's own drivers.  This guide walks through building `libwolfssl.ko`,
loading it, and verifying that a LUKS2 volume is encrypted and decrypted using
wolfSSL rather than the kernel's built-in AES driver.

## Algorithm mapping

LUKS2 uses the kernel crypto API for all cryptographic operations.  With
`libwolfssl.ko` loaded at priority 100000, it wins every algorithm contest
against the kernel's built-in drivers (AES-NI priority 400).

| LUKS2 operation | Kernel API name | wolfSSL driver (x86-64) |
| :--- | :--- | :--- |
| Data encryption | `xts(aes)` | `xts-aes-aesni-avx-wolfcrypt` |
| Key derivation hash | `sha256` | `sha256-avx2-wolfcrypt` |
| Key derivation MAC | `hmac(sha256)` | `hmac-sha256-avx2-wolfcrypt` |

On ARM64, the driver names use `wolfcrypt` suffix without the `aesni-avx`
middle component: e.g. `xts-aes-wolfcrypt`, `sha256-wolfcrypt`.

## Prerequisites

Your kernel must be configured with `CONFIG_CRYPTO_FIPS=n`.  Non-FIPS wolfSSL
cannot register algorithms against a kernel built with `CONFIG_CRYPTO_FIPS=y`.
See [Distro compatibility](#distro-compatibility) below.

You also need:

- Kernel headers for the running kernel
- The gcc version that was used to build that kernel
- `cryptsetup` (for LUKS operations)
- `openssl` (for module signing)

On Ubuntu/Debian:

```
# apt-get install build-essential autoconf automake libtool \
    linux-headers-$(uname -r) \
    libssl-dev openssl cryptsetup-bin
```

The gcc version must match the kernel's build compiler exactly.  A mismatch
produces `insmod: ERROR: could not insert module: Invalid module format`.
Check the compiler used for your kernel:

```
$ cat /proc/version
Linux version 6.8.0-1053-aws (... gcc (Ubuntu 12.3.0) 12.3.0 ...)
```

Install the matching gcc package (`gcc-12` in the example above) and
substitute it for `$KGCC` in the commands below.

## Building `libwolfssl.ko`

(1) **Clone wolfSSL:**

```
$ git clone --depth=1 https://github.com/wolfSSL/wolfssl
$ cd wolfssl
$ ./autogen.sh
```

(2) **Configure for the kernel module:**

On x86-64:

```
$ ./configure --quiet \
    --enable-cryptonly \
    --enable-linuxkm \
    --enable-linuxkm-lkcapi-register \
    --enable-intelasm \
    --enable-aes \
    --enable-aesgcm \
    --enable-aesxts \
    --enable-sha256 \
    --enable-sha512 \
    --enable-hmac \
    --with-linux-source=/lib/modules/$(uname -r)/build \
    CC=$KGCC HOSTCC=$KGCC
```

On ARM64, omit `--enable-intelasm` (do not replace it with `--enable-armasm`
— ARM SIMD is not yet supported in the linuxkm build context) and add
`ARCH=arm64` to the `make` command below.

`--enable-linuxkm-lkcapi-register` is required.  Without it, wolfSSL loads
but registers no algorithms — dm-crypt will silently use the kernel's
built-in AES driver instead.

`--enable-aesxts` is required.  AES-XTS is the cipher mode dm-crypt uses for
the LUKS2 data partition.

(3) **Build the kernel module:**

```
$ make -j$(nproc) CC=$KGCC HOSTCC=$KGCC module
$ ls -lh linuxkm/libwolfssl.ko
```

On ARM64 add `ARCH=arm64` to the make invocation.

wolfSSL's build system attempts to self-sign `libwolfssl.ko.signed` using the
kernel's own build key, which is not available outside the kernel tree.  That
step will fail.  The unsigned `linuxkm/libwolfssl.ko` is produced before the
signing attempt and is the artifact you will use.

## Signing the Module

Most kernels require a module signature before loading.  Sign with an
ephemeral key; the kernel logs a taint warning but loads the module without
error.  If your kernel enforces `MODULE_SIG_FORCE=y` (Ubuntu Pro / FIPS
kernels), you must instead enroll the signing certificate via MOK — see
[Troubleshooting](#troubleshooting).

```
$ openssl req -new -x509 -newkey rsa:2048 \
    -keyout signing_key.pem \
    -out signing_cert.pem \
    -days 1 -nodes \
    -subj "/CN=wolfssl-luks-ephemeral" 2>/dev/null

$ SIGN_FILE=$(find /lib/modules/$(uname -r)/build/scripts \
                   /usr/src/linux-headers-$(uname -r)/scripts \
                   -name sign-file -type f 2>/dev/null | head -1)

$ "$SIGN_FILE" sha256 signing_key.pem signing_cert.pem \
    linuxkm/libwolfssl.ko

$ rm signing_key.pem
```

## Loading the Module

```
# insmod linuxkm/libwolfssl.ko
```

Check `dmesg` for the registration summary.  You should see one line per
registered algorithm ending in `self-test OK -- registered`, followed by:

```
wolfCrypt: 44 algorithms registered.
wolfCrypt 5.9.1 loaded without valid module signature.
```

"Without valid module signature" is expected when using an ephemeral key that
is not in the distribution's trusted keyring.  All 44 algorithms are
registered regardless.

Confirm with `lsmod`:

```
$ lsmod | grep libwolfssl
libwolfssl           2043904  0
```

## Verifying Algorithm Registration

```
$ grep -A3 "^name.*: xts(aes)$" /proc/crypto | grep driver
driver       : xts-aes-aesni-avx-wolfcrypt

$ grep -A3 "^name.*: sha256$" /proc/crypto | grep driver | head -1
driver       : sha256-avx2-wolfcrypt

$ grep -A3 "^name.*: hmac(sha256)$" /proc/crypto | grep driver
driver       : hmac-sha256-avx2-wolfcrypt
```

All three drivers must show a `wolfcrypt` suffix.  If any shows a non-wolfssl
driver, `libwolfssl.ko` either did not load, or was built without
`--enable-linuxkm-lkcapi-register`.

## Creating and Using a LUKS2 Volume

These steps use a loopback file as the backing block device.  Substitute a
real block device path where appropriate.

(1) **Create a backing file and attach a loop device:**

```
$ dd if=/dev/zero of=luks-test.img bs=1M count=256 status=none
# losetup --find --show luks-test.img
/dev/loop0
```

Set `LOOP_DEV` to the path printed by `losetup`.

(2) **Format as LUKS2:**

```
# cryptsetup luksFormat \
    --type luks2 \
    --cipher aes-xts-plain64 \
    --key-size 512 \
    --pbkdf pbkdf2 \
    --hash sha256 \
    --iter-time 2000 \
    --batch-mode \
    $LOOP_DEV
```

`--key-size 512` gives AES-256-XTS (two 256-bit halves); `--key-size 256`
would give AES-128-XTS.

`--pbkdf pbkdf2` selects PBKDF2 for key stretching.  PBKDF2 uses only
sha256 and hmac(sha256), both provided by wolfSSL.  The LUKS2 default,
Argon2, runs in userspace and does not go through the kernel crypto API.

(3) **Open the volume:**

```
# cryptsetup luksOpen $LOOP_DEV myluks
# ls -l /dev/mapper/myluks
lrwxrwxrwx 1 root root 7 ... /dev/mapper/myluks -> ../dm-0
```

Confirm the cipher reported by dm-crypt:

```
# dmsetup table myluks
0 491520 crypt aes-xts-plain64 ...
```

(4) **Create a filesystem, mount, and verify:**

```
# mkfs.ext4 -q /dev/mapper/myluks
# mkdir -p /mnt/myluks
# mount /dev/mapper/myluks /mnt/myluks
# echo "wolfSSL LUKS test" > /mnt/myluks/test.txt
# cat /mnt/myluks/test.txt
wolfSSL LUKS test
```

(5) **Confirm wolfSSL is the active crypto provider:**

While the volume is open, `refcnt` on `xts(aes)` will be non-zero and the
module field will show `libwolfssl`:

```
$ grep -A10 "^name.*: xts(aes)$" /proc/crypto | grep "module\|refcnt"
module       : libwolfssl
refcnt       : 2
```

(6) **Unmount and close:**

```
# umount /mnt/myluks
# cryptsetup luksClose myluks
```

## Unloading the Module

Before `rmmod`, deregister wolfSSL's algorithms.  This is required when
`--enable-linuxkm-lkcapi-register` was used:

```
# sh -c 'echo 1 > /sys/module/libwolfssl/deinstall_algs'
# rmmod libwolfssl
```

`dmesg` will confirm:

```
wolfCrypt: 44 algorithms deregistered, 0 remain registered.
wolfCrypt 5.9.1 cleanup complete.
```

After unload, `/proc/crypto` will show the kernel's built-in drivers for
`xts(aes)`, `sha256`, and `hmac(sha256)` at their normal priority.

## Distro Compatibility

wolfSSL linuxkm requires `CONFIG_CRYPTO_FIPS=n` in the kernel.  If the
kernel has `CONFIG_CRYPTO_FIPS=y`, the wolfSSL build fails at compile time:

```
#error CONFIG_CRYPTO_MANAGER requires that CONFIG_CRYPTO_FIPS match HAVE_FIPS
```

Check your running kernel:

```
$ grep CONFIG_CRYPTO_FIPS /boot/config-$(uname -r)
CONFIG_CRYPTO_FIPS=n   ← supported
```

| Distro | Stock cloud kernel | Action required |
| :--- | :--- | :--- |
| Ubuntu (all versions) | `CONFIG_CRYPTO_FIPS=n` | None — use stock kernel |
| NixOS 25.11+ | `CONFIG_CRYPTO_FIPS=n` | None — use stock kernel |
| Fedora | `CONFIG_CRYPTO_FIPS=y` | Build custom kernel |
| Debian | `CONFIG_CRYPTO_FIPS=y` | Build custom kernel |
| CentOS / RHEL family | `CONFIG_CRYPTO_FIPS=y` | Build custom kernel |

For distros that require a custom kernel, build from source with
`CONFIG_CRYPTO_FIPS=n`.  This is the normal path for embedded and product
developers who own their kernel configuration.  Disable the option during
kernel configuration:

```
$ scripts/config --disable CONFIG_CRYPTO_FIPS
```

To use wolfSSL linuxkm against a FIPS kernel *without* recompiling it, a
wolfSSL FIPS license is required.  Contact <facts@wolfssl.com>.

## Troubleshooting

### `insmod: ERROR: could not insert module: Invalid module format`

The module was built with a different gcc than the kernel.  Find the compiler
version from `/proc/version` and rebuild with the matching gcc:

```
$ cat /proc/version | grep -oE 'gcc[^)]+\)'
```

### `insmod: ERROR: Required key not available`

`MODULE_SIG_FORCE=y` is active (Ubuntu Pro / FIPS kernels).  Enroll the
signing certificate into MOK before rebooting:

```
# mokutil --import signing_cert.pem
```

Then reboot and accept the enrollment in the UEFI MOK Manager.

### `/proc/crypto` shows `xts-aes-aesni` (not wolfcrypt) after insmod

wolfSSL was built without `--enable-linuxkm-lkcapi-register`.  Verify:

```
$ grep ENABLED_LINUXKM_LKCAPI_REGISTER Makefile | head -1
ENABLED_LINUXKM_LKCAPI_REGISTER = yes   ← must be yes
```

Reconfigure with the flag and rebuild.

### Build fails with `CONFIG_CRYPTO_FIPS` error

The running kernel has `CONFIG_CRYPTO_FIPS=y`.  Either rebuild the kernel
with `CONFIG_CRYPTO_FIPS=n`, or obtain a wolfSSL FIPS license.

### `make module` fails on `libwolfssl.ko.signed`

Expected.  The build system tries to self-sign using the kernel's own key,
which is not available.  The unsigned `linuxkm/libwolfssl.ko` is produced
before this step and is the correct build artifact.

### `rmmod: ERROR: Module libwolfssl is in use`

Either a LUKS volume is still open, or `deinstall_algs` was not triggered.
Close all open volumes, then:

```
# sh -c 'echo 1 > /sys/module/libwolfssl/deinstall_algs'
# rmmod libwolfssl
```

Note: on NixOS, wolfSSL's stdrng becomes the system entropy source and the
kernel holds a persistent refcount on it.  `rmmod` will report one remaining
algorithm.  This is expected; for a production NixOS system, declare the
module as a permanent boot-time module in `configuration.nix`.

### `sign-file` binary not found

Compile it from the kernel source:

```
$ gcc -o /tmp/sign-file \
    /usr/src/linux-headers-$(uname -r)/scripts/sign-file.c \
    -lssl -lcrypto
```

## References

- wolfSSL: <https://github.com/wolfSSL/wolfssl>
- wolfGuard (wolfSSL WireGuard): <https://github.com/wolfSSL/wolfGuard>
- cryptsetup / LUKS: <https://gitlab.com/cryptsetup/cryptsetup>
- Linux kernel crypto API: <https://www.kernel.org/doc/html/latest/crypto/>

## Getting help, support, sales, licensing, and FIPS certification

For supported FIPS 140-3 validated wolfCrypt (including the validated
kernel module), production licensing, the actual FIPS-certified code,
an actual FIPS certificate, and Operational Environment (OE) work to
extend that certificate to your specific platform, contact
wolfSSL Inc.

**Contact wolfSSL:**

- Email: <facts@wolfssl.com>
- Phone: +1 425 245 8247
- Web: <https://www.wolfssl.com/contact/>
- Products: <https://www.wolfssl.com/products/>
- FIPS 140-3 information: <https://www.wolfssl.com/license/fips/>
- Licensing: <https://www.wolfssl.com/license/>
- Support & Maintenance: <https://www.wolfssl.com/products/support-and-maintenance/>

**Download the supported, licensed wolfSSL:**
<https://www.wolfssl.com/download/>
