add wolfHSM recipe

pull/174/head
JacobBarthelmeh 2026-07-28 10:22:27 -06:00
parent 965c98d134
commit 7434ef2b9d
6 changed files with 231 additions and 0 deletions

View File

@ -12,6 +12,8 @@ This layer currently provides recipes for the following wolfSSL products:
- [wolfSSH lightweight SSH library](https://www.wolfssl.com/products/wolfssh/)
- [wolfMQTT lightweight MQTT client library](https://www.wolfssl.com/products/wolfmqtt/)
- [wolfTPM portable TPM 2.0 library](https://www.wolfssl.com/products/wolftpm/)
- [wolfHSM hardware security module framework](https://www.wolfssl.com/products/wolfhsm/)
(source staging only, see `recipes-wolfssl/wolfhsm/README.md`)
- [wolfSSL-py A Python wrapper for the wolfSSL library](https://github.com/wolfSSL/wolfssl-py)
- [wolfCrypt-py A Python Wrapper for the wolfCrypt API](https://github.com/wolfSSL/wolfcrypt-py)
- [wolfPKCS11 A PKCS#11 implementation using wolfSSL](https://github.com/wolfSSL/wolfpkcs11)

View File

@ -33,6 +33,8 @@ BBFILES += "${LAYERDIR}/recipes-wolfssl/wolfssl/*.bb \
${LAYERDIR}/recipes-wolfssl/wolfengine/wolfssl*.bbappend \
${LAYERDIR}/recipes-wolfssl/wolfboot/*.bb \
${LAYERDIR}/recipes-wolfssl/wolfboot/*.bbappend \
${LAYERDIR}/recipes-wolfssl/wolfhsm/*.bb \
${LAYERDIR}/recipes-wolfssl/wolfhsm/*.bbappend \
${LAYERDIR}/recipes-examples/wolfcrypt/wolfcryptbenchmark/*.bb \
${LAYERDIR}/recipes-examples/wolfcrypt/wolfcryptbenchmark/*.bbappend \
${LAYERDIR}/recipes-examples/wolfcrypt/wolfcrypttest/*.bb \
@ -110,6 +112,7 @@ PREFERRED_PROVIDER_wolfcrypt-py ??= "wolfcrypt-py"
PREFERRED_PROVIDER_wolfprovider ??= "wolfprovider"
PREFERRED_PROVIDER_wolfengine ??= "wolfengine"
PREFERRED_PROVIDER_wolfboot ??= "wolfboot"
PREFERRED_PROVIDER_wolfhsm ??= "wolfhsm"
BBFILES += "${@bb.utils.contains('WOLFSSL_TYPE', \
'fips', \

View File

@ -0,0 +1,94 @@
# wolfHSM (Yocto/OE recipe)
Stages [wolfHSM](https://github.com/wolfSSL/wolfHSM) sources and headers into
the sysroot so other recipes can compile them into their own binaries.
## Recipes
| Recipe | Purpose |
|---|---|
| `wolfhsm_git.bb` | Stages `wolfhsm/` (headers), `src/` and the selected `port/` directories to `${datadir}/wolfhsm`, plus a `wolfhsm.mk` build fragment. Also installs the headers at `${includedir}/wolfhsm`. |
## Why this stages source instead of building a library
wolfHSM is configured by the application that uses it. `wolfhsm/wh_settings.h`
does `#include "wolfhsm_cfg.h"` whenever `WOLFHSM_CFG` is defined, and that
header selects the transport, the NVM backend, buffer sizes, whether crypto is
compiled in at all, and much else besides. Two consumers with different
`wolfhsm_cfg.h` files do not share an ABI, so there is no single `libwolfhsm`
that would be correct to ship.
wolfHSM also has no build system to drive: its top-level `Makefile` only
recurses into `test/`, `benchmark/`, `tools/` and `examples/`, each of which
brings its own `wolfhsm_cfg.h`. Upstream expects you to compile `src/*.c` and
one `port/*/` directory directly into your application. This recipe makes that
possible from a Yocto build without vendoring a checkout.
## Consuming it from a recipe
```bitbake
DEPENDS += "wolfhsm"
do_compile() {
oe_runmake WOLFHSM_DIR="${STAGING_DATADIR}/wolfhsm"
}
```
Your Makefile then compiles `$(WOLFHSM_DIR)/src/*.c` and
`$(WOLFHSM_DIR)/port/posix/*.c` with `-I$(WOLFHSM_DIR) -DWOLFHSM_CFG` and an
include path pointing at your own `wolfhsm_cfg.h`.
Alternatively, include the staged fragment and use the variables it defines:
```make
include $(WOLFHSM_DIR)/wolfhsm.mk
CFLAGS += $(WOLFHSM_INC) -DWOLFHSM_CFG -I$(MY_CONFIG_DIR)
SRC += $(WOLFHSM_SRC) $(WOLFHSM_PORT_SRC)
```
`wolfhsm.mk` resolves `WOLFHSM_DIR` from its own location, so it works
unchanged from a recipe sysroot, an SDK sysroot, or a plain copy.
## Selecting ports
wolfHSM ships ports for `posix`, `skeleton`, `microchip`, `infineon`,
`stmicro`, `renesas` and `ti`. Only `posix` is staged by default; staging all
of them would put a lot of unrelated vendor code in every sysroot. Override in
`local.conf` or a bbappend:
```bitbake
WOLFHSM_PORTS = "posix infineon"
```
Naming a port that does not exist in the source tree is a `bbfatal` rather
than a silent no-op.
## Packaging
Everything lands in `wolfhsm-dev`; `FILES:${PN}` is explicitly emptied so the
default `${datadir}/${BPN}` claim cannot pull the staging directory into a
runtime package. wolfHSM source is a build input, not a runtime artifact, and
should never appear in a target rootfs. `RDEPENDS:${PN}-dev` is cleared for the
same reason: bitbake's default would make `wolfhsm-dev` depend on a runtime
`wolfhsm` package that is deliberately never produced.
To cross-compile a wolfHSM consumer from an SDK, have the consumer's own `-dev`
package pull the headers in:
```bitbake
RDEPENDS:${PN}-dev += "wolfhsm-dev"
```
or, if there is no such consumer package, add it to the SDK directly:
```bitbake
TOOLCHAIN_TARGET_TASK:append = " wolfhsm-dev"
```
## Pinning
`SRCREV` is pinned in `wolfhsm.inc`. Override per-build with:
```bitbake
SRCREV:pn-wolfhsm = "<sha>"
```

View File

@ -0,0 +1,25 @@
## wolfhsm.mk - build fragment for consumers of the staged wolfHSM sources.
##
## wolfHSM has no build system of its own; it is compiled into the application
## that supplies wolfhsm_cfg.h. Include this fragment to get the source lists
## and include paths for doing that:
##
## include $(SDKTARGETSYSROOT)/usr/share/wolfhsm/wolfhsm.mk
## CFLAGS += $(WOLFHSM_INC) -DWOLFHSM_CFG -I$(MY_CONFIG_DIR)
## SRC += $(WOLFHSM_SRC) $(WOLFHSM_PORT_SRC)
##
## $(MY_CONFIG_DIR) must contain your wolfhsm_cfg.h. -DWOLFHSM_CFG is what
## makes wolfhsm/wh_settings.h include it.
# Resolved from this fragment's own location, so it is correct whether it is
# read out of a recipe sysroot, an SDK sysroot, or a plain copy.
WOLFHSM_DIR ?= $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
# Which platform port to compile. Only ports listed in WOLFHSM_PORTS at
# recipe-build time are present here.
WOLFHSM_PORT ?= posix
WOLFHSM_PORT_DIR ?= $(WOLFHSM_DIR)/port/$(WOLFHSM_PORT)
WOLFHSM_SRC := $(wildcard $(WOLFHSM_DIR)/src/*.c)
WOLFHSM_PORT_SRC := $(wildcard $(WOLFHSM_PORT_DIR)/*.c)
WOLFHSM_INC := -I$(WOLFHSM_DIR) -I$(WOLFHSM_PORT_DIR)

View File

@ -0,0 +1,19 @@
# Shared include for wolfHSM recipes.
#
# wolfHSM is a hardware security module framework: a client/server protocol
# plus a set of platform "ports" mapping transport, flash, time and lock
# primitives onto a given target.
HOMEPAGE = "https://www.wolfssl.com/products/wolfhsm"
BUGTRACKER = "https://github.com/wolfSSL/wolfHSM/issues"
SECTION = "libs"
LICENSE = "GPL-3.0-only"
LIC_FILES_CHKSUM = "file://LICENSE;md5=1ebbd3e34237af26da5dc08a4e440464"
# NOTE: pinned to a wolfSSL/wolfHSM main tip at the time of writing. Bump as
# upstream evolves. Downstream users can override via local.conf:
# SRCREV:pn-wolfhsm = "<sha>"
SRC_URI = "git://github.com/wolfSSL/wolfHSM.git;protocol=https;branch=main"
SRCREV ?= "4aeecb2c35686bd4daeb40b3537500d15a93aff9"
S = "${WORKDIR}/git"

View File

@ -0,0 +1,88 @@
SUMMARY = "wolfHSM hardware security module framework (source staging)"
DESCRIPTION = "wolfHSM provides a client/server protocol for offloading key \
storage and cryptographic operations to a secure processor or enclave, plus \
platform ports supplying the transport, flash, time and lock primitives. \
This recipe stages the wolfHSM sources and headers for other recipes to \
compile in-tree; it does not build a library. See the note below."
# WHY THIS STAGES SOURCE INSTEAD OF BUILDING A LIBRARY
#
# wolfHSM is configured by the application that uses it: wolfhsm/wh_settings.h
# does `#include "wolfhsm_cfg.h"` whenever WOLFHSM_CFG is defined, and that
# header selects the transport, the NVM backend, buffer sizes, whether crypto
# is compiled in at all, and much else. Two consumers with different
# wolfhsm_cfg.h files do not share an ABI, so there is no single libwolfhsm
# that would be correct to ship.
#
# wolfHSM also has no build system to drive: its top-level Makefile only
# recurses into test/, benchmark/, tools/ and examples/, each of which brings
# its own wolfhsm_cfg.h. Upstream expects you to compile src/*.c and one
# port/*/ directory directly into your application, which is what this recipe
# makes possible from a Yocto build.
#
# Consumers therefore DEPEND on wolfhsm and point their build at
# ${STAGING_DATADIR}/wolfhsm, supplying their own wolfhsm_cfg.h. See README.md.
require wolfhsm.inc
SRC_URI += "file://wolfhsm.mk"
# Which port/ directories to stage. wolfHSM ships ports for posix, skeleton,
# microchip, infineon, stmicro, renesas and ti; staging all of them would put
# a lot of unrelated vendor code in every sysroot. Override in local.conf or a
# bbappend, e.g. WOLFHSM_PORTS = "posix infineon".
WOLFHSM_PORTS ?= "posix"
PV = "1.4.0+git"
# Nothing to build. See the note above.
do_configure[noexec] = "1"
do_compile[noexec] = "1"
do_install() {
install -d ${D}${datadir}/wolfhsm
# Headers and core sources. Consumers add -I${STAGING_DATADIR}/wolfhsm so
# that #include "wolfhsm/wh_client.h" resolves, which is why the wolfhsm/
# directory is preserved rather than flattened.
cp -R --no-dereference --preserve=mode,timestamps \
${S}/wolfhsm ${S}/src ${D}${datadir}/wolfhsm/
install -d ${D}${datadir}/wolfhsm/port
for port in ${WOLFHSM_PORTS}; do
if [ ! -d ${S}/port/$port ]; then
bbfatal "WOLFHSM_PORTS names '$port' but ${S}/port/$port does not exist."
fi
cp -R --no-dereference --preserve=mode,timestamps \
${S}/port/$port ${D}${datadir}/wolfhsm/port/
done
# Also expose the headers at the conventional include path, for consumers
# that only need to call the client API against a library someone else
# already compiled (e.g. an application linking a vendor's libwolfhsm).
install -d ${D}${includedir}/wolfhsm
install -m 0644 ${S}/wolfhsm/*.h ${D}${includedir}/wolfhsm/
# ${WORKDIR}, not ${UNPACKDIR}: the layer still supports pre-styhead
# releases (LAYERSERIES_COMPAT reaches back to sumo) where file:// SRC_URI
# entries unpack straight into ${WORKDIR}.
install -m 0644 ${WORKDIR}/wolfhsm.mk ${D}${datadir}/wolfhsm/wolfhsm.mk
}
# ${datadir} is already part of the default SYSROOT_DIRS; named explicitly so
# the staging behaviour this recipe depends on is visible at a glance.
SYSROOT_DIRS += "${datadir}/wolfhsm"
# Everything lands in -dev. wolfHSM source has no business in a target rootfs:
# it is a build input, not a runtime artifact. FILES:${PN} is emptied because
# the default value claims ${datadir}/${BPN}, which is exactly our staging dir.
FILES:${PN} = ""
FILES:${PN}-dev = "${datadir}/wolfhsm ${includedir}/wolfhsm"
# bitbake.conf defaults RDEPENDS:${PN}-dev to "${PN} (= ${EXTENDPKGV})". With
# no files in ${PN} that package is never produced, which would leave
# wolfhsm-dev with an unsatisfiable runtime dependency at rootfs/SDK install
# time. There is nothing at runtime to depend on, so clear it.
RDEPENDS:${PN}-dev = ""
BBCLASSEXTEND = "native nativesdk"