/
FIDO Device Onboard

FIDO Device Onboard

This document provides how to set up FIDO Device Onboard (FDO) on Synquacer and runs a simple demo.

Prerequisites

  • meta-ts (>=0.4) installed machine connected to the internet.

For building and installing the firmware, refer to https://linaro.atlassian.net/wiki/spaces/FLT/pages/28747595918/Firmware+Build+and+Installation+Manual#Build-firmware-for-DeveloperBox.

Overview

FDO, or FIDO Device Onboarding, establishes a standardized and secure process for manufacturers to configure devices during onboarding. The primary goal is enabling OEMs or sellers to accurately and automatically configure devices, improving efficiency and security without requiring user involvement.

Setup environment

We need to prepare the servers to ensure that the Synquacer device can communicate with FDO servers. To achieve this, we will use a Docker image that provides portability and install all the necessary FDO servers on it. On the Synquacer side, we will install the Fedora OS with the FDO client package using U-Boot UEFI HTTP Boot.

On host machine

Run Fedora docker image

docker pull fedora:39 docker run --name fdo -it -p 8080-8083:8080-8083/tcp fedora:39 /bin/bash

Install FDO packages

[root@fedora /]# dnf install -y fdo-*

Setup configurations for FDO servers

[root@fedora /]# cd /etc/fdo [root@fedora fdo]# for i in manufacturer owner device-ca diun ; do > fdo-admin-tool generate-key-and-cert --destination-dir keys $i > done [root@fedora fdo]# touch manufacturing-server.yml \ rendezvous-server.yml \ rendezvous-info.yml \ owner-onboarding-server.yml \ serviceinfo-api-server.yml
--- session_store_driver: Directory: path: /etc/fdo/stores/manufacturing_sessions/ ownership_voucher_store_driver: Directory: path: /etc/fdo/stores/owner_vouchers/ public_key_store_driver: Directory: path: /etc/fdo/stores/manufacturer_keys bind: 0.0.0.0:8080 rendezvous_info: - ip: 192.168.1.10 device_port: 8082 owner_port: 8082 protocol: http protocols: diun: key_path: /etc/fdo/keys/diun_key.der cert_path: /etc/fdo/keys/diun_cert.pem key_type: SECP256R1 mfg_string_type: SerialNumber allowed_key_storage_types: - FileSystem - Tpm manufacturing: manufacturer_cert_path: /etc/fdo//keys/manufacturer_cert.pem manufacturer_private_key: /etc/fdo/keys/manufacturer_key.der owner_cert_path: /etc/fdo/keys/owner_cert.pem device_cert_ca_private_key: /etc/fdo/keys/device_ca_key.der device_cert_ca_chain: /etc/fdo/keys/device_ca_cert.pem
--- storage_driver: Directory: path: /etc/fdo/stores/rendezvous_registered session_store_driver: Directory: path: /etc/fdo/stores/rendezvous_sessions trusted_manufacturer_keys_path: /etc/fdo/keys/manufacturer_cert.pem max_wait_seconds: ~ bind: "0.0.0.0:8082"
--- - ip_address: 192.168.1.10 deviceport: 8082 ownerport: 8082 protocol: http
--- session_store_driver: Directory: path: /etc/fdo/stores/owner_onboarding_sessions/ ownership_voucher_store_driver: Directory: path: /etc/fdo/stores/owner_vouchers/ trusted_device_keys_path: /etc/fdo/keys/device_ca_cert.pem owner_private_key_path: /etc/fdo/keys/owner_key.der owner_public_key_path: /etc/fdo/keys/owner_cert.pem owner_addresses: - transport: HTTP port: 8081 addresses: - ip_address: 192.168.1.10 report_to_rendezvous_endpoint_enabled: false bind: 0.0.0.0:8081 service_info_api_url: "http://localhost:8083/device_info" service_info_api_authentication: BearerToken: token: TestAuthToken
--- bind: 0.0.0.0:8083 device_specific_store_driver: Directory: path: /etc/fdo/stores/device_specific_serviceinfo service_info_auth_token: TestAuthToken admin_auth_token: TestAdminToken service_info: initial_user: username: admin sshkeys: - "testkey" files: - path: /var/lib/fdo/service-info-api/files/hosts permissions: 644 source_path: /etc/hosts - path: /var/lib/fdo/service-info-api/files/resolv.conf source_path: /etc/resolv.conf commands: - command: ls args: - /etc/hosts return_stdout: true return_stderr: true - command: ls args: - /etc/doesnotexist/whatever.foo may_fail: true return_stdout: true return_stderr: true - command: touch args: - /etc/command-testfile after_onboarding_reboot: false

Prepare an Ownership Voucher (OV) and Device Credential

Generate the OV and Device Credential

[root@fedora fdo]# mkdir -p ./stores/device_credentials [root@fedora fdo]# fdo-owner-tool initialize-device \ 1234 \ ./stores/owner_vouchers/ownership_voucher_synquacer \ ./stores/device_credentials/device_credential_synquacer \ --device-cert-ca-chain ./keys/device_ca_cert.pem \ --device-cert-ca-private-key ./keys/device_ca_key.der \ --manufacturer-cert ./keys/manufacturer_cert.pem \ --rendezvous-info ./rendezvous-info.yml

How to use the Device Credential?

Before onboarding, the target device must install the Device Credential (device_credential_synquacer), which will be stored by U-Boot in the form of an EFI variable in this demo. Please note that in the later stage, a properly configured TFTP server will be required to transfer the credential to the target device and the process of setting up a TFTP server is not covered in this document. If you already have a TFTP server (/var/lib/tftpboot), you can follow the steps given below:

# docker cp fdo:/etc/fdo/stores/device_credentials/device_credential_synquacer /var/lib/tftpboot/

Extend the OV with the Owner's Certificate

[root@fedora fdo]# fdo-owner-tool extend-ownership-voucher \ ./stores/owner_vouchers/ownership_voucher_synquacer \ --current-owner-private-key ./keys/manufacturer_key.der \ --new-owner-cert ./keys/owner_cert.pem

Convert the OV to COSE format

[root@fedora fdo]# fdo-owner-tool dump-ownership-voucher \ ./stores/owner_vouchers/ownership_voucher_synquacer --outform cose > \ ./stores/owner_vouchers/ownership_voucher_synquacer.cose [root@fedora fdo]# GUID=$(fdo-owner-tool dump-ownership-voucher \ ./stores/owner_vouchers/ownership_voucher_synquacer.cose \ | awk '/Device GUID:/ {print $3}') [root@fedora fdo]# mv ./stores/owner_vouchers/{ownership_voucher_synquacer.cose,$GUID}

Run FDO servers

[root@fedora fdo]# export LOG_LEVEL=info [root@fedora fdo]# /usr/libexec/fdo/fdo-manufacturing-server & [root@fedora fdo]# /usr/libexec/fdo/fdo-owner-onboarding-server & [root@fedora fdo]# /usr/libexec/fdo/fdo-rendezvous-server & [root@fedora fdo]# /usr/libexec/fdo/fdo-serviceinfo-api-server &

Remember to make sure the required ports (8080-8083/tcp) are open in your firewall.

Once package installation and configurations are completed, consider to commit the changes not to lose them after exiting the docker process.

$ docker commit fdo fedora:39

Setup the HTTP local server for Linux OS installation

This section explains how to automate the OS installation process and system configuration by providing a custom Fedora ISO image and kickstart file to the target device from a local HTTP server.

Download Fedora ISO image

mkdir -p ~/fdo-workspace/htdocs cd ~/fdo-workspace/htdocs wget https://download.fedoraproject.org/pub/alt/iot/39/IoT/aarch64/iso/Fedora-IoT-ostree-aarch64-39-20231103.1.iso

Create a custom ISO

Copy files from ISO to a working directory
mkdir /tmp/iso-orig /tmp/iso-cust sudo mount -o loop ./Fedora-IoT-ostree-aarch64-39-20231103.1.iso /tmp/iso-orig sudo rsync -av --exclude='*/install.img' /tmp/iso-orig/* /tmp/iso-cust
Write a kickstart file
touch ~/fdo-workspace/htdocs/synquacer.ks

Here's an example of a kickstart file that installs the minimal system with fdo-client on eMMC and creates a user named fdo with the password the same as its name.

text keyboard --vckeymap=us --xlayouts='us' lang en_US.UTF-8 firewall --use-system-defaults ostreesetup --osname="fedora-iot" --remote="fedora-iot" --url="file:///ostree/repo" --ref="fedora/stable/aarch64/iot" --nogpg %post --erroronfail rm -f /etc/ostree/remotes.d/fedora-iot.conf ostree remote add --set=gpg-verify=true --set=gpgkeypath=/etc/pki/rpm-gpg/ --set=contenturl=mirrorlist=https://ostree.fedoraproject.org/iot/mirrorlist fedora-iot 'https://ostree.fedoraproject.org/iot' cp /etc/skel/.bash* /root # Generate the devcreds file from efivarfs dd if=$(ls /sys/firmware/efi/efivars/DeviceCred-*) of=/boot/device-credentials bs=1 skip=4 cat <<EOF >"/boot/fdo-client-env" DEVICE_CREDENTIAL="/boot/device-credentials" EOF # SELinux permissive for allowing fdo-client access anywhere sed -i 's/^SELINUX=.*/SELINUX=permissive/' /etc/selinux/config %end firstboot --enable skipx ignoredisk --only-use=mmcblk0 bootloader --location=mbr --boot-drive=mmcblk0 autopart --type=plain clearpart --all --initlabel --drives=mmcblk0 timezone Etc/UTC --utc rootpw --lock user --groups=wheel --name=fdo --plaintext --password=fdo services --enabled=fdo-client-linuxapp reboot
Edit the grub.cfg

Modify “inst.stage2” and “inst.ks” parameters in grub.cfg not to edit them at runtime during the OS installation.

mkdir /tmp/efiboot sudo mount -o loop /tmp/iso-cust/images/efiboot.img /tmp/efiboot awk -v KS="http://192.168.1.10/synquacer.ks" \ -v STAGE2="https://dl.fedoraproject.org/pub/alt/iot/39/IoT/aarch64/os/" \ '{sub(/^set default=.*/,"set default=\"0\"");\ sub(/inst.stage2=[^[:space:]]*/,\ "inst.stage2="STAGE2" inst.ks="KS" inst.noverifyssl noefi efi=runtime")} 1' \ /tmp/efiboot/EFI/BOOT/grub.cfg \ > tmp && sudo cp tmp /tmp/efiboot/EFI/BOOT/grub.cfg && rm tmp sudo umount /tmp/efiboot && rm -r /tmp/efiboot

Despite its length the changes to grub.cfg made by the above commands are actually straightforward:

  • Selected ‘Fedora Installation’ as the default rather than Media checking

  • Added the following kernel args

inst.ks=http://192.168.1.10/synquacer.ks inst.stage2=https://dl.fedoraproject.org/pub/alt/iot/39/IoT/aarch64/os/ inst.noverifyssl noefi efi=runtime

The last three additions are meant to suppress warnings and errors during installation that may not be necessary or ideal.

Create new ISO
iso_label=$(blkid ./Fedora-IoT-ostree-aarch64-39-20231103.1.iso | \ awk -F 'LABEL="' '{print $2}' | cut -d '"' -f 1) sudo xorriso -as mkisofs -V $iso_label -r \ -o ~/fdo-workspace/htdocs/Fedora-39-synquacer.iso \ -J -joliet-long -cache-inodes -efi-boot-part --efi-boot-image \ -e images/efiboot.img -no-emul-boot /tmp/iso-cust/ sudo implantisomd5 ~/fdo-workspace/htdocs/Fedora-39-synquacer.iso sudo umount /tmp/iso-orig && sudo rm -r /tmp/iso-orig /tmp/iso-cust

Start HTTP server

docker run --rm -d -p 80:80/tcp -v ~/fdo-workspace/htdocs:/usr/local/apache2/htdocs httpd

On Synquacer

Device Onboarding Process

Power on the Synquacer and interrupt the autobooting by pressing any key to enter the U-Boot command line.

Install Device Credential

=> setenv autoload no => dhcp => setenv serverip 192.168.1.10 => tftp $loadaddr device_credential_synquacer => setenv -e -nv -bs -rt -i ${loadaddr}:$filesize DeviceCred

Install OS by U-Boot UEFI HTTP

=> setenv httpserverip $serverip => efidebug boot add -u 5 fedora-inst http://${httpserverip}/Fedora-39-synquacer.iso => bootmenu

Select fedora-inst from the boot menu to start the installation process. The device will reboot upon completion.

Check FDO client logs

The FDO client will automatically initiate the device onboarding process during the first boot. You can view the outputs below.

systemctl status fdo-client-linuxapp -l --no-pager
fdo-client-logs.png