Add nat20 integration test suite for linux examples#105
Conversation
Add a kernel module that provides libnat20 functionality to linux kernel modules. Also add a configuration to build a minimal linux image with buildroot and run in on qemu and a workflow to test build nat20lib.ko
This module creates a new character device class intended to implement the nat20 service protocol implementing DICE based device state attestation and an embedded CA.
The nat20crypto module implements the libnat20 crypto interface in terms of linux kernel crypto primitives. The module implements - deterministic ECDSA with curves P256 and P384. - Bytewise SHA-2 224/256/384/512 - HMAC - HKDF ED25519 is currently not supported.
…/linux_example_nat20device
…urm/linux_example_nat20crypto
…linux_example_libnat20
This commandline tool provides a primitive interface to communicate with a nat20 device.
783f03c to
eaf904a
Compare
LCOV of commit
|
There was a problem hiding this comment.
Pull request overview
Adds a Buildroot-packaged Linux/QEMU integration test suite for the nat20 service stack, including a new C test binary that exercises /dev/nat200, certificate issuance, signatures, parent paths, and promote behavior.
Changes:
- Adds
nat20_integration_testplus OpenSSL/libnat20-based verification helpers. - Adds QEMU/rootfs test launch scripts and Buildroot package wiring.
- Extends CI to build the rootfs and run the integration test in QEMU.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
examples/linux/nat20test/test/test_helpers.h |
Declares helper APIs for test cryptographic verification and parsing. |
examples/linux/nat20test/test/test_helpers.c |
Implements OpenSSL, CBOR, COSE, and compression helpers. |
examples/linux/nat20test/test/nat20_integration_test.c |
Adds the main nat20 service integration test suite. |
examples/linux/nat20test/nat20test.sh |
Adds the test runner script for loading the module and launching the binary. |
examples/linux/nat20test/nat20_qemu_init.sh |
Adds the QEMU init wrapper for running tests and emitting result markers. |
examples/linux/nat20test/CMakeLists.txt |
Builds and installs the integration test binary and scripts. |
examples/linux/br_external/utils/envsetup.sh |
Adds nat20test override and rebuild support. |
examples/linux/br_external/package/nat20test/nat20test.mk |
Adds the Buildroot package definition for nat20test. |
examples/linux/br_external/package/nat20test/Config.in |
Adds the Buildroot config option for nat20test. |
examples/linux/br_external/package/nat20cli/nat20cli.mk |
Documents nat20cli override-source behavior. |
examples/linux/br_external/configs/qemu_br_defconfig |
Enables nat20test in the QEMU Buildroot config. |
examples/linux/br_external/Config.in |
Sources the new nat20test Buildroot config. |
.github/workflows/linux-kmod-build.yml |
Adds rootfs build and QEMU integration-test execution steps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds a C integration test binary (nat20_integration_test) that exercises
the full DICE service stack via /dev/nat200. The test generates certificate
chains across all supported key type (P-256, P-384) and format (X.509,
COSE) permutations, verifies cryptographic signatures at each link, and
confirms that parent_path-based issuance produces identical results to
direct issuance after promote.
Test structure:
- Phase 1 (level 1): Generate CDI1, CDI2, ECA, ECA_EE certs and
signatures using parent paths of varying depth from the UDS level.
Verify all X.509 and COSE chains cryptographically.
- Phase 2 (level 2): After one promote, regenerate CDI2/ECA/ECA_EE/sign
with reduced parent path depth and assert byte-for-byte equality.
- Phase 3 (level 3): After second promote, regenerate ECA/ECA_EE/sign
with no parent path and assert equality.
Also includes:
- test_helpers.c: OpenSSL-based X.509 signature verification, public key
extraction, COSE_Sign1 parsing and verification, CWT subject public
key extraction, and compressed input computation.
- nat20_qemu_init.sh: init wrapper for running tests in QEMU CI.
- GitHub Action steps to build the rootfs and run the test suite in QEMU.
- Buildroot package (nat20test) with OpenSSL dependency.
eaf904a to
47500a2
Compare
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This reverts commit 0612f25.
| - name: Build rootfs image | ||
| env: | ||
| NAT20LIB_OVERRIDE_SRCDIR: ${{ github.workspace }} | ||
| NAT20DEVICE_OVERRIDE_SRCDIR: ${{ github.workspace }} | ||
| NAT20CRYPTO_OVERRIDE_SRCDIR: ${{ github.workspace }} | ||
| NAT20SW_OVERRIDE_SRCDIR: ${{ github.workspace }} | ||
| LIBNAT20_OVERRIDE_SRCDIR: ${{ github.workspace }} | ||
| NAT20TEST_OVERRIDE_SRCDIR: ${{ github.workspace }} | ||
| run: make -C ${{ runner.temp }}/buildroot.build/buildroot -j $(( $(nproc) + 1 )) | ||
|
|
||
| - name: Run integration tests in QEMU | ||
| timeout-minutes: 5 | ||
| run: | | ||
| BUILDROOT_DIR="${{ runner.temp }}/buildroot.build/buildroot" | ||
| KERNEL="${BUILDROOT_DIR}/output/images/bzImage" | ||
| ROOTFS="${BUILDROOT_DIR}/output/images/rootfs.ext2" | ||
|
|
||
| qemu-system-x86_64 \ | ||
| -M pc \ | ||
| -kernel "${KERNEL}" \ | ||
| -drive file="${ROOTFS}",if=virtio,format=raw \ | ||
| -append "rootwait root=/dev/vda console=ttyS0 init=/usr/bin/nat20test_qemu_init.sh" \ | ||
| -nographic \ | ||
| -no-reboot \ | ||
| -net none \ | ||
| 2>&1 | tee qemu_output.log | ||
|
|
||
| if grep -q "INTEGRATION_TESTS_PASSED" qemu_output.log; then | ||
| echo "Integration tests passed." | ||
| else | ||
| echo "Integration tests failed. QEMU output:" | ||
| cat qemu_output.log | ||
| exit 1 | ||
| fi |
There was a problem hiding this comment.
These changes are also present in #104. Based on the PR title, I think they should be here.. can you please separate them out so it's more clear?
| uint8_t* compressed_out, | ||
| size_t compressed_out_size) { | ||
| n20_crypto_digest_context_t* digest_ctx = NULL; | ||
| n20_error_t err = n20_crypto_nat20_open(&digest_ctx); |
There was a problem hiding this comment.
Basically re-iterating what copilot said below. We don't close this in the success path or in any of the error paths.
| /* CDI1: subject_key_type × format, issuer = P-256, no parent path */ | ||
| for (size_t si = 0; si < NUM_KEY_TYPES; si++) { | ||
| for (size_t fi = 0; fi < NUM_CDI_FORMATS; fi++) { | ||
| level1_artifacts.cdi1_valid[si][fi] = issue_cdi_cert(n20_crypto_key_type_secp256r1_e, |
There was a problem hiding this comment.
From the code below it looks like we are OK with some of these failing and other succeeding, but it's hard to derive the actual expectations just by looking at the code. It could be that the expectations will vary across devices/implementations, but this integration test is already pretty tightly coupled to the reference implementation.
Obviously Copilots suggestion of expecting them all to succeed is wrong, do it would be nice if we could at least validate that the expectations are met.
The same comment applies to cdi2_valid, eca_valid, eca_ee_valid, and signature valid.
| for (size_t fi = 0; fi < NUM_CDI_FORMATS; fi++) { | ||
| cert_buffer_t cert; | ||
| bool ok = | ||
| issue_cdi_cert(KEY_TYPES[ii], KEY_TYPES[si], CDI_FORMATS[fi], no_path, &cert); |
There was a problem hiding this comment.
So each of these cases are expected to pass? Aren't these the same calls as were made in the level 1 test? Or does the promotion change their behavior from level1?
Adds a C integration test binary (nat20_integration_test) that exercises
the full DICE service stack via /dev/nat200. The test generates certificate
chains across all supported key type (P-256, P-384) and format (X.509,
COSE) permutations, verifies cryptographic signatures at each link, and
confirms that parent_path-based issuance produces identical results to
direct issuance after promote.
Test structure:
signatures using parent paths of varying depth from the UDS level.
Verify all X.509 and COSE chains cryptographically.
with reduced parent path depth and assert byte-for-byte equality.
with no parent path and assert equality.
Also includes:
extraction, COSE_Sign1 parsing and verification, CWT subject public
key extraction, and compressed input computation.