diff --git a/CMakeLists.txt b/CMakeLists.txt index ef46235..bfc45f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,9 @@ set(LIBNAT20_DOC_PAGES # Add additional input files for doxygen here. README.md CONTRIBUTING.md + examples/linux/README_linux.md + examples/linux/nat20crypto/SECURITY.md + src/service/DICE_SERVICE.md ) set(LIBNAT20_PUB_CRYPTO_BSSL_HEADERS @@ -686,6 +689,7 @@ if (NAT20_WITH_DOCS) set(DOXYGEN_USE_MDFILE_AS_MAINPAGE README.md) set(DOXYGEN_MACRO_EXPANSION YES) + set(DOXYGEN_EXTRACT_STATIC YES) doxygen_add_docs(nat20_docs ${LIBNAT20_PUB_HEADERS} diff --git a/README.md b/README.md index e2c152e..534d1a9 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,15 @@ make nat20_docs Open the documentation by pointing your browser to `html/index.html` in your build directory. +## Examples + +### Linux DICE kernel modules + +The `examples/linux/` directory contains a complete Linux kernel module +implementation of a software DICE node, including a userspace CLI tool and a +Buildroot-based build environment targeting QEMU. See +[README_linux.md](examples/linux/README_linux.md) for details. + ## API Reference The API references is generated from the main branch using doxygen and deployed diff --git a/examples/linux/README_linux.md b/examples/linux/README_linux.md new file mode 100644 index 0000000..5ca24ce --- /dev/null +++ b/examples/linux/README_linux.md @@ -0,0 +1,151 @@ +# Linux DICE Example + +This directory contains a set of Linux kernel modules and a userspace CLI tool +that together implement a software DICE node using libnat20. + +## Architecture + +The example is structured as four kernel modules with the following dependency +chain: + +@dot +digraph mod_deps { + rankdir=LR; + node [shape=record]; + nat20sw -> nat20crypto; + nat20sw -> nat20device; + nat20crypto -> nat20lib; + nat20device -> nat20lib; +} +@enddot + +### nat20lib + +A kernel module wrapper around the core libnat20 C library. It compiles all +core library sources, i.e, +- certificate rendering primitives for X.509 and COSE_Sign1 wrapped CWTs, +- DICE key derivation procedures including + - CDI derivation, + - CDI_ID computation, + - AKDF key pare generation, + - issuing and signing of CDI attestaiton and ECA certificates, +- service messages (un)marshaling and dispatch, and +- gnostic node service implementation + +into a kernel obejct (`.ko`) and re-exports their symbols via `EXPORT_SYMBOL()` +so that other kernel modules can use them. + +### nat20crypto + +Implements the libnat20 crypto interface (`n20_crypto_context_t`) using the +Linux kernel's crypto API. Provides ECDSA signing (P-256, P-384), HKDF key +derivation, and SHA-2 hashing — all in kernel space. + +\warning The eliptic curve crypto (ECC) implementaiton in this module is not ready +for production see [Security Assessment - nat20crypto](examples/linux/nat20crypto/SECURITY.md) +for details. + +### nat20device + +A generic character device framework for DICE services. On load it allocates +the `nat20` device class. Backend modules (like `nat20sw`) register via +`nat20device_register_driver()`, which creates: + +- `/dev/nat20` — a character device for DICE service requests (write a CBOR + request, read the CBOR response). +- `/sys/kernel/security/nat20/dice_chain` — a read-only securityfs file + exposing the boot-time DICE certificate chain. + +### nat20sw + +A concrete software DICE node that wires `nat20lib`, `nat20crypto`, and +`nat20device` together. On load it derives a UDS from a hardcoded passphrase +(for demonstration purposes only), issues a self-signed X.509 certificate, and +registers itself with the `nat20device` framework. + +### nat20cli + +A userspace command-line tool that communicates with the DICE service via +`/dev/nat200`. It can issue CDI certificates, ECA certificates, and advance +the DICE layer via the `promote` command. + +## The dice_chain securityfs interface + +Each registered nat20device driver instance exposes a `dice_chain` file at +`/sys/kernel/security/nat20/dice_chain`. This file contains the DICE +certificate chain constructed during bootup, encoded as a CBOR +indefinite-length array. + +### Encoding + +The file contains a single CBOR indefinite-length array (`0x9f ... 0xff`). +Each element in the array is one of the following CBOR-tagged values: + +| CBOR tag | Content | Description | +|----------|---------|-------------| +| `#6.80150(bstr)` | DER-encoded X.509 certificate | An X.509 certificate, typically with the Open DICE Input extension (OID `1.3.6.1.4.1.11129.2.1.24`). | +| `#6.18(COSE_Sign1)` | COSE_Sign1 with CWT payload | A COSE certificate as specified by the Open DICE profile or a similar custom DICE profile. | +| `#8.80152(COSE_Key)` | COSE_Key | A public key. | + +### Ordering and semantics + +- The first element represents the root device identity key. It may be a + self-signed certificate, a CA-signed certificate, or a bare public key + (`#8.80152`). +- A benign implementation orders the remaining certificates from root to leaf. +- The chain only contains certificates generated during bootup. Userspace is + responsible for managing additional CDI certificates issued via the + `/dev/nat20` character device. + +## Building with Buildroot + +The `br_external/` directory provides a Buildroot external tree for building +all components targeting a QEMU x86_64 virtual machine. + +```sh +# Bootstrap the Buildroot environment (build directory must be outside the repo) +BUILDROOT_DIR=/path/to/buildroot.build +examples/linux/br_external/bootstrap.sh qemu $BUILDROOT_DIR + +# Build everything +cd $BUILDROOT_DIR/buildroot +make +``` + +### Local development +The bootstrap script installs a file `envsetup.sh` in `$BUILDROOT_DIR` +which sets the `*_OVERRIDE_SRCDIR`s for all of the packages nat20* etc., +and defines helper functions for rebuilding and running the result in +qemu. + +``` +# Source the environment +cd $BUILDROOT_DIR +. envsetup.sh + +# Rebuild a package and the rootfs, this is equivalent to +# pushd $BUILDROOT_DIR/buildroot +# make nat20sw-rebuild all +# popd +brrebuild nat20sw + +# Rebuild all packages and the rootfs +brrebuild all + +# Run the resulting rootfs and kernel in qemu +run-qemu + +# Run the nat20cli test in qemu and shut down the emulator +run-nat20cli-test + +# Run the nat20test integration test in qemu and sht down the emulator +run-nat20test-test +``` + +### Caveat - `bootstrap.sh` +The bootstrap script is usefull for setting up the development environment +once, but it cannot keep the build root environment in sync with the upstream +repository. When pulling the upstream repository and changes where made to +`envsetup.sh`, `bootstrap.sh`, or the buildroot config, it may be necessary +to bootstrap a new environment. A savvy user may track the changes and manually +update the environment to save 30 minutes rebuilding the build root environment. \ No newline at end of file diff --git a/examples/linux/nat20crypto/SECURITY.md b/examples/linux/nat20crypto/SECURITY.md index ca24b59..89b39fd 100644 --- a/examples/linux/nat20crypto/SECURITY.md +++ b/examples/linux/nat20crypto/SECURITY.md @@ -9,19 +9,9 @@ key information through timing side channels. ## Key Material Leak Analysis -### Addressed - -- **`nat20crypto_sign`** — stack buffers `z`, `k`, `k_inv`, `rs` are wiped via - `memzero_explicit` on all exit paths. This covers the nonce, the inverted - nonce, the byte-swapped private key (in `k_inv` via the `key_bytes` alias), - and intermediate signature values. -- **`nat20crypto_key_destroy`** — uses `memzero_explicit` before `kfree`. -- **`nat20crypto_make_secret`** — the input `secret_in` buffer is caller-owned; - the output key is heap-allocated and properly zeroed on free. - ### Outstanding issues -#### `n20_rfc6979_k_generation` internal state +#### n20_rfc6979_k_generation internal state This function (from nat20lib) uses HMAC internally with the private key as input. Whether its internal buffers are zeroed depends on its implementation. @@ -34,11 +24,12 @@ Out of scope for this module but noted as a dependency. In a DICE boot-time context where signing happens once during module init with no concurrent attacker (single-threaded init, no network, no user interaction), timing side channels are not practically exploitable. For a general-purpose -signing oracle accessible from userspace, the issues below would be exploitable. +signing oracle accessible from userspace, i.e., the embedded-CA functionality, +the issues below would be exploitable. ### High risk -#### `vli_mod_inv` — variable-time modular inverse +#### vli_mod_inv — variable-time modular inverse The kernel's `vli_mod_inv` computes the modular inverse of `k` using a binary extended GCD with data-dependent branches and loop counts. The number of @@ -46,7 +37,7 @@ iterations depends on the value of `k`, leaking nonce information through timing. Partial nonce knowledge enables private key recovery via lattice attacks. -#### `ecc_make_pub_key` — variable-time point multiplication +#### ecc_make_pub_key — variable-time point multiplication The kernel's ECC point multiplication uses a double-and-add algorithm. Older kernels (pre-6.10) use a naive implementation with data-dependent @@ -54,7 +45,7 @@ doublings/additions, leaking the scalar `k` through timing. ### Medium risk -#### `vli_mod_mult_slow` — conditional subtraction +#### vli_mod_mult_slow — conditional subtraction The kernel's `vli_mod_mult_slow` is a shift-and-add modular multiplication. The loop count is constant, but the conditional subtraction after each shift @@ -82,7 +73,7 @@ about the private key. The kernel's SHA implementations are generally constant-time for the compression function. HMAC processes fixed-size blocks. Low timing risk. -#### `ecc_swap_digits` / `memcpy` / simple copies +#### ecc_swap_digits / memcpy / simple copies These process a fixed number of bytes regardless of value. Constant-time. diff --git a/include/nat20/crypto/nat20/crypto.h b/include/nat20/crypto/nat20/crypto.h index 07e7568..ddb1726 100644 --- a/include/nat20/crypto/nat20/crypto.h +++ b/include/nat20/crypto/nat20/crypto.h @@ -70,7 +70,7 @@ extern n20_error_t n20_crypto_nat20_open(n20_crypto_digest_context_t** ctx_out); * @brief Close the NAT20 cryptographic context. * * This function closes and frees the resources associated with the - * context @ref ctx_out. + * context @p ctx_out. * * In the current implementation this is a no-op, as the context * is a singleton. But this may change in the future, and must diff --git a/include/nat20/crypto/nat20/rfc6979.h b/include/nat20/crypto/nat20/rfc6979.h index 1c03cb0..a04584d 100644 --- a/include/nat20/crypto/nat20/rfc6979.h +++ b/include/nat20/crypto/nat20/rfc6979.h @@ -54,7 +54,13 @@ extern "C" { * index always has the lowest significance. */ struct n20_bn_s { + /** + * @brief The number of words in the big number. + */ size_t word_count; + /** + * @brief The array of words representing the big number. + */ uint32_t* words; }; diff --git a/include/nat20/endian.h b/include/nat20/endian.h index b2f8ce7..3d24658 100644 --- a/include/nat20/endian.h +++ b/include/nat20/endian.h @@ -35,7 +35,10 @@ * . */ -/** @file Homogeneous Endian definitions for various environments. */ +/** + * @file endian.h + * @brief Homogeneous Endian definitions for various environments. + */ #pragma once diff --git a/include/nat20/limits.h b/include/nat20/limits.h index c502d58..ba40fba 100644 --- a/include/nat20/limits.h +++ b/include/nat20/limits.h @@ -35,7 +35,10 @@ * . */ -/** @file Homogeneous Limits definitions for various environments. */ +/** + * @file limits.h + * @brief Homogeneous Limits definitions for various environments. + */ #pragma once diff --git a/include/nat20/service/gnostic.h b/include/nat20/service/gnostic.h index ad3aba9..89baee1 100644 --- a/include/nat20/service/gnostic.h +++ b/include/nat20/service/gnostic.h @@ -60,8 +60,8 @@ extern "C" { * * The service node state includes a pointer to a crypto context and the minimal CDI * that the service node can use to derive other CDIs. The service operations - * for this implementation are defined in @ref src/service/gnostic.c, and is based - * on the DICE functionality implemented in @ref src/core/functionality.c. + * for this implementation are defined in src/service/gnostic.c, and is based + * on the DICE functionality implemented in src/core/functionality.c. * The supported operations include CDI promotion, issuing CDI certificates, * issuing ECA certificates, issuing ECA end-entity certificates, signing with ECA * end-entity keys. @@ -100,7 +100,7 @@ typedef struct n20_gnostic_node_state_s n20_gnostic_node_state_t; /** * @brief The service operations for the Gnostic Stateless service implementation. * - * This symbol is defined in @ref src/service/gnostic.c and represents + * This symbol is defined in src/service/gnostic.c and represents * a fully initialized n20_service_ops_t structure that can be used to * implement a service node with the Gnostic Stateless implementation. */