Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 70 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,8 @@ For building commercial bundles of wolfSSL products, view the
instructions in this
[README](recipes-wolfssl/wolfssl/commercial/README.md).

For FIPS-Ready builds, view the instructions in this
[README](recipes-wolfssl/wolfssl/fips-ready/README.md).
For FIPS-Ready builds, see the [Using wolfssl-fips-ready
Recipe](#using-wolfssl-fips-ready-recipe) section below.

To gain access to these bundles, contact support@wolfssl.com to get a quote.

Expand All @@ -578,9 +578,9 @@ between open-source, FIPS, and commercial versions of wolfSSL.
recipes:
- `wolfssl` (open-source) - Default provider from meta-networking
- `wolfssl-fips` (FIPS-validated) - Provided by this layer
- `wolfssl-fips-ready` (FIPS Ready - emulates FIPS 140-3 requirements
without full validation) - Provided by this layer
- Future: `wolfssl-commercial` - For commercial non-FIPS bundles
- Future: `wolfssl-fips-ready` - For FIPS Ready bundle builds (Emulates FIPS
Requirements)

When you set `PREFERRED_PROVIDER_virtual/wolfssl = "wolfssl-fips"`, all
recipes that depend on `virtual/wolfssl` will automatically use the
Expand Down Expand Up @@ -655,6 +655,72 @@ The `conf/wolfssl-fips.conf` file is automatically ignored by git (via
`.gitignore`), keeping your bundle password and license information private.
Only the `.sample` template is tracked in git.

### Using wolfssl-fips-ready Recipe

The `wolfssl-fips-ready` recipe builds wolfSSL from a publicly available
**FIPS Ready** bundle (`wolfssl-x.x.x-gplv3-fips-ready.zip`, GPLv3). FIPS
Ready emulates the FIPS 140-3 module layout and self-tests but is **not**
a certified FIPS build — use it to develop and validate your integration
before acquiring a commercial FIPS bundle.

A companion recipe, `wolfssl-linuxkm-fips-ready`, builds the wolfSSL FIPS
kernel module (`libwolfssl.ko`) from the same bundle, suitable for loading
via initramfs or modprobe.

For a full working integration (RPi5 + QEMU aarch64, with libgcrypt,
GnuTLS, wolfProvider, and kernel-module loading via initramfs), see the
[meta-wolfssl-linux-fips](https://github.com/wolfSSL/wolfssl-examples/tree/master/meta-wolfssl-linux-fips)
example in the `wolfssl-examples` repo.

#### Setup Instructions

1. **Copy the configuration template:**
```bash
cd meta-wolfssl
cp conf/wolfssl-fips-ready.conf.sample conf/wolfssl-fips-ready.conf
```

2. **Download the FIPS Ready bundle** from
[wolfSSL's download page](https://www.wolfssl.com/download/)
(`wolfssl-x.x.x-gplv3-fips-ready.zip`) and place it anywhere on disk.

3. **Edit `conf/wolfssl-fips-ready.conf`:**
- `WOLFSSL_VERSION` - Bundle version (e.g., `"5.8.4"`)
- `WOLFSSL_SRC` - Bundle name without extension
(e.g., `"wolfssl-5.8.4-gplv3-fips-ready"`)
- `WOLFSSL_BUNDLE_FILE` - Archive filename (`${WOLFSSL_SRC}.zip`)
- `WOLFSSL_SRC_SHA` - SHA256 of the `.zip`
- `WOLFSSL_SRC_DIR` - Absolute path to the directory containing the `.zip`
- `WOLFSSL_LICENSE_MD5` - MD5 of the `COPYING` (GPLv3) file inside the zip
- `FIPS_HASH` - Leave as placeholder when using `WOLFSSL_FIPS_HASH_MODE =
"auto"` (default); set manually after first build if using `"manual"`

4. **Include the configuration in `build/conf/local.conf`:**
```bitbake
require /path/to/meta-wolfssl/conf/wolfssl-fips-ready.conf
```

This automatically sets
`PREFERRED_PROVIDER_virtual/wolfssl = "wolfssl-fips-ready"`.

5. **Build your image:**
```bash
bitbake <your-image>
```

Hash extraction (auto mode) runs transparently via QEMU during the
wolfSSL build.

#### Kernel Module (wolfssl-linuxkm-fips-ready)

To additionally build the FIPS Ready kernel module, depend on
`wolfssl-linuxkm-fips-ready` from an image recipe (typically via an
initramfs that includes it). The same `wolfssl-fips-ready.conf` values
apply — no separate bundle is required.

Comment thread
JacobBarthelmeh marked this conversation as resolved.
See [README-linuxkm.md](recipes-wolfssl/wolfssl/README-linuxkm.md) for
module signing and initramfs integration details.

### Commercial Bundles from Google Cloud Storage

BitBake ships with a GCS fetcher. To use it with `wolfssl-fips`:
Expand Down Expand Up @@ -733,8 +799,6 @@ This repository contains additional README files with detailed information:
### Commercial/FIPS
- [recipes-wolfssl/wolfssl/commercial/README.md](recipes-wolfssl/wolfssl/commercial/README.md)
- Commercial/FIPS bundle instructions
- [recipes-wolfssl/wolfssl/fips-ready/README.md](recipes-wolfssl/wolfssl/fips-ready/README.md)
- FIPS-Ready build instructions

### OSP Integrations
- [recipes-support/libgcrypt/README.md](recipes-support/libgcrypt/README.md)
Expand Down
4 changes: 2 additions & 2 deletions classes/wolfssl-helper.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def wolfssl_conditional_require_mode(d, package_name, mode, inc_file=None):
bb.debug(2, f"{package_name}: {mode_var_name}='{current_mode_str}' does not contain '{single_mode}' - skipping")
continue

bb.note(f"{package_name}: {mode_var_name}='{current_mode_str}' contains '{single_mode}' mode - including {single_inc}")
bb.debug(2, f"{package_name}: {mode_var_name}='{current_mode_str}' contains '{single_mode}' mode - including {single_inc}")
full_inc_file = os.path.join(layerdir, single_inc)
bb.parse.mark_dependency(d, full_inc_file)
try:
Expand Down Expand Up @@ -157,7 +157,7 @@ def wolfssl_conditional_require_flag(d, flag_name, inc_file):
return False

# Flag found in list - include the configuration
bb.note(f"{package_name}: {flags_var_name}='{current_flags_str}' contains '{flag_name}' flag - including {inc_file}")
bb.debug(2, f"{package_name}: {flags_var_name}='{current_flags_str}' contains '{flag_name}' flag - including {inc_file}")

layerdir = d.getVar('WOLFSSL_LAYERDIR')
if not layerdir:
Expand Down
10 changes: 5 additions & 5 deletions classes/wolfssl-osp-support.bbclass
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ def wolfssl_osp_conditional_include(d, feature_name, inc_file, allowed_providers

# Check if current provider is in the allowed list
if current_provider not in allowed_providers:
bb.note(f"{feature_name}: PREFERRED_PROVIDER is '{current_provider}', but only {allowed_providers} are supported - skipping wolfSSL backend")
bb.debug(2, f"{feature_name}: PREFERRED_PROVIDER is '{current_provider}', but only {allowed_providers} are supported - skipping wolfSSL backend")
return False

# Both conditions met - include the configuration
bb.note(f"{feature_name}: WOLFSSL_FEATURES enabled + provider '{current_provider}' allowed - enabling wolfSSL backend")
bb.debug(2, f"{feature_name}: WOLFSSL_FEATURES enabled + provider '{current_provider}' allowed - enabling wolfSSL backend")

# Resolve full path to include file
layer_dir = d.getVar('WOLFSSL_LAYERDIR')
Expand Down Expand Up @@ -130,11 +130,11 @@ def wolfssl_conditional_include_ext(d, enable_for, inc_file, allowed_providers=N

# Check if current provider is in the allowed list
if current_provider not in allowed_providers:
bb.note(f"{enable_for}: PREFERRED_PROVIDER is '{current_provider}', but only {allowed_providers} are supported - skipping wolfSSL backend")
bb.debug(2, f"{enable_for}: PREFERRED_PROVIDER is '{current_provider}', but only {allowed_providers} are supported - skipping wolfSSL backend")
return False

# All conditions met - include the configuration
bb.note(f"{enable_for}: IMAGE_INSTALL/WOLFSSL_FEATURES enabled + provider '{current_provider}' allowed - enabling wolfSSL backend")
bb.debug(2, f"{enable_for}: IMAGE_INSTALL/WOLFSSL_FEATURES enabled + provider '{current_provider}' allowed - enabling wolfSSL backend")

# Resolve full path to include file
layer_dir = d.getVar('WOLFSSL_LAYERDIR')
Expand Down Expand Up @@ -213,7 +213,7 @@ def wolfssl_osp_include_if_provider(d, inc_file, allowed_providers):
bb.debug(2, f"Current provider '{current_provider}' not in {allowed_providers} - skipping configuration")
return False

bb.note(f"Provider '{current_provider}' matches - including {inc_file}")
bb.debug(2, f"Provider '{current_provider}' matches - including {inc_file}")

# Resolve full path to include file
layer_dir = d.getVar('WOLFSSL_LAYERDIR')
Expand Down
47 changes: 47 additions & 0 deletions conf/wolfssl-fips-ready.conf.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# wolfSSL FIPS Ready Configuration
#
# This file contains wolfSSL FIPS Ready bundle settings.
# Include this file in your local.conf:
# require /path/to/meta-wolfssl/conf/wolfssl-fips-ready.conf
#
# Instructions:
# 1. Set the variables below with your FIPS Ready bundle details
# 2. Set WOLFSSL_SRC_DIR to the directory containing your .zip bundle
# 3. Build once to get the FIPS_HASH value (if using manual mode)
# 4. Set FIPS_HASH and rebuild (if using manual mode)

# Use wolfSSL FIPS Ready as the wolfSSL provider
PREFERRED_PROVIDER_virtual/wolfssl = "wolfssl-fips-ready"
PREFERRED_PROVIDER_wolfssl = "wolfssl-fips-ready"

# FIPS hash mode: "auto" (QEMU-based extraction) or "manual" (use static FIPS_HASH)
WOLFSSL_FIPS_HASH_MODE ?= "auto"

# ============================================================================
# FIPS Ready Bundle Configuration - EDIT THESE VALUES
# ============================================================================

# Bundle version
WOLFSSL_VERSION = ""

# Bundle name (extracted directory name, without extension)
WOLFSSL_SRC = ""

# Bundle archive filename (including .zip extension)
WOLFSSL_BUNDLE_FILE = ""

# Bundle SHA256 checksum
WOLFSSL_SRC_SHA = ""

# Directory containing the .zip bundle (REQUIRED - must be set)
WOLFSSL_SRC_DIR = ""

# MD5 of the COPYING (GPLv3) license file in the bundle
WOLFSSL_LICENSE_MD5 ?= ""

# FIPS hash (only needed for manual mode - set after first build)
FIPS_HASH = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"

# ============================================================================
# Contact support@wolfssl.com for commercial FIPS Ready bundles
# ============================================================================
4 changes: 2 additions & 2 deletions inc/curl/curl-enable-wolfprovider-fips.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def curl_get_wolfprovider_fips_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("curl-enable-wolfprovider-fips.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"curl-enable-wolfprovider-fips.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def curl_get_wolfprovider_fips_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/curl/%s/curl-enable-wolfprovider-fips-legacy.inc' % codename)

bb.note("curl-enable-wolfprovider-fips.inc: Including file: %s" % inc_file)
bb.debug(2,"curl-enable-wolfprovider-fips.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
4 changes: 2 additions & 2 deletions inc/gnupg/gnupg-enable-libgcrypt-wolfssl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def gnupg_get_libgcrypt_wolfssl_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("gnupg-enable-libgcrypt-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"gnupg-enable-libgcrypt-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def gnupg_get_libgcrypt_wolfssl_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/gnupg/%s/gnupg-enable-libgcrypt-wolfssl-legacy.inc' % codename)

bb.note("gnupg-enable-libgcrypt-wolfssl.inc: Including file: %s" % inc_file)
bb.debug(2,"gnupg-enable-libgcrypt-wolfssl.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
4 changes: 2 additions & 2 deletions inc/gnutls/gnutls-enable-wolfssl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def gnutls_get_wolfssl_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("gnutls-enable-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"gnutls-enable-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def gnutls_get_wolfssl_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/gnutls/%s/gnutls-enable-wolfssl-legacy.inc' % codename)

bb.note("gnutls-enable-wolfssl.inc: Including file: %s" % inc_file)
bb.debug(2,"gnutls-enable-wolfssl.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
6 changes: 3 additions & 3 deletions inc/gnutls/scarthgap/gnutls-enable-wolfssl-modern.inc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ SRCREV:class-target = "${AUTOREV}"
S:class-target = "${WORKDIR}/git"
B:class-target = "${S}"

# Enable FIPS mode only if using wolfssl-fips provider
PACKAGECONFIG:append:class-target = "${@' fips' if d.getVar('PREFERRED_PROVIDER_virtual/wolfssl') == 'wolfssl-fips' else ''}"
# Enable FIPS mode when using a wolfSSL FIPS provider
PACKAGECONFIG:append:class-target = "${@' fips' if d.getVar('PREFERRED_PROVIDER_virtual/wolfssl') in ('wolfssl-fips', 'wolfssl-fips-ready') else ''}"

# Configure options for wolfSSL backend
EXTRA_OECONF:class-target = "\
Expand All @@ -34,7 +34,7 @@ EXTRA_OECONF:class-target = "\
--disable-dependency-tracking \
--enable-srp-authentication \
--enable-fips140-mode \
Comment thread
JacobBarthelmeh marked this conversation as resolved.
${@'--enable-fips140-mode' if d.getVar('PREFERRED_PROVIDER_virtual/wolfssl') == 'wolfssl-fips' else ''} \
${@'--enable-fips140-mode' if d.getVar('PREFERRED_PROVIDER_virtual/wolfssl') in ('wolfssl-fips', 'wolfssl-fips-ready') else ''} \
"

TARGET_CFLAGS:append:class-target = " -DGNUTLS_WOLFSSL"
Expand Down
4 changes: 2 additions & 2 deletions inc/libgcrypt/libgcrypt-enable-wolfssl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def libgcrypt_get_wolfssl_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("libgcrypt-enable-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"libgcrypt-enable-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def libgcrypt_get_wolfssl_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/libgcrypt/%s/libgcrypt-enable-wolfssl-legacy.inc' % codename)

bb.note("libgcrypt-enable-wolfssl.inc: Including file: %s" % inc_file)
bb.debug(2,"libgcrypt-enable-wolfssl.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
11 changes: 9 additions & 2 deletions inc/libgcrypt/scarthgap/libgcrypt-enable-wolfssl-modern.inc
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# libgcrypt with wolfSSL FIPS backend
#
# This include file configures libgcrypt to use wolfSSL/wolfCrypt as the crypto backend.
# Only applied when wolfssl-fips is the active provider.
# Supports both wolfssl-fips and wolfssl-fips-ready providers.

# Select the git branch based on the active wolfSSL provider
WOLFSSL_LIBGCRYPT_BRANCH = "${@'libgcrypt-1.11.0-wolfCrypt-fips-ready' if d.getVar('PREFERRED_PROVIDER_virtual/wolfssl') == 'wolfssl-fips-ready' else 'libgcrypt-1.11.0-wolfCrypt'}"

# Override to use custom git repo and version - TARGET ONLY

Expand All @@ -15,7 +18,7 @@ LIC_FILES_CHKSUM:class-target = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a
"

# Override source to use wolfSSL-enabled git repo
SRC_URI:class-target = "git://github.com/wolfSSL/libgcrypt-wolfssl.git;protocol=https;branch=libgcrypt-1.11.0-wolfCrypt \
SRC_URI:class-target = "git://github.com/wolfSSL/libgcrypt-wolfssl.git;protocol=https;branch=${WOLFSSL_LIBGCRYPT_BRANCH} \
file://run-ptest \
file://wc_ptest-fixes.patch \
"
Expand All @@ -36,6 +39,10 @@ RDEPENDS:${PN}:append:class-target = " wolfssl"
# Add wolfSSL FIPS configuration flag
EXTRA_OECONF:append:class-target = " --enable-wolfssl-fips --with-wolfssl=${STAGING_EXECPREFIXDIR} --disable-jent-support --disable-doc"

# Additional CFLAGS for fips-ready:
# - AES_BLOCK_SIZE is not exported by fips-ready wolfSSL headers
CFLAGS:append:class-target = "${@' -DAES_BLOCK_SIZE=WC_AES_BLOCK_SIZE' if d.getVar('PREFERRED_PROVIDER_virtual/wolfssl') == 'wolfssl-fips-ready' else ''}"

# In FIPS mode, some tests are excluded - install only tests that were actually built
do_install_ptest:class-target() {
cd ${B}/tests
Expand Down
4 changes: 2 additions & 2 deletions inc/libssh/libssh-enable-libgcrypt-wolfssl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def libssh_get_libgcrypt_wolfssl_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("libssh-enable-libgcrypt-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"libssh-enable-libgcrypt-wolfssl.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def libssh_get_libgcrypt_wolfssl_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/libssh/%s/libssh-enable-libgcrypt-wolfssl-legacy.inc' % codename)

bb.note("libssh-enable-libgcrypt-wolfssl.inc: Including file: %s" % inc_file)
bb.debug(2,"libssh-enable-libgcrypt-wolfssl.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
4 changes: 2 additions & 2 deletions inc/nettle/nettle.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def nettle_get_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("nettle.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"nettle.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def nettle_get_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/nettle/%s/nettle-legacy.inc' % codename)

bb.note("nettle.inc: Including file: %s" % inc_file)
bb.debug(2,"nettle.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
4 changes: 2 additions & 2 deletions inc/rsyslog/rsyslog-enable-fips-crypto.inc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ def rsyslog_get_fips_crypto_inc(d):
import os
layerseries = d.getVar('LAYERSERIES_CORENAMES') or ""

bb.note("rsyslog-enable-fips-crypto.inc: LAYERSERIES_CORENAMES = %s" % layerseries)
bb.debug(2,"rsyslog-enable-fips-crypto.inc: LAYERSERIES_CORENAMES = %s" % layerseries)

# Check if version is 3.1 or newer (dunfell and later)
use_modern = False
Expand All @@ -23,7 +23,7 @@ def rsyslog_get_fips_crypto_inc(d):
else:
inc_file = os.path.join(layerdir, 'inc/rsyslog/%s/rsyslog-enable-fips-crypto-legacy.inc' % codename)

bb.note("rsyslog-enable-fips-crypto.inc: Including file: %s" % inc_file)
bb.debug(2,"rsyslog-enable-fips-crypto.inc: Including file: %s" % inc_file)
return inc_file

# Include the appropriate file
Expand Down
Loading