Post-Quantum TLS at the Edge: wolfSSL on NVIDIA Jetson Orin

The NVIDIA Jetson Orin Nano is widely deployed in robotics, industrial vision and edge AI, where devices terminate TLS, verify signed firmware, and are increasingly expected to have a post-quantum migration path. Whether that migration is affordable on embedded silicon is a practical question, so we measured it: what the Orin Nano’s CPU delivers for cryptography, ML-KEM and ML-DSA performance, and wolfSSL 5.9.2 against OpenSSL 3.0.2 for TLS 1.3 on the same board.

Key findings

  • The ARMv8 Crypto Extensions deliver up to 76x over portable C, with AES-GCM at ~2 GiB/s per core, beyond the board’s network capacity. wolfSSL’s AArch64 assembly targets them directly.
  • ML-KEM-768 sustains 37,287 encapsulations/sec on a single core, outpacing the classical signature beside it in the handshake. Post-quantum key establishment is practical on this class of device today.
  • Post-quantum signatures are practical too: ML-DSA-44 signs at 3,628/sec and verifies at 11,317/sec.
  • wolfSSL performs ~1.58x more TLS 1.3 handshakes/sec than OpenSSL 3.0.2, with materially lower variance, and leads on AES-GCM (1.18x) at parity on SHA-256.
  • Single-Precision assembly cuts TLS handshake cost from 5.20 ms to 1.79 ms, nearly tripling connections completed.
  • The Orin offers hardware key protection through its OP-TEE fTPM, which is backed by the Tegra Security Engine. wolfTPM supports it out of the box over the standard Linux TPM interface, including TLS authentication with private keys that never leave the secure world.
  • Build with –enable-armasm –enable-sp –enable-sp-asm; omitting the SP options understates ECDSA signing by 18.6x.
  • Choose SHA-256 over SHA-512 where the protocol allows. The CPU accelerates SHA-256 in hardware but has no SHA-512 instruction, making SHA-256 3.4x faster here (1053.6 vs 306.9 MiB/s).

Figures come from a Jetson Orin Nano Developer Kit: six Cortex-A78AE cores at 1728 MHz in MAXN_SUPER with jetson_clocks, on L4T Ubuntu 22.04.5 (kernel 5.15.148-tegra), booting UEFI Secure Boot to wolfBoot to a wolfCrypt-verified Linux kernel. All measurements are single-threaded on one of the six cores, so they are per-core figures, not aggregate throughput.

ARMv8 Crypto Extensions

The Cortex-A78AE reports Features: asimd aes pmull sha1 sha2, and wolfSSL’s AArch64 assembly targets exactly these: AES for block encryption, PMULL (carry-less multiply) for GCM authentication, SHA-1/SHA-2 for hashing, and NEON (asimd) for ChaCha20, Poly1305 and ML-KEM.

Symmetric and hash performance

Same source, built with and without the assembly:

Algorithm C (MiB/s) ARM assembly (MiB/s) Gain
AES-128-GCM decrypt 26.3 2007.1 76.2x
AES-128-GCM encrypt 74.5 2012.8 27.0x
AES-128-CBC decrypt 160.6 3332.0 20.7x
AES-256-CBC encrypt 108.2 822.8 7.6x
SHA-256 138.7 1053.6 7.6x
GMAC n/a 4788.2 n/a

AES-GCM sustains roughly 2 GiB/s per core, beyond the board’s gigabit Ethernet capacity, so bulk TLS encryption is not the network constraint.

Hashes with no matching instruction land lower: SHA-384/SHA-512 at 306.9 MiB/s, SHA3-256 at 252.5, SHAKE128 at 310.2.

This makes SHA-256 about 3.4x faster than SHA-512 on this part, because the CPU implements a SHA-256 instruction and no SHA-512 one. Server-class CPUs that carry the SHA-512 extension reverse that ranking, so a cipher suite or signature choice tuned on a server may be the slower option here. Where the protocol lets you pick, pick SHA-256.

Note: the wolfCrypt benchmark’s “Cycles per byte” column is not valid on this platform, because wolfSSL falls back to the 31.25 MHz ARM generic timer when userspace cannot read the PMU; throughput and ops/sec are elapsed-time measurements and unaffected.

Public key performance

Operation ops/sec
ECDSA P-256 sign 22,582
ECDSA P-256 verify 8,644
ECC P-256 key generation 30,979
ECDHE P-256 agree 9,043
RSA-2048 private (sign) 725
RSA-2048 public (verify) 23,909

These require Single-Precision assembly; see Build configuration.

Post-quantum algorithms

ML-KEM(FIPS 203) and ML-DSA (FIPS 204), single core. All figures are operations per second:

ML-KEM key gen (ops/sec) encapsulate (ops/sec) decapsulate (ops/sec)
512 67,889 58,928 43,016
768 42,136 37,287 28,125
1024 24,537 22,779 18,159
ML-DSA key gen (ops/sec) sign (ops/sec) verify (ops/sec)
44 11,904 3,628 11,317
65 6,333 2,330 7,020
87 4,242 1,844 4,184

ML-KEM-768, the level most deployments will select, is faster than the ECDSA P-256 signature accompanying it in a handshake, so post-quantum key establishment is not the limiting factor here. ML-KEM gains 1.6x to 1.8x from the ARMv8 assembly (it has a dedicated AArch64 NEON implementation); ML-DSA gains little, being SHAKE-dominated.

TLS 1.3: wolfSSL and OpenSSL

Handshake rate, measured with a single common client (openssl s_time) against each library’s server in turn: same RSA-2048 certificate, cipher suite (TLS_AES_128_GCM_SHA256) and duration, over loopback. One client against both servers is what makes the results comparable.

Server Handshakes/sec Variation (4 runs)
wolfSSL 5.9.2 ~394 ±0.2%
OpenSSL 3.0.2 ~249 ±4%

wolfSSL completes approximately 1.58x more TLS 1.3 handshakes per second, with markedly more consistent timing. (s_time‘s “connections/user sec” derives from client CPU time, not elapsed time, and misleadingly favours the slower server; connections per elapsed second is the correct measure.)

At the primitive level the two are closely matched, each ahead in different operations. OpenSSL figures are openssl speed -elapsed at 16 KB blocks, converted to MiB/s:

Operation wolfSSL OpenSSL 3.0.2
AES-128-GCM 2012.8 MiB/s 1702.7 MiB/s
SHA-256 1053.6 MiB/s 1035.3 MiB/s
RSA-2048 sign 724.5/s 672.0/s
ECDSA P-256 verify 8,644/s 8,234/s
ECDSA P-256 sign 22,582/s 25,041/s
RSA-2048 verify 23,909/s 27,024/s

With the primitives this close, the handshake advantage reflects efficiency in the surrounding protocol implementation rather than arithmetic speed.

The asymmetric ranking is also specific to this CPU and this OpenSSL build: repeating the same comparison on a Raspberry Pi 5 (Cortex-A76, OpenSSL 3.0.18) kept ECDSA sign ahead for OpenSSL but reversed RSA-2048 verify to wolfSSL by 1.19x. Treat single-operation comparisons as platform-specific.

Isolating the TLS stack from kernel networking separates what each build option buys:

Build Bulk transfer (MiB/s) Handshake
Portable C 72.4 6.13 ms
+ ARMv8 assembly 1320.8 5.20 ms
+ SP assembly 1259.5 1.79 ms

ARMv8 assembly delivers roughly 18x on bulk throughput; Single-Precision assembly cuts handshake cost by a factor of three without affecting throughput. These runs also produced three tls_bench fixes: monotonic-clock timing, correct MiB/s labelling, and a divide-by-zero guard.

Build configuration

./configure --enable-armasm --enable-sp --enable-sp-asm

–enable-armasm accelerates symmetric ciphers and hashes only. Public key arithmetic needs –enable-sp –enable-sp-asm:

Operation –enable-armasm only With SP assembly Gain
ECC P-256 key generation 1,248 30,979 24.8x
ECDSA P-256 sign 1,215 22,582 18.6x
ECDHE P-256 agree 1,254 9,043 7.2x
RSA-2048 private 214 725 3.4x

The benchmark header shows which is active: Multi-Precision: Wolf(SP) … sp_int.c without SP assembly, Single Precision: … asm sp_arm64.c with it. Any AArch64 comparison should confirm that line first. Every configuration reported passes wolfcrypt/test with exit code 0, including ML-KEM and ML-DSA.

Cryptographic hardware on Orin

Two distinct hardware resources are available, serving different purposes: the CPU extensions for speed, and the Security Engine for key protection.

Resource

Status

Applicable use
ARMv8 Crypto Extensions Available in-core Already used by wolfSSL, the source of the gains above
fTPM 2.0 (/dev/tpmrm0) Available Runs as an OP-TEE TA backed by the SE, so it is the practical route to SE-protected asymmetric private keys, plus attestation and seeding
Tegra Security Engine (SE/PKA1/RNG1) Secure-world resident Reached from Linux through the fTPM; direct access would need an OP-TEE trusted application
Kernel crypto API (AF_ALG) Available No advantage here, since only CPU implementations are registered

Bulk cryptography runs in-core: every implementation registered in /proc/crypto is CPU-based, which is the right arrangement given the extensions reach ~2 GiB/s. The part implements the aes, pmull, sha1 and sha2 extensions but not the optional sha3 or sha512 ones, which is why SHA-512, SHA-3 and SHAKE gain little from assembly while SHA-256 gains 7.6x.

Hardware key protection: the fTPM
The Orin runs a TPM 2.0 as an OP-TEE trusted application backed by the Security Engine, exposed to Linux at /dev/tpmrm0. That makes it the supported route to asymmetric private keys that never exist in normal-world memory, along with attestation and sealing.

wolfTPM supports this out of the box.Build with –enable-devtpm and it speaks to the fTPM over the standard Linux TPM interface, with no vendor driver and no new firmware. That includes TLS authentication using a TPM-resident private key: wolfTPM’s crypto callback layer (wolfTPM2_SetCryptoDevCb) routes signing to the TPM, so a wolfSSL server or client can present a certificate whose private key stays inside the secure world. Key generation, sealing, NV storage and PCR quotes are equally available; wolfBoot already extends its kernel measurement into PCR 9, so an attestation quote can tie the running kernel to the same TPM.

Treat it as a key vault rather than an accelerator. Every operation crosses an SMC world switch into the secure world, and the fTPM’s RNG runs at roughly 2 KB/s against 245 MiB/s for wolfSSL’s DRBG. Keys held in the TPM will sign more slowly than software keys; the return is that they cannot be extracted.

Direct SE access outside the TPM would mean writing an OP-TEE trusted application, and the infrastructure exists for it (/dev/tee0, CONFIG_OPTEE=y, a linaro,optee-tz node). wolfSSL would bind to such a TA through wc_CryptoCb_RegisterDevice without library changes. In practice the fTPM already provides the property most deployments want, so that work is only worth undertaking for a requirement the TPM cannot express.


If you have questions about any of the above, please contact us at +1 425 245 8247.

Posted in Post-Quantum, Uncategorized