Skip to main content

SoM Releases — Verification & Provisioning

Every SoM ships from production test with a flashed bootloader stack, a system image, and a programmed EEPROM identity — all drawn from a versioned, signed SoM-release bundle. This page covers what a bundle is, how to verify its provenance, and how a module is provisioned from one.

This is supply-chain provenance — it is not the device secure-boot chain, which signs bootable firmware images with a different, device-scoped key (MCUboot + OPTIGA Trust M).

The release bundle

A bundle is a directory with a manifest (bundle.json, schema som-release-bundle-v1) plus the component binaries. The manifest records:

FieldWhat it carries
sku / family / hw_revWhich module this release targets (e.g. E1M-V2N101, v2n, r1).
release_versionSemantic release id, som-X.Y.Z.
statuscomplete, or bootloader-only:image-pending-hw for early bundles.
components[]One row per artefact — role (bl2 / fip / system_image), file, sha256, size_bytes, and flash_target (xspi:mtd0 / xspi:mtd1 / emmc).
provenanceBuild reproducibility pins: toolchain, U-Boot / TF-A source revisions, defconfig, applied patches.
signatureECDSA-P256 provenance signature (or null on early, pre-signing bundles).

Verifying provenance

Bundles are signed with Alp Lab's ECDSA P-256 release-signing key. The public half is published in the SDK repo at keys/alp_release_signing_ecdsa_p256.pub.pem; the key_id in the signature block (first 16 hex chars of SHA-256(DER(public key)), currently 8be383f850354f40) lets verification match the right key across rotations.

The signature is computed over the manifest in canonical JSON form (with signature: null, sorted keys, compact separators), digested with SHA-256. Since the manifest already records the SHA-256 of every component, one signature transitively attests the whole release.

python scripts/check_som_bundle.py \
--bundle releases/E1M-V2N101/som-0.2.0/bundle.json \
--require-signature
  • Without --require-signature, an unsigned bundle still passes — early bundles such as som-0.1.0 predate signing. With it, unsigned is a failure.
  • --pubkey <PEM> verifies against a specific key instead of the published default (useful during key rotation).
  • A tampered manifest, an invalid signature, or an unloadable key fails with a clear FAIL … line and a non-zero exit code.

Programmatic verification (verify-only module, no private key involved):

import som_signing # scripts/som_signing.py
pub = som_signing.load_public_key_file("keys/alp_release_signing_ecdsa_p256.pub.pem")
assert som_signing.verify_signature(bundle_dict, pub)

Key rotation is non-disruptive: verify_with_keys(doc, [pub1, pub2, …]) accepts any trusted key, so already-shipped bundles stay verifiable against the retained old key during the overlap window.

Provisioning a module

scripts/provision_som.py provisions one module from a bundle in a linear, stop-on-first-failure sequence:

  1. Validate the bundle (check_som_bundle.py).
  2. Flashbl2/fip to xSPI via the xspi_flashwriter backend (Flash Writer SCIF over serial), system image to eMMC via yocto_wic. Skipped for bootloader-only bundles.
  3. EEPROM — allocate a serial number, build the 128-byte hardware-info manifest, write it to the on-module EEPROM, and read it back to verify.
  4. Power-on test — run the board's HIL smoke suite, gated on alp_hw_info_read() succeeding first.
  5. Record the unit to the production ledger.

Provisioning rewrites the bootloader, wipes eMMC, and programs the EEPROM — so the tool dry-runs by default, printing exactly what each step would do. Pass --execute to perform the real operations:

python scripts/provision_som.py --execute \
--bundle <bundle> --port COM24 \
--flash-writer <Flash_Writer_SCIF_RZV2N_DEV_LPDDR4X.mot> \
--emmc-device /dev/sdX --hil-spec tests/hil/e1m-v2n101-x-evk \
--station bench1 --by <technician>

See also

Questions about this page? Discuss in Community Forum