Skip to content

arch/arm64/imx9: add key store, signing and persistence to the ELE - #20343

Merged
xiaoxiang781216 merged 1 commit into
apache:masterfrom
royzah:upstream-ele-keystore
Sep 28, 2026
Merged

xiaoxiang781216 merged 1 commit into
apache:masterfrom
royzah:upstream-ele-keystore

Conversation

@royzah

@royzah royzah commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The i.MX9 ELE driver reaches the mailbox but not the key store the enclave offers. This adds sessions, key stores, key management, key generation, signing by handle, and the storage exchange that lets a key store outlive a boot.

A key generated in there is permitted one algorithm and one usage, and export can be withheld, so the private half has no command that returns it.

Storage runs the opposite way to every other command: the enclave asks the host to write its key store down and to give it back, and those requests arrive while a command of this side's is still outstanding. The reply tag is what tells a question from an answer.

Two things neither the reference implementation nor the headers say, each of which looks from outside like "this firmware has no key store":

  • Key store commands carry a trailing crc, the exclusive or of every word including the header. Without it the enclave answers rating 0xb9.
  • A persistent key lifetime is intent only. The strict flag on key generation is what writes the key to the store; without it the next signature answers rating 0x03.

Mailbox waits are now bounded in both directions, and the kilobyte reply buffer no longer sits on the caller's stack.

Impact

i.MX9 only, additive. No Kconfig, no init-time behaviour, nothing enabled by default. Boards that do not call the new functions are unaffected. The command payload layouts move to file scope as named types.

Testing

On an i.MX93 Cortex-A55 board, NuttX 12.11.0, kernel build. A P-256 key generated in the enclave, signing sha256(""):

$ openssl pkeyutl -verify -pubin -inkey pub.der -keyform DER -sigfile sig.der -in digest -pkeyopt digest:sha256
Signature Verified Successfully

Power cycled, then repeated. The key store is restored from the pieces the enclave exported, the public half is byte-identical, and a fresh signature verifies against it. ECDSA is randomised, so verification is the test, not comparison.

tools/checkpatch.sh -f passes on all three files.

@github-actions github-actions Bot added Arch: arm64 Issues related to ARM64 (64-bit) architecture Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces. labels Sep 24, 2026
@royzah
royzah force-pushed the upstream-ele-keystore branch from 9b7d7af to 8ab1820 Compare September 24, 2026 12:00
@royzah
royzah marked this pull request as draft September 24, 2026 12:02
@royzah
royzah force-pushed the upstream-ele-keystore branch from 8ab1820 to 26a6fb8 Compare September 24, 2026 12:06
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

@royzah
royzah force-pushed the upstream-ele-keystore branch from 26a6fb8 to 5cec1bc Compare September 24, 2026 16:14
@royzah
royzah marked this pull request as ready for review September 24, 2026 16:15
@royzah

royzah commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

@acassis @jerpelea could one of you take a look? It builds on #20191 and is already hardware-proven on the i.MX93 (key made, used, survives power loss).

@royzah

royzah commented Sep 27, 2026

Copy link
Copy Markdown
Contributor Author

Pushed two fixes found on hardware, squashed in:

  • the ELE mailbox and the shared msg had no lock, so /dev/random could interleave with a key store command from another thread. There's now a recursive imx9_ele_lock(); imx9_ele_get_random() takes it itself.
  • SIGNATURE_GENERATE was one word short of the PSA layout (salt_len + reserved were missing before the CRC).

nxstyle clean. Sorry for the re-review @xiaoxiang781216

@royzah
royzah force-pushed the upstream-ele-keystore branch from e3a6f6d to 7ce439f Compare September 27, 2026 07:13
@royzah

royzah commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor Author

@acassis @pussuw @tkaratapanis if any of you has ten minutes, extra eyes very welcome

@jlaitine jlaitine left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added just a few comments, nice work!

I'd re-check the cache operations. I made some quick notes about those, but didn't have time to really think twice. Please just re-check those points!

Comment thread arch/arm64/src/imx9/imx9_ele.c
Comment thread arch/arm64/src/imx9/imx9_ele.c
Comment thread arch/arm64/src/imx9/imx9_ele.c Outdated
Comment thread arch/arm64/src/imx9/imx9_ele.c Outdated
Comment thread arch/arm64/src/imx9/imx9_ele.c
Comment thread arch/arm64/src/imx9/imx9_ele.c Outdated
Comment thread arch/arm64/src/imx9/imx9_ele.c Outdated
Comment thread arch/arm64/src/imx9/imx9_ele.c Outdated
Comment thread arch/arm64/src/imx9/imx9_ele.c
The EdgeLock Enclave offers a key store the mailbox driver did not
reach. A key generated in there is permitted one algorithm and one
usage, and export can be withheld, so the private half has no command
that returns it.

Adds the session, key store and key management services, key generation,
signing by handle, and the storage exchange that makes a key store
outlive a boot. Storage runs the other way round from every other
command: the enclave asks the host to write its key store down and to
give it back, and those requests arrive while a command of this side's
is still outstanding, so the reply tag is what tells them apart.

Two things a port has to know and neither reference nor header says.
Key store commands carry a trailing crc, the exclusive or of every word
including the header, without which the enclave answers rating 0xb9. And
a persistent key lifetime is a statement of intent: the strict flag on
key generation is what writes the key to the store, and without it a
store exported around the key comes back without it.

Every mailbox wait is bounded. An enclave that stops answering must not
take the calling thread with it, and a reply buffer is a kilobyte, which
does not belong on the stack of whatever task asked for a signature.

Tested on an i.MX93: a P-256 key generated in the enclave, signing a
digest whose signature verifies against the returned public half on a
host, and still doing so after the board has been powered off.

Signed-off-by: Royyan Zahir <royzah@gmail.com>
@royzah
royzah force-pushed the upstream-ele-keystore branch from 7ce439f to 91c26c2 Compare September 27, 2026 18:22
royzah added a commit to tiiuae/nuttx that referenced this pull request Sep 27, 2026
Review on apache#20343: clean what the enclave reads, poll the
mailbox every 1us, and sign into a driver-owned line so callers need no
aligned buffer.
royzah added a commit to tiiuae/px4-firmware that referenced this pull request Sep 27, 2026
@jlaitine

Copy link
Copy Markdown
Contributor

Thanks @royzah, looks nice

@royzah

royzah commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

@xiaoxiang781216 and @acassis can you take another look ?

@xiaoxiang781216
xiaoxiang781216 merged commit 68dd87f into apache:master Sep 28, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm64 Issues related to ARM64 (64-bit) architecture Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants