add option to use external wolfSSL source with wolfBOOT build
parent
5ed8935a9a
commit
965c98d134
|
|
@ -83,6 +83,47 @@ Artifacts deployed to `tmp/deploy/images/<MACHINE>/`:
|
|||
Note: the private signing key is **not** deployed — it stays on the
|
||||
workstation / secrets store you pointed `WOLFBOOT_SIGNING_KEY` at.
|
||||
|
||||
## Using an existing wolfSSL source tree
|
||||
|
||||
By default `wolfboot.inc` fetches a pinned wolfSSL (`SRCREV_wolfssl`) into
|
||||
`lib/wolfssl` alongside wolfBoot. To build wolfCrypt from a tree you already
|
||||
have instead, set an absolute path in `local.conf`:
|
||||
|
||||
```
|
||||
WOLFBOOT_WOLFSSL_SRC = "/path/to/wolfssl"
|
||||
```
|
||||
|
||||
This drops the wolfSSL entry from `SRC_URI` entirely — nothing is downloaded
|
||||
and `SRCREV_wolfssl` is unused. Both `wolfboot_git.bb` and
|
||||
`wolfboot-keytools-native_git.bb` pick it up, so the bootloader and the
|
||||
signing tools stay on one wolfCrypt version.
|
||||
|
||||
Things worth knowing:
|
||||
|
||||
- **It is a source tree, not a library.** wolfBoot compiles the wolfCrypt
|
||||
sources into a `-nostdlib` bare-metal image; it cannot link the target
|
||||
`libwolfssl.so` that the `wolfssl` recipe builds. Point this at wolfSSL
|
||||
*sources*.
|
||||
- **The tree is copied into `${WORKDIR}` before use**, by the
|
||||
`do_stage_external_wolfssl` task. wolfBoot writes its object files next to
|
||||
the wolfCrypt sources, so an in-place build would dirty your tree. The
|
||||
original may therefore be read-only or shared, but the copy is a full one —
|
||||
prefer a clean source tree over a working directory with a large `.git` and
|
||||
build output in it.
|
||||
- **Prebuilt objects are excluded** from that copy (`*.o`, `*.a`, `*.lo`,
|
||||
`*.la`, `*.so*`, `.libs`, `.git`). Without this, a natively configured tree
|
||||
(`./configure && make`) would hand the cross build host x86 objects that
|
||||
`make` considers newer than their sources.
|
||||
- **Changes to the tree do trigger a rebuild.** The recipe fingerprints every
|
||||
file's path, size and mtime into the task hashes, since BitBake would
|
||||
otherwise hash only the `WOLFBOOT_WOLFSSL_SRC` string and happily reuse a
|
||||
stale `wolfboot.elf`.
|
||||
- The path must be absolute. wolfBoot's `Makefile` abspaths
|
||||
`WOLFBOOT_LIB_WOLFSSL` only for its own default; a command-line override —
|
||||
how the recipe passes it — reaches every sub-makefile verbatim. The recipe
|
||||
rejects relative paths rather than let them resolve against whichever
|
||||
directory each sub-make runs in.
|
||||
|
||||
## SD card layout (wolfBoot A/B scheme)
|
||||
|
||||
| Partition | Size | Type | Contents |
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
SUMMARY = "wolfBoot signing and key generation tools (native)"
|
||||
DESCRIPTION = "Host-side keygen and sign utilities for wolfBoot secure-boot \
|
||||
image signing. Builds RSA4096 signing keys and signs firmware images with \
|
||||
SHA3-384 hashes. Uses wolfBoot's bundled wolfCrypt (under lib/wolfssl) -- \
|
||||
no external wolfSSL dependency."
|
||||
SHA3-384 hashes. Uses wolfBoot's bundled wolfCrypt (under lib/wolfssl) by \
|
||||
default, or the tree named by WOLFBOOT_WOLFSSL_SRC when that is set."
|
||||
|
||||
require wolfboot.inc
|
||||
|
||||
|
|
@ -12,11 +12,23 @@ do_configure[noexec] = "1"
|
|||
|
||||
do_compile() {
|
||||
# Build the keytools (host-side signing/keygen utilities).
|
||||
#
|
||||
# Track wolfboot_git.bb's choice of wolfCrypt: the keytools produce the
|
||||
# keystore and the image signatures that wolfboot.elf then verifies, so
|
||||
# building the two halves from different wolfSSL versions risks a format
|
||||
# mismatch that only shows up as a failed verification on the target.
|
||||
# tools/keytools/Makefile also emits its objects under
|
||||
# $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src, hence the staged copy here too.
|
||||
WOLFSSL_DIR="${S}/lib/wolfssl"
|
||||
if [ -n "${WOLFBOOT_WOLFSSL_SRC}" ]; then
|
||||
WOLFSSL_DIR="${WOLFBOOT_WOLFSSL_STAGED_SRC}"
|
||||
fi
|
||||
|
||||
oe_runmake -C tools/keytools \
|
||||
CC="${CC}" \
|
||||
LD="${CC}" \
|
||||
WOLFBOOTDIR=${S} \
|
||||
WOLFBOOT_LIB_WOLFSSL=${S}/lib/wolfssl \
|
||||
WOLFBOOT_LIB_WOLFSSL="$WOLFSSL_DIR" \
|
||||
V=1
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
# Pulls the wolfBoot source tree and the wolfSSL submodule source side-by-side.
|
||||
# wolfBoot bundles wolfSSL under lib/wolfssl, so we stage wolfSSL there instead
|
||||
# of fetching it from the wolfBoot submodule pointer (keeps the two SRCREVs
|
||||
# explicit and greppable).
|
||||
# explicit and greppable). Set WOLFBOOT_WOLFSSL_SRC to build against an
|
||||
# existing wolfSSL source tree instead, see the block below.
|
||||
|
||||
HOMEPAGE = "https://github.com/wolfssl/wolfBoot"
|
||||
BUGTRACKER = "https://github.com/wolfssl/wolfBoot/issues"
|
||||
|
|
@ -11,6 +12,26 @@ SECTION = "bootloaders"
|
|||
LICENSE = "GPL-3.0-only"
|
||||
LIC_FILES_CHKSUM = "file://LICENSE;md5=1ebbd3e34237af26da5dc08a4e440464"
|
||||
|
||||
# --- Optional: build against an existing wolfSSL source tree ----------------
|
||||
#
|
||||
# Set WOLFBOOT_WOLFSSL_SRC to the absolute path of a wolfSSL source tree to
|
||||
# build wolfCrypt from it instead of the pinned copy fetched below. When it is
|
||||
# set the wolfSSL entry drops out of SRC_URI entirely and nothing is downloaded
|
||||
# making SRCREV_wolfssl unused.
|
||||
#
|
||||
# NOTE: this reuses a source *tree*, not a built library. wolfBoot compiles the
|
||||
# wolfCrypt sources itself into a -nostdlib bare-metal image; it can never link
|
||||
# against the target libwolfssl.so that the wolfssl recipe produces.
|
||||
WOLFBOOT_WOLFSSL_SRC ?= ""
|
||||
|
||||
# Private copy of that tree, made by do_stage_external_wolfssl below. The copy
|
||||
# is not an optimisation: wolfBoot compiles objects *alongside* the wolfCrypt
|
||||
# sources ($(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/*.o, in both options.mk and
|
||||
# tools/keytools/Makefile), so building in place would write into the caller's
|
||||
# tree -- and race with it if it belongs to another recipe. Copying also lets
|
||||
# WOLFBOOT_WOLFSSL_SRC live somewhere read-only or shared.
|
||||
WOLFBOOT_WOLFSSL_STAGED_SRC = "${WORKDIR}/wolfssl-external"
|
||||
|
||||
# NOTE: SRCREVs below are pinned to wolfSSL/wolfBoot master and
|
||||
# wolfSSL/wolfssl master tips at the time of writing. Bump these as
|
||||
# upstream evolves. Downstream users can override via local.conf:
|
||||
|
|
@ -18,11 +39,93 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=1ebbd3e34237af26da5dc08a4e440464"
|
|||
# SRCREV_wolfboot:pn-wolfboot-keytools-native = "<sha>"
|
||||
SRC_URI = " \
|
||||
git://github.com/wolfssl/wolfBoot.git;protocol=https;branch=master;name=wolfboot;destsuffix=git \
|
||||
git://github.com/wolfssl/wolfssl.git;protocol=https;branch=master;name=wolfssl;destsuffix=git/lib/wolfssl \
|
||||
${@'' if d.getVar('WOLFBOOT_WOLFSSL_SRC') else 'git://github.com/wolfssl/wolfssl.git;protocol=https;branch=master;name=wolfssl;destsuffix=git/lib/wolfssl'} \
|
||||
"
|
||||
SRCREV_wolfboot ?= "9a667f2a7527da2b8e490ae7923665321af2d3ac"
|
||||
SRCREV_wolfssl ?= "1d363f3adceba9d1478230ede476a37b0dcdef24"
|
||||
SRCREV_FORMAT = "wolfboot_wolfssl"
|
||||
SRCREV_FORMAT = "${@'wolfboot' if d.getVar('WOLFBOOT_WOLFSSL_SRC') else 'wolfboot_wolfssl'}"
|
||||
|
||||
def wolfboot_wolfssl_src_id(d):
|
||||
"""Fingerprint the external wolfSSL tree: relative path, size and mtime of
|
||||
every file. Fed into the task hashes below so that editing the tree rebuilds
|
||||
wolfBoot. BitBake otherwise hashes only the WOLFBOOT_WOLFSSL_SRC *string*,
|
||||
and changes to its contents would silently reuse a stale wolfboot.elf.
|
||||
Returns '' (and costs nothing) when the feature is not in use."""
|
||||
import os
|
||||
import hashlib
|
||||
|
||||
src = d.getVar('WOLFBOOT_WOLFSSL_SRC')
|
||||
if not src or not os.path.isdir(src):
|
||||
return ''
|
||||
|
||||
h = hashlib.sha256()
|
||||
for root, dirs, files in os.walk(src):
|
||||
# Same pruning as the copy below, so the fingerprint tracks exactly
|
||||
# what gets staged.
|
||||
dirs[:] = sorted(x for x in dirs if x not in ('.git', '.libs'))
|
||||
for name in sorted(files):
|
||||
path = os.path.join(root, name)
|
||||
try:
|
||||
st = os.lstat(path)
|
||||
except OSError:
|
||||
continue
|
||||
entry = '%s %d %d\n' % (os.path.relpath(path, src),
|
||||
st.st_size, st.st_mtime_ns)
|
||||
h.update(entry.encode())
|
||||
return h.hexdigest()
|
||||
|
||||
WOLFBOOT_WOLFSSL_SRC_ID = "${@wolfboot_wolfssl_src_id(d)}"
|
||||
|
||||
python check_wolfboot_wolfssl_src() {
|
||||
import os
|
||||
|
||||
src = d.getVar('WOLFBOOT_WOLFSSL_SRC') or ''
|
||||
if not src:
|
||||
return
|
||||
if not os.path.isabs(src):
|
||||
bb.fatal("WOLFBOOT_WOLFSSL_SRC='%s' must be an absolute path. wolfBoot's "
|
||||
"Makefile only abspaths WOLFBOOT_LIB_WOLFSSL when the value "
|
||||
"comes from a makefile; the recipe passes it on the make "
|
||||
"command line, which overrides that assignment, so a relative "
|
||||
"path reaches every sub-makefile verbatim and resolves against "
|
||||
"whichever working directory each one runs in." % src)
|
||||
if not os.path.isdir(os.path.join(src, 'wolfcrypt', 'src')):
|
||||
bb.fatal("WOLFBOOT_WOLFSSL_SRC='%s' does not look like a wolfSSL source "
|
||||
"tree (no wolfcrypt/src directory)." % src)
|
||||
}
|
||||
|
||||
do_stage_external_wolfssl() {
|
||||
if [ -z "${WOLFBOOT_WOLFSSL_SRC}" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
rm -rf "${WOLFBOOT_WOLFSSL_STAGED_SRC}"
|
||||
mkdir -p "${WOLFBOOT_WOLFSSL_STAGED_SRC}"
|
||||
|
||||
# Prebuilt objects are excluded so a natively-configured wolfSSL tree
|
||||
# (./configure && make) cannot leak host x86 .o/.a files into the cross
|
||||
# build: wolfBoot's object paths sit inside this tree, and make would
|
||||
# happily reuse an existing .o that is newer than its .c.
|
||||
tar -cf - -C "${WOLFBOOT_WOLFSSL_SRC}" \
|
||||
--exclude=.git --exclude=.libs \
|
||||
--exclude='*.o' --exclude='*.lo' --exclude='*.a' --exclude='*.la' \
|
||||
--exclude='*.so' --exclude='*.so.*' \
|
||||
. | tar -xf - -C "${WOLFBOOT_WOLFSSL_STAGED_SRC}"
|
||||
|
||||
# Guard against a half-copied tree: the pipeline above reports only the
|
||||
# extract side's exit status under a plain POSIX shell.
|
||||
if [ ! -f "${WOLFBOOT_WOLFSSL_STAGED_SRC}/wolfcrypt/src/asn.c" ]; then
|
||||
bbfatal "Failed to stage WOLFBOOT_WOLFSSL_SRC='${WOLFBOOT_WOLFSSL_SRC}':" \
|
||||
"wolfcrypt/src/asn.c is missing from the copy at" \
|
||||
"${WOLFBOOT_WOLFSSL_STAGED_SRC}."
|
||||
fi
|
||||
|
||||
chmod -R u+w "${WOLFBOOT_WOLFSSL_STAGED_SRC}"
|
||||
}
|
||||
do_stage_external_wolfssl[prefuncs] += "check_wolfboot_wolfssl_src"
|
||||
do_stage_external_wolfssl[vardeps] += "WOLFBOOT_WOLFSSL_SRC_ID"
|
||||
do_compile[vardeps] += "WOLFBOOT_WOLFSSL_SRC_ID"
|
||||
addtask stage_external_wolfssl after do_unpack before do_compile
|
||||
|
||||
python () {
|
||||
if d.getVar('UNPACKDIR', False):
|
||||
|
|
|
|||
|
|
@ -133,6 +133,21 @@ do_compile() {
|
|||
# the resulting AArch64 binary on the x86_64 build host. Point it at
|
||||
# the native keygen from wolfboot-keytools-native instead.
|
||||
NATIVE_KEYGEN="$(command -v wolfboot-keygen)"
|
||||
|
||||
# Build wolfCrypt from a caller-supplied wolfSSL tree when asked.
|
||||
# WOLFBOOT_LIB_WOLFSSL is wolfBoot's way to set an external wolfSSL source
|
||||
# location. Leaving it unset keeps the in-tree lib/wolfssl fetched
|
||||
# by wolfboot.inc. Always point it at the WORKDIR copy staged by
|
||||
# do_stage_external_wolfssl, never at the caller's tree because the build
|
||||
# needs to write object files into this directory. Unquoted below so it
|
||||
# vanishes when empty.
|
||||
WOLFSSL_LIB_ARG=""
|
||||
if [ -n "${WOLFBOOT_WOLFSSL_SRC}" ]; then
|
||||
WOLFSSL_LIB_ARG="WOLFBOOT_LIB_WOLFSSL=${WOLFBOOT_WOLFSSL_STAGED_SRC}"
|
||||
bbnote "wolfBoot: building wolfCrypt from ${WOLFBOOT_WOLFSSL_SRC}" \
|
||||
"(staged at ${WOLFBOOT_WOLFSSL_STAGED_SRC})"
|
||||
fi
|
||||
|
||||
make wolfboot.elf \
|
||||
CROSS_COMPILE=${TARGET_PREFIX} \
|
||||
CC="${TARGET_PREFIX}gcc $SYSROOT_FLAG" \
|
||||
|
|
@ -140,6 +155,7 @@ do_compile() {
|
|||
USER_PRIVATE_KEY="${WOLFBOOT_SIGNING_KEY}" \
|
||||
USER_PUBLIC_KEY="$PUBKEY_FOR_MAKE" \
|
||||
KEYGEN_TOOL="$NATIVE_KEYGEN" \
|
||||
$WOLFSSL_LIB_ARG \
|
||||
${WOLFBOOT_EXTRA_MAKE_FLAGS} \
|
||||
V=1
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue