meta-wolfssl/recipes-support/libfcs/agilex5/README.md

12 KiB

wolfSSL FCS offload on Altera Agilex 5

This guide builds wolfSSL with Secure Device Manager crypto offload, includes the result in an Agilex 5 Linux image, deploys that image, and verifies the packaged wolfCrypt test on the board.

Prerequisites

  • An Agilex 5 GSRD Yocto build configured for the exact board and release.
  • This meta-wolfssl layer in BBLAYERS.
  • A layer that builds Altera's libfcs. The 26.1 GSRD's meta-altera-fpga provides gsrd-intel-fcs-lib, and meta-intel-fpga-refdes provides socfpga-intel-fcs-lib. A user recipe that installs the libfcs headers and libFCS.so also works.
  • A wolfSSL revision that contains the Agilex 5 port. wolfSSL 5.9.4 predates it; see Use a wolfSSL revision with the Agilex 5 port.
  • A kernel exposing /sys/kernel/fcs_sysfs/platform. libfcs reads that file during initialization. Older Altera kernels such as linux-socfpga 6.12.19 create /sys/kernel/fcs_sysfs without it, and libfcs then fails to start.
  • An owner root key hash provisioned in the SDM.

Provisioning is outside this layer's scope. Follow Altera's device-security procedure and distinguish recoverable virtual-key programming from permanent eFuse programming before changing a board. A virtual owner key is cleared when the board loses power and must be reapplied before each cold-boot test. Once an owner key is active, boot and FPGA configuration artifacts must be signed by that owner.

Run BitBake on a Linux build server with the memory and storage required by the GSRD release. Do not run BitBake on the target board.

The 26.1 GSRD source and board-specific build instructions are published in Altera's DK-A5E013BM16AEA GSRD guide. Install python3-venv and Kas as described there. If the build server cannot install Python packages, the official Kas container is an alternative:

docker pull ghcr.io/siemens/kas/kas:4.8

The 26.1 GSRD kernel append uses Bash conditionals in a BitBake task that runs under /bin/sh. Make those conditionals portable before building:

sed -i \
    -e 's/if \[\[/if [/g' \
    -e 's/\]\]; then/]; then/g' \
    -e 's/" == "/" = "/g' \
    meta-altera-fpga/meta-altera-bsp/recipes-kernel/linux/\
linux-socfpga-lts_%.bbappend

Without this correction, linux-socfpga-lts:do_deploy reports [[: not found and selects a nonexistent fit_agilex5_kernel_no_rbf.its file.

Add the layer to an Agilex 5 GSRD build

The 26.1 GSRD for the DK-A5E013BM16AEA uses Kas. Add meta-wolfssl to the GSRD kas.yml or to a Kas configuration fragment:

header:
  version: 17

repos:
  meta-wolfssl:
    url: https://github.com/wolfSSL/meta-wolfssl.git
    branch: master
    layers:
      .:

local_conf_header:
  wolfssl-altera-fcs: |
    WOLFSSL_ALTERA_FCS = "1"
    WOLFSSL_FCS_PROVIDER = "gsrd-intel-fcs-lib"
    IMAGE_INSTALL:append = " wolfssl wolfcrypttest wolfcryptbenchmark "
    # Remove after the first wolfSSL release that contains the Agilex 5 port.
    SRC_URI:pn-wolfssl = "git://github.com/wolfssl/wolfssl.git;nobranch=1;protocol=https"
    SRCREV:pn-wolfssl = "c177f861d0ecba3a998e1cae3d18d21103572aed"    

Save the fragment as wolfssl-fcs.yml. Kas configurations can be combined without changing the GSRD's supplied kas.yml.

For a local meta-wolfssl checkout under the GSRD Yocto directory, replace the repository URL and branch with:

  meta-wolfssl:
    path: meta-wolfssl
    layers:
      .:

meta-wolfssl does not build libfcs itself. WOLFSSL_FCS_PROVIDER names the recipe that does, and defaults to the 26.1 GSRD's gsrd-intel-fcs-lib. Altera's recipes install only the versioned runtime library, so this layer appends the unversioned libFCS.so linker name to gsrd-intel-fcs-lib and socfpga-intel-fcs-lib. Builds using meta-intel-fpga-refdes select its recipe instead:

WOLFSSL_FCS_PROVIDER = "socfpga-intel-fcs-lib"

A user supplied recipe must install libFCS.so itself. The port has been validated with libfcs 3.01, the revision built by the 26.1 GSRD.

Use a wolfSSL revision with the Agilex 5 port

The --enable-alterafcs option this layer passes exists only in wolfSSL releases after 5.9.4. Until the next release, add a bbappend to your own layer, for example recipes-wolfssl/wolfssl/wolfssl_%.bbappend, that builds a wolfSSL master commit containing the port:

# Remove after the first wolfSSL release that contains the Agilex 5 port.
SRC_URI = "git://github.com/wolfssl/wolfssl.git;nobranch=1;protocol=https"
SRCREV = "c177f861d0ecba3a998e1cae3d18d21103572aed"

Keep the revision in SRCREV, not as rev= in the URL. The % append also matches meta-openembedded's wolfssl recipe, which sets its own SRCREV, and a rev= parameter would then conflict with it during parsing. The same two assignments can be placed in local.conf or a Kas local_conf_header as SRC_URI:pn-wolfssl and SRCREV:pn-wolfssl. Without them, do_configure fails on the unrecognized option.

Build the Agilex 5 image

From the 26.1 DK-A5E013BM16AEA GSRD software/yocto_linux directory, build the same gsrd-console-image target documented by Altera:

source venv/bin/activate
kas build kas.yml:wolfssl-fcs.yml gsrd-console-image

With the Kas container, run the equivalent command from the same directory:

docker run --rm --user "$(id -u):$(id -g)" \
    -e HOME=/work -v "$PWD:/work" -w /work \
    ghcr.io/siemens/kas/kas:4.8 \
    build kas.yml:wolfssl-fcs.yml gsrd-console-image

The SD card image is written to BitBake's DEPLOY_DIR_IMAGE. Its parent TMPDIR depends on the distribution: Kas 4.x selects poky and uses build/tmp, while Kas 5.x defaults to nodistro and uses build/tmp-glibc. Ask BitBake for the directory instead of assuming either. From the same software/yocto_linux directory, inspect the image and the installed test in an initialized OpenEmbedded shell:

(
    set -e
    source poky/oe-init-build-env build >/dev/null
    deploy="$(bitbake-getvar --value DEPLOY_DIR_IMAGE)"
    image="$deploy/gsrd-console-image-agilex5e_013b.rootfs.wic"
    test -s "$image"
    sha256sum "$image"
    native="$(bitbake-getvar -r gsrd-console-image --value RECIPE_SYSROOT_NATIVE)"
    test -d "$native"
    wic ls -n "$native" "$image"
    wolfcrypt_bins="$(wic ls -n "$native" "$image:2/usr/bin/")"
    printf '%s\n' "$wolfcrypt_bins"
    printf '%s\n' "$wolfcrypt_bins" | grep -q 'wolfcrypttest'
    printf '%s\n' "$wolfcrypt_bins" | grep -q 'wolfcryptbenchmark'
    oe-pkgdata-util find-path /usr/bin/wolfcrypttest
    printf 'image=%s\n' "$image"
)

When the image was built with the Kas container, run the same commands, without the source line, through kas shell so Yocto's native tools retain the /work path used at build time:

docker run --rm --user "$(id -u):$(id -g)" \
    -e HOME=/work -v "$PWD:/work" -w /work \
    ghcr.io/siemens/kas/kas:4.8 \
    shell kas.yml:wolfssl-fcs.yml -c '
        set -e
        deploy="$(bitbake-getvar --value DEPLOY_DIR_IMAGE)"
        image="$deploy/gsrd-console-image-agilex5e_013b.rootfs.wic"
        test -s "$image"
        sha256sum "$image"
        native="$(bitbake-getvar -r gsrd-console-image \
            --value RECIPE_SYSROOT_NATIVE)"
        test -d "$native"
        wic ls -n "$native" "$image"
        wolfcrypt_bins="$(wic ls -n "$native" "$image:2/usr/bin/")"
        printf "%s\n" "$wolfcrypt_bins"
        printf "%s\n" "$wolfcrypt_bins" | grep -q wolfcrypttest
        printf "%s\n" "$wolfcrypt_bins" | grep -q wolfcryptbenchmark
        oe-pkgdata-util find-path /usr/bin/wolfcrypttest
        printf "image=%s\n" "$image"
    '

The container reports paths under /work, which is the current directory on the host. Either block must exit with status 0. The image must contain a FAT boot partition and an ext4 root partition, the second wic ls command must show both wolfcrypttest and wolfcryptbenchmark, and the package lookup must report wolfssl. Keep the printed image path and SHA-256 for deployment.

Deploy the image

Power off the board and remove its microSD card. Attach the card to the build server, identify the whole device by its capacity, and unmount any mounted partitions. Device names vary: USB readers commonly appear as /dev/sdX, while built-in readers may appear as /dev/mmcblkN. The example below uses the device observed on the build server; replace it only after checking lsblk. Set image to the absolute path printed by the inspection step:

image=/path/printed/by/inspection/gsrd-console-image-agilex5e_013b.rootfs.wic
card=/dev/mmcblk0

lsblk -o NAME,SIZE,TYPE,TRAN,RM,MODEL,MOUNTPOINTS
test -b "$card"
for part in $(lsblk -lnpo NAME "$card" | tail -n +2); do
    if findmnt -rn -S "$part" >/dev/null; then
        sudo umount "$part"
    fi
done

sudo dd if="$image" of="$card" bs=4M status=progress conv=fsync
image_size=$(stat -Lc %s "$image")
sudo cmp -n "$image_size" "$image" "$card" && echo "WIC verified"
sync
sudo blockdev --flushbufs "$card"

Verify the destination with lsblk before writing. This operation replaces the card contents. Do not use a disk containing the build server's root filesystem. Use a spare card or make a full-device backup first if the existing image must be recoverable. cmp is silent on success; do not remove the card unless it returns zero and prints WIC verified. A built-in MMC reader may not implement the eject command. Once the partitions are unmounted and blockdev has flushed the device, it is safe to remove the card physically.

If the target image enables a package manager and a compatible package feed, an incremental update is also valid:

bitbake wolfssl wolfcrypttest
bitbake package-index

Publish the generated package feed, refresh the target package index, and install or upgrade wolfssl and wolfcrypttest with the target's package manager. Do not copy a package from a different machine, tune, C library, or Yocto release.

Verify on the board

Boot the deployed image and confirm that its packaged files are present:

test -x /usr/bin/wolfcrypttest
/lib/ld-linux-aarch64.so.1 --list /usr/bin/wolfcrypttest
test -r /sys/kernel/fcs_sysfs/platform

If /sys/kernel/fcs_sysfs/platform is missing, the kernel is too old for the libfcs build in the image. libfcs fails to initialize and wolfcrypttest skips the hardware test, so a zero exit status alone does not prove offload.

The DHCP address can change after booting a replacement image. Use the serial console, the DHCP server's leases, or a local subnet scan to find the target rather than assuming its previous address is retained.

The GSRD image does not install ldd by default. Invoking the AArch64 dynamic loader with --list performs the same runtime dependency check without adding a diagnostic package to the image.

Run the installed test:

/usr/bin/wolfcrypttest

The run must exit with status 0 and print:

ALTERA-FCS test passed!

The Altera subtests require successful hardware operations for RNG, SHA-256, and AES. They cannot pass solely through wolfSSL software fallback. Device resident ECDSA and ECDH keys and HMAC verification are also exercised.

If the marker is missing, first confirm /sys/kernel/fcs_sysfs/platform exists. If only the Altera test fails, check SDM provisioning status 0x85. Status 0x84 indicates session exhaustion and requires a board power cycle.

Developer-only smoke test

Copying ${B}/wolfcrypt/test/.libs/testwolfcrypt directly to a running target is useful while developing the recipe. It is not the final integration test because it bypasses image construction, package installation, and runtime dependency resolution. Use the packaged /usr/bin/wolfcrypttest flow above for release validation.