-
Notifications
You must be signed in to change notification settings - Fork 303
[RFC] qcom-firmware-sign: build-time secure-boot signing of Qualcomm firmware #2598
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
5086824
f032556
446e1ec
a998372
8c7a2de
6265560
bb6079a
52c0458
efca6cc
a1ee798
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json | ||
| # | ||
| # Include this kas file to enable test ECDSA PKI keys for Qualcomm | ||
| # secure-boot image signing. These keys are for CI / development use | ||
| # only and must NOT be used in production images. | ||
| # | ||
| # Usage: kas build ci/base.yml:ci/<machine>.yml:ci/secure-boot.yml:ci/ecdsa-secure-boot-test-keys.yml | ||
|
|
||
| header: | ||
| version: 14 | ||
|
|
||
| local_conf_header: | ||
| ecdsa-secure-boot-test-keys: | | ||
| QCOM_FIRMWARE_SIGN_KEY_DIR = "${LAYERDIR_qcom}/ci/test-keys/ecdsa" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/siemens/kas/master/kas/schema-kas.json | ||
| # | ||
| # Include this kas file to enable Qualcomm secure-boot signing of | ||
| # pre-built firmware images via classes-recipe/qcom-firmware-sign.bbclass. | ||
| # Wires the build through to sectools-native and security-profiles-native | ||
| # and supplies the fuse-binding parameters used by sectools at sign time. | ||
| # | ||
| # Usage: | ||
| # kas build ci/base.yml:ci/<machine>.yml:ci/secure-boot.yml:ci/ecdsa-secure-boot-test-keys.yml | ||
| # | ||
| # For production builds, replace ecdsa-secure-boot-test-keys.yml with | ||
| # a kas overlay that sets QCOM_FIRMWARE_SIGN_KEY_DIR to an OEM key | ||
| # directory (with qpsa_rootca0.cer / qpsa_attestca0.cer / | ||
| # qpsa_attestca0.key / sha384_roots_hash.txt) sourced from a secrets | ||
| # manager rather than the in-tree test fixtures. | ||
|
|
||
| header: | ||
| version: 14 | ||
|
|
||
| # meta-oe provides libzip, which qdl-native links against (besides | ||
| # libusb-1.0 and libxml-2.0 from oe-core). meta-python is not pulled | ||
| # in; we have no Python-only dependency. | ||
| repos: | ||
| meta-openembedded: | ||
| url: https://github.com/openembedded/meta-openembedded | ||
| layers: | ||
| meta-oe: | ||
|
|
||
| local_conf_header: | ||
| secure-boot: | | ||
| QCOM_FIRMWARE_SIGN_ENABLE = "1" | ||
| # Per-SoC Security Profile XML. Bare filenames are resolved | ||
| # against the directory staged by security-profiles-native; an | ||
| # absolute path can be used to point at a custom profile. | ||
| QCOM_SECURITY_PROFILE ?= "kodiak_security_profile.xml" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Profile should probably come from the board conf.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. make sense, will do |
||
| QCOM_FIRMWARE_SIGN_SECPROFILE = "${QCOM_SECURITY_PROFILE}" | ||
| # Fuse-binding identifiers. These are device-specific; the values | ||
| # below are placeholders for development. Override per OEM / | ||
| # production build. | ||
| QCOM_FUSE_OEM_HW_ID = "0x0001" | ||
| QCOM_FUSE_OEM_PRODUCT_ID = "0xabcd" | ||
| QCOM_FUSE_SEC_KEY_DERIVATION_KEY = "" | ||
| # Anti-rollback floor stamped into signed images. Bump only when | ||
| # rolling forward security-critical firmware revisions. | ||
| QCOM_FIRMWARE_SIGN_ANTI_ROLLBACK = "0x0" | ||
| # Enable the qcomflash-vip image type. Produces an additional | ||
| # ${IMAGE_NAME}.qcomflash-vip.tar.gz next to the qcomflash tarball | ||
| # containing the signed VIP (Validated Image Programming) digest | ||
| # table -- intended to be flashed alongside qcomflash via | ||
| # `qdl --vip-table-path`. See classes-recipe/image_types_qcom_vip.bbclass | ||
| # and recipes-devtools/qdl/qdl-native_2.7.bb. | ||
| IMAGE_CLASSES += "image_types_qcom_vip" | ||
| IMAGE_FSTYPES += "qcomflash-vip" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need a separate class and separate image type? |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| -----BEGIN EC PARAMETERS----- | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Split this commit in 2, have one dedicated just for the keys. |
||
| BgUrgQQAIg== | ||
| -----END EC PARAMETERS----- | ||
| -----BEGIN EC PRIVATE KEY----- | ||
| MIGkAgEBBDD0kj7dDRzPghNxNjknJC68swgJH/XGdBVinbVPoWjlEV95Ipr3y6E4 | ||
| RNF7IU3lT2KgBwYFK4EEACKhZANiAASnFtGeU9cEUA3+kBdiUyP7wDL4HUTgzZoo | ||
| KBS+aGWZ0F04+lcPxpKfxGXv3LGJ1Ucbusc2TsijfPsuWoP9YhRnb0bdpvsarUDG | ||
| mCuFPv9+lABY30VuKyfVMR0iNGQhQlY= | ||
| -----END EC PRIVATE KEY----- | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| SHA2-384(qpsa_rootca0.cer)= 9bc289bd255ec63e5752d15c15fa64d2f1ec0dd78e0438e5ffea498ae16d0aada49491eadaefe782fe3f91d147a540d3 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| # | ||
| # Copyright (c) 2026 Qualcomm Innovation Center, Inc. All rights reserved. | ||
| # SPDX-License-Identifier: BSD-3-Clause-Clear | ||
| # | ||
| # qcomflash-vip image type: produce a VIP (Validated Image Programming) | ||
| # digest table for a signed qcomflash build, wrap it as an MBN and sign | ||
| # it with the OEM secure-boot keys. The resulting `.qcomflash-vip.tar` | ||
| # bundle deploys the signed VIP table next to the qcomflash artifacts | ||
| # and is intended to be flashed alongside it via qdl --vip-table-path | ||
| # (see qcom-sec-tools/secure.sh "make sign-build" for the reference | ||
| # pipeline this class is derived from). | ||
| # | ||
| # Usage: | ||
| # IMAGE_FSTYPES += "qcomflash-vip" | ||
| # | ||
| # Requires the qcom-firmware-sign signing machinery to be active | ||
| # (QCOM_FIRMWARE_SIGN_ENABLE = "1"); without it the VIP step is a | ||
| # no-op because there is nothing to bind the digests to. | ||
|
|
||
| inherit image_types_qcom qcom-firmware-sign | ||
|
|
||
| IMAGE_TYPES += "qcomflash-vip" | ||
| IMAGE_TYPEDEP:qcomflash-vip += "qcomflash" | ||
| IMAGE_CMD:qcomflash-vip = "create_qcomflash_vip_pkg" | ||
|
|
||
| # Tooling staged into the native sysroot by the secure-boot recipes. | ||
| QCOM_VIP_QDL ?= "${STAGING_BINDIR_NATIVE}/qdl" | ||
| QCOM_VIP_SECTOOLS ?= "${QCOM_FIRMWARE_SIGN_SECTOOLS}" | ||
|
|
||
| QCOM_VIP_FIREHOSE ?= "prog_firehose_ddr.elf" | ||
|
|
||
| # MBN container version used to wrap the digest table | ||
| QCOM_VIP_MBN_VERSION ?= "6" | ||
|
|
||
| QCOMFLASH_VIP_DIR = "${IMGDEPLOYDIR}/${IMAGE_NAME}.qcomflash-vip" | ||
|
|
||
| do_image_qcomflash_vip[dirs] = "${QCOMFLASH_VIP_DIR}" | ||
| do_image_qcomflash_vip[cleandirs] = "${QCOMFLASH_VIP_DIR}" | ||
| do_image_qcomflash_vip[depends] += "qdl-native:do_populate_sysroot \ | ||
| sectools-native:do_populate_sysroot \ | ||
| security-profiles-native:do_populate_sysroot" | ||
|
|
||
| create_qcomflash_vip_pkg() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, having a separate fstype kind of makes sense. |
||
| if ! qcom_check_signing_enabled ; then | ||
| bbwarn "qcomflash-vip requested but QCOM_FIRMWARE_SIGN_ENABLE is not '1'; skipping VIP generation" | ||
| return 0 | ||
| fi | ||
|
|
||
| if [ ! -d "${QCOMFLASH_DIR}" ]; then | ||
| bbfatal "qcomflash-vip: expected qcomflash output at ${QCOMFLASH_DIR}, but it does not exist" | ||
| fi | ||
|
|
||
| if [ ! -f "${QCOMFLASH_DIR}/${QCOM_VIP_FIREHOSE}" ]; then | ||
| bbfatal "qcomflash-vip: firehose programmer ${QCOM_VIP_FIREHOSE} not found in ${QCOMFLASH_DIR}" | ||
| fi | ||
|
|
||
| # 1. Mirror the qcomflash content into our output directory. The | ||
| # resulting tarball is a superset of the regular qcomflash tarball | ||
| bbnote "qcomflash-vip: mirroring qcomflash artefacts into ${QCOMFLASH_VIP_DIR}" | ||
| cp -al "${QCOMFLASH_DIR}"/. "${QCOMFLASH_VIP_DIR}/" | ||
|
|
||
| vipdir="${QCOMFLASH_VIP_DIR}/vip-tables" | ||
| install -d "${vipdir}" | ||
|
|
||
| # 2. Generate the digest table. qdl in --dry-run + --create-digests | ||
| # mode walks the rawprogram/patch XMLs the same way it would for a | ||
| # real flash, but instead of transferring data computes a digest | ||
| # over each programmed segment and writes them to | ||
| # DigestsToSign.bin under the requested directory. | ||
| ( | ||
| cd "${QCOMFLASH_VIP_DIR}" | ||
| "${QCOM_VIP_QDL}" --allow-fusing --dry-run \ | ||
| --create-digests="${vipdir}" \ | ||
| "${QCOM_VIP_FIREHOSE}" \ | ||
| rawprogram*.xml patch*.xml | ||
| ) || bbfatal "qcomflash-vip: qdl digest generation failed" | ||
|
|
||
| if [ ! -f "${vipdir}/DigestsToSign.bin" ]; then | ||
| bbfatal "qcomflash-vip: qdl did not produce DigestsToSign.bin in ${vipdir}" | ||
| fi | ||
|
|
||
| # 3. Wrap the digest table as an MBN so it has a proper Qualcomm | ||
| # firmware header, otherwise the on-target VIP verifier rejects | ||
| # it. mbn-tool generate writes the MBN beside the source bin. | ||
| "${QCOM_VIP_SECTOOLS}" mbn-tool generate \ | ||
| --data "${vipdir}/DigestsToSign.bin" \ | ||
| --mbn-version "${QCOM_VIP_MBN_VERSION}" \ | ||
| --outfile "${vipdir}/DigestsToSign.bin.mbn" \ | ||
| || bbfatal "qcomflash-vip: sectools mbn-tool generate failed" | ||
|
|
||
| # 4. Sign the MBN as image-id VIP using the same keying material as | ||
| # the rest of the firmware. qcom_sign_only_file looks up VIP in | ||
| # QCOM_FIRMWARE_SIGN_IMAGE_ID_MAP, validates it against the active | ||
| # security profile and runs sectools secure-image --sign in-place. | ||
| # | ||
| # We deliberately skip the post-sign verify-root step (use | ||
| # qcom_sign_only_file, not qcom_sign_verify_file): the upstream | ||
| # github security-profiles repo marks VIP with | ||
| # <oem_vouch_for_disallowed/>, which makes sectools' verify-root | ||
| # reject OEM-only signatures even though the boot ROM accepts | ||
| qcom_sign_only_file "${vipdir}/DigestsToSign.bin.mbn" | ||
|
|
||
| # 5. Bundle the mirrored qcomflash directory plus the signed VIP | ||
| # table into a single tarball. The tar layout mirrors the | ||
| # qcomflash convention: everything lives under <image>-<machine>/ | ||
| # so consumers that drive flashing from the extracted root can | ||
| # use exactly the same paths as they do for the plain qcomflash | ||
| # artefact, with the additional vip-tables/ subdir. | ||
| ${IMAGE_CMD_TAR} --sparse --numeric-owner \ | ||
| --transform="s,^\./,${IMAGE_BASENAME}-${MACHINE}/," \ | ||
| -cf- -C "${QCOMFLASH_VIP_DIR}" . \ | ||
| | pigz -p ${BB_NUMBER_THREADS} -9 -n --rsyncable \ | ||
| > "${IMGDEPLOYDIR}/${IMAGE_NAME}.qcomflash-vip.tar.gz" | ||
|
|
||
| ln -sf "${IMAGE_NAME}.qcomflash-vip.tar.gz" \ | ||
| "${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.qcomflash-vip.tar.gz" | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer this to be done as part of the main tarball, to avoid confusion.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will do |
||
|
|
||
| create_qcomflash_vip_pkg[vardepsexclude] += "BB_NUMBER_THREADS DATETIME" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same.