Community Over Code · Glasgow 2026

WireGuard for Apache NuttX

Bringing Secure Remote Access to Embedded Devices

Satoru AkitaSony Semiconductor Solutions

QR code for the slidesSLIDES

About Me

Satoru Akita

Satoru Akita — edge AI engineer at Sony Semiconductor Solutions, working with Apache NuttX from the application side.

Fox icon
my icon on social media
1 2 3 ① Nagoya — born ② Sendai — university ③ Kawasaki — now

Japan

My background & activities

A model rocket on its launch pad
Rocket / Aerospace Engineering
A DNA nanostructure seen with cryo-TEM
DNA Nanorobotics
Test chips on a silicon wafer
Semiconductor Research
With a humanoid robot at a hackathon
Robots
Volunteering at an open-source conference
Open-Source Conference Volunteer
2 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
3 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 14 / 36

Project Overview

NUTTX RTOS Application / NSH NuttX network stack (BSD socket API) eth0 / wlan0 physical NIC wg0 WireGuard netdev — this project UDP socket (port 51820) Internet / LTE / satellite link WireGuard peer Linux, Windows, ...
Lightweight VPN

Bring WireGuard to NuttX-based microcontrollers.

Virtual interface

Use wg0 as a network interface for the VPN tunnel.

Secure communication

Exchange encrypted packets with WireGuard peers over UDP.

Takeaway

NuttX devices can now talk IP securely, like any other WireGuard peer.

PART 1 · 1/55 / 36

How it started

MID FEBRead the GSoC idea list. Started to study.
EARLY MARProposed the plan.
MAR 20Alan told me about this conference. Submitted a CfP.
EARLY APRSent the GSoC proposal.
EARLY MAYCfP accepted. GSoC proposal not selected. Kept going anyway.
OCT 11–14Glasgow — this talk.
FEB
MAR
APR
MAY
JUN
JUL
AUG
SEP
OCT
MAY – JULStudied NuttX and WireGuard, explored approaches
AUGV1
SEP –V2
VERSION 1Application (FLAT) · hardware testing
→
VERSION 2Kernel driver
DEVELOPMENT
Takeaway

The GSoC proposal was not selected, but the work went on.

PART 1 · 2/56 / 36

A Quick Overview of Apache NuttX

Apache NuttX
Apache NuttXA small RTOS for microcontrollers
  • POSIX-like real-time OS
  • Small footprint
  • Broad hardware support15+ CPU architectures · 300+ boards
  • Apache open-source project
RTOSStandard APIs
FreeRTOSIts own task API
ZephyrOwn API, optional POSIX layer
NuttXPOSIX-like by design

Used in real devices

A Fitbit Charge 3 fitness tracker on a wrist
FitbitFitness trackers (Charge 3 / 4)
The SORA-Q lunar robot
SORA-QLunar robot on Japan's 2024 Moon mission
1,000+
Xiaomi OpenVelaReported products: watches, speakers, displays
Takeaway

Apache NuttX is a POSIX-like RTOS used in a wide range of real-world embedded devices.

Sources: nuttx.apache.org/market-share · “NuttX at Fitbit” (2020) · docs.px4.io · Sony Developer Blog. Images: Sony; Wikimedia Commons (Charge 3: Vemerce, CC BY-SA 4.0; Pixhawk: Pixhawk project, CC BY 4.0; SORA-Q: テレストレラッソ, CC BY-SA 4.0)
PART 1 · 3/57 / 36

Sony's history with NuttX

2013–15

Early adoption

Ported NuttX to LC823425 / LC823450; first commercial audio products shipped in 2015.

2016–17

Commercial products

Walkman NW-WS620, SMR-10, ICD-TX800 and ICD-PX470 used NuttX.

2018

Xperia Ear Duo & SPRESENSE

Xperia Ear Duo shipped with CXD5602 / NuttX; SPRESENSE launched as a multicore development board.

2019–20

Upstream collaboration

Sony engineers upstreamed CXD56xx platform support and drivers, and shared the work in public NuttX talks.

2020s

Edge sensing

Expanded camera, GNSS, connectivity and edge-sensing capabilities.

Sony Walkman NW-WS620
Walkman NW-WS620
Sony Xperia Ear Duo
Xperia Ear Duo
Sony SPRESENSE boards
SPRESENSE
Takeaway

Sony's NuttX journey began with audio products, expanded through SPRESENSE, and evolved into long-term open-source collaboration.

PART 1 · 4/58 / 36

My Experience with NuttX

The ARICA CubeSat

SPRESENSE — Satellite Project

Sony's low-power board, the on-board computer of the ARICA-2 CubeSat (Aoyama Gakuin University, launched April 2026).

I took part through an internal, grassroots engineering initiative.

AITRIOS edge AI camera signage

AITRIOS — Edge AI Sensing Platform

Sony's platform for managing edge AI cameras and running inference on them.

I worked on setting up and operating camera systems that use ESP32 and Apache NuttX.

Takeaway

I wanted a secure way to access and troubleshoot remote embedded devices.

Images: ARICA project (ARICA CubeSat) · Sony Semiconductor Solutions (AITRIOS). ARICA-2: nanosats.eu/sat/arica-2 · SmallSat 2026 paper (Mabuchi et al.)
PART 1 · 5/59 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 210 / 36

Problem: How Can We Securely Access Remote Devices?

NEEDED — A SECURE PATH ALL THE WAY TO THE DEVICE Engineer Internet router / network Wi-Fi NuttX device WPA2 / WPA3 protects only this hop
Devices are far away

Embedded devices sit at remote sites and on other networks.

Remote diagnosis

Engineers need to check and fix them when something goes wrong.

A secure path

Wi-Fi security protects the radio link. Remote access needs its own secure path.

Takeaway

We needed a secure way to access and troubleshoot remote NuttX devices.

PART 2 · 1/411 / 36

Options: Ways to Reach a Remote Device

WayAny IP service (telnet, web…)?No server in the middle?Protected up to
Open a port to the Internetyesyesthe application itself
HTTPS / MQTT via a cloudno, only your API or messagesno, a server or brokerthe server or broker
Reverse tunnel / relay (SSH, WebSocket)one port per tunnelno, a relay hostthe relay host
VPN on the routeryes, the whole LANyesthe router, not the LAN behind it
Carrier closed networkyesno, the carrierthe carrier gateway
VPN on the device (this talk)yes, any IP serviceyes, any WireGuard peerthe device itself
Takeaway

Every option has trade-offs. I chose a VPN on the device, so the device itself is the end of the tunnel.

Each option can be made secure. The last column shows where its protection ends. Mesh VPN agents (Tailscale, ZeroTier) are another “VPN on the device” option, but they usually need a bigger OS.
PART 2 · 2/412 / 36

Solution: A VPN on the Device

Engineer · Linux · Windows real, existing WireGuard peers WIREGUARD TUNNEL NuttX device wg0

Why WireGuard?

Small & simple

Far less code than IPsec or OpenVPN, so it is easier to review and to port.

IPsec~420k OpenVPN~120k WireGuard~3.8k
Lines of code, 2018 — not today's counts
Modern cryptography

ChaCha20-Poly1305 and Curve25519, in one fixed, well-defined suite.

UDP-based tunnel

Encrypted IP packets over UDP. It works with existing WireGuard peers such as Linux, and the microcontroller itself is the VPN endpoint.

Takeaway

Run a lightweight, standard VPN directly on the NuttX device.

Lines of code (rounded): J. Donenfeld, “WireGuard”, Linux Plumbers Conference 2018, wireguard.com/talks/lpc2018-wireguard-slides.pdf. Specific implementations, counted in 2018; the talk's own slides differ slightly for OpenVPN.
PART 2 · 3/413 / 36

Architecture: where wg0 sits

Application TCP / UDP / IP wg0 (NET_LL_TUN netdev) WireGuard encrypt / decrypt UDP socket wlan0 / usrsock · physical network TX RX
Takeaway

To NuttX, wg0 is a normal network device. Under it, WireGuard turns its packets into encrypted UDP.

PART 2 · 4/414 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 315 / 36

Porting Strategy: Start from wireguard-lwip

STARTING POINTgithub.com/smartalock/wireguard-lwipAn existing open-source WireGuard for lwIP
KEEP

Protocol & crypto

Reuse the WireGuard protocol and cryptography, with two small fixes.

ADAPT

Platform hooks

Implement NuttX-specific system functions.

REPLACE

lwIP network glue

Use NuttX networking APIs instead of lwIP.

Takeaway

We ported wireguard-lwip to NuttX by reusing the core, adapting platform hooks, and replacing the lwIP integration.

PART 3 · 1/216 / 36

Mapping lwIP Networking to NuttX

ConceptlwIPNuttX
Network devicestruct netifstruct net_driver_s
Packet bufferspbufiob (d_iob)
Registrationnetif_add()netdev_register()
Sendingoutput callbackd_txavail → devif_poll()
UDP “wire”udp_pcb, udp_sendto()UDP socket, psock_sendto()

These are matches of ideas, not a one-to-one swap of APIs.

Takeaway

Porting meant using NuttX's own building blocks, not bringing lwIP into NuttX.

PART 3 · 2/217 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 418 / 36

Version 1: WireGuard as a NuttX application

GOAL

Run a standard WireGuard tunnel as a NuttX application.

Reuse the existing core and implement the NuttX integration.

LayerWork neededIn this port
Protocol & cryptoAlmost noneportable CCrypto byte-identical. Two small fixes to the protocol core.~3,100 lines reused · ~40 changed
OS hooksFour functionssmallclock, /dev/urandom, TAI64N, load check~120 new lines
Network glueThe real worknetdev + UDP socket + RX task~1,200 new lines
Takeaway

Version 1 proved that WireGuard could run on NuttX.It also exposed OS and networking problems that the first tunnel did not reveal.

Lines include comments, from git history. Reused: the vendored wireguard-lwip files. New: the first working tunnel, 2026-08-13. Fixes: 2026-09-18.
PART 4 · 1/519 / 36

Where it was hard: six bugs

#BugShowed up inLesson
1The receive thread stopped when the wg command exitedapps versionpthread_detach() frees memory later. It does not keep a thread alive.
2ping works, TCP dies in detailapps versionA file descriptor belongs to one task group.
3“No real impact” was 10× in detailapps versionMeasure a quick fix before you call it free.
4Stack 94% full; saving the config froze the boardreal boards only, never simMeasure on real hardware. Sim's big stacks hide it.
5Handshake OK, data fails: NuttX's own ChaCha20‑Poly1305 part 5kernel driverA passing handshake does not prove the data path.
6A 6 KB array on a 3 KB kernel stack part 5BUILD_KERNEL (QEMU)The same stack lesson, one level deeper.
Takeaway

Most of them hid behind a test that passed, so I first looked in the wrong place.

PART 4 · 2/520 / 36

Bug ②: Ping Works. TCP Dies.

SYMPTOM

ping works: 0% loss.

A TCP handshake even completes, then the connection dies.

psock_sendto: ret=-1 errno=9
EBADF — “Bad file descriptor”

ROOT CAUSE & FIX

Sends from the wg_rx task worked. Sends from the system work queue, which flushes TCP data, failed.

Cause: a file descriptor belongs to one task group. It is not valid in another one.

Fix: use psock_*() on a struct socket. No fd, so any task can use it.

Takeaway

If only some tasks fail, look at what each task owns. Here, it was the file descriptor.

PART 4 · 3/521 / 36

Bug ③: “No Real Impact” Was 10× Slower

QUICK FIX

Check every 50 ms

Dropping fds also broke poll(), so I polled the socket. I thought the only cost was waking an idle CPU.

Measured: about 10× slower.

REAL FIX

Event-driven wake-up

A callback on psock_poll() and a semaphore: a real blocking wait. Each packet wakes the thread when it arrives.

Takeaway

A quick fix you never measure can look free. Measure it.

PART 4 · 4/522 / 36

Version 1 demo: the first video

1  telnet 10.10.0.2
2  uname -a, ifconfig
3  webserver &
4  browser: http://10.10.0.2/

ESP32-S3 DevKit, apps version (FLAT). USB unplugged.

Other end: the official Windows WireGuard client.

Video: youtu.be/1kyX2av5WG4

Takeaway

Version 1 was enough for a demo. Next, I made it a real NuttX driver.

PART 4 · 5/523 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 524 / 36

Version 2: WireGuard as a NuttX kernel driver

BEFORE — VERSION 1

An application

Lives in apps/ and reaches into kernel internals (psock_*).

Works only in a FLAT build, and does not fit as an in-tree driver.

AFTER — VERSION 2

A kernel driver

wg0 lives in drivers/net/wireguard/. A small wg command sets it up through ioctl.

Made for FLAT, PROTECTED and KERNEL builds.

BUILD MODES

FLATApplications and kernel share one address space.
PROTECTEDMPU separates application and kernel memory.
KERNELMMU provides separate address spaces.
Takeaway

The goal: a proper kernel driver for every NuttX build mode, in a form that is easier to review upstream.

PART 5 · 1/425 / 36

The Kernel Design: The Big Picture

USER SPACE wg command apps/system/wg · genkey · set · show USER / KERNEL BOUNDARY NUTTX KERNEL ioctl: one flat struct, no pointers the private key is write-only NuttX network stack TCP / UDP / IP wg0 netdev drivers/net/wireguard owns its UDP socket owns its RX thread timers · peers · cookies NuttX crypto (crypto/) Encrypted UDP wlan0 / usrsock → peer
Takeaway

The driver owns everything that must keep running. The command only sends settings, and then it can exit.

PART 5 · 2/426 / 36

Two Issues Found During Kernel Integration

CRYPTOGRAPHY — ChaCha20-Poly1305

NuttX crypto/chachapoly.c

  • The nonce counter sits in different bytes from the RFC 8439 / WireGuard layout.
  • Counter 0 still matches: the handshake works, but data packets after the first fail.
  • A two-line fix with test vectors, kept as its own change.
KERNEL STACK — Stack Overflow

This driver, KERNEL build only

  • Setting the peers put a 6 KB array on a 3 KB kernel stack: overflow, then panic.
  • The sim (FLAT, big stacks) never showed it.
  • A bug in the driver itself. The array now lives on the heap.
Takeaway

Porting WireGuard also surfaced findings worth sharing with the NuttX community.

PART 5 · 3/427 / 36

Testing: What Ran Where

Build modeEnvironmentResult
FLATESP32-S3 · SPRESENSEreal boards✓ Verified
KERNELQEMU rv-virttunnel to Linux; 4 CPUs under load✓ Verified
PROTECTEDQEMU rv-virtone fault found and fixed: 20/20 runs✓ Verified
KERNEL / PROTECTEDReal hardware— Not tested yet

✓ means it passed in the conditions noted here. It is not a guarantee for other hardware.

Takeaway

Verified on real boards in FLAT builds and on QEMU in KERNEL / PROTECTED builds.Real-hardware testing for those modes remains open.

PART 5 · 4/428 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 629 / 36

Live Demo: Stack-chan over WireGuard

NETWORK SETUP

Laptop WireGuard peer VPN IP 10.10.0.1 Smartphone Wi-Fi hotspot Provides the local network Stack-chan Apache NuttX + WireGuard VPN IP 10.10.0.2 Wi-Fi Wi-Fi Encrypted WireGuard Tunnel

LIVE DEMO STEPS

StepWhat to demonstrateCommand / Action
1VPN Connectionwg show
2Remote Logintelnet 10.10.0.2
3Network Interfaceifconfig → wg0
4Control Stack-chanChange face / Play voice
Stack-chan, a palm-sized robot with a small face on its screen Stack-chan Open-source palm-sized robot github.com/meganetaaan/stack-chan
Photo: Stack-chan project (docs/images, Apache License 2.0).
PART 6 · 1/230 / 36

Live Demo: backup video

THREE TERMINALS

Left: control
Middle: tcpdump, encrypted
Right: tcpdump, plaintext

A recording of the same demo: Stack-chan over WireGuard.

Video: youtu.be/kMRaY8cDx2E

PART 6 · 2/231 / 36

Agenda

1

Overview & background

Project origins · NuttX & Sony · my experience

~5 MIN
2

The Problem & Solution

Remote access challenge · why WireGuard

~4 MIN
3

The Development Plan

Reuse wireguard-lwip · adapt to NuttX

~2 MIN
4

Version 1: Application-Based Implementation

First working tunnel · debugging challenges

~4 MIN
5

Version 2: The Kernel Driver

Why a driver · integration challenges · validation

~5 MIN
6

Live Demo

Secure remote access · Stack-chan control

~3 MIN
7

Summary & Reflections

Achievements · personal reflections · community

~4 MIN
PART 732 / 36

Summary

1

Secure Communication

Brought WireGuard to Apache NuttX, enabling secure IP communication with standard WireGuard peers.

2

Application to Kernel Driver

Evolved the implementation from a NuttX application into a kernel network driver, tested on real boards and QEMU.

3

Toward Upstream Contribution

Preparing the driver and related fixes for review by the Apache NuttX community.

Prepared as small, separate changes. Nothing is submitted yet.
PART 7 · 1/433 / 36

What I learned

Lesson 1

From application user to OS contributor

For years I used NuttX from the application side.

This time I worked inside the OS: drivers and the kernel.

Lesson 2

AI helped me code, but understanding was my job

I used Claude a lot. Research and code went much faster.

OS internals were new to me. I did not take AI code as it was. I asked, read, and tested until I could explain it myself.

That was the hard part.

Lesson 3

A welcoming open-source community

Good docs and contributing guides. Active discussion and review.

Open to AI-assisted development, with people staying responsible.

CI, hackathons and events help new people join.

Hope

I hope to keep contributing to Apache NuttX and the open-source community, and I look forward to seeing NuttX continue to grow.

PART 7 · 2/434 / 36

Acknowledgements

Alin JerpeleaFor encouraging me to submit this talk to Community Over Code.
The Apache NuttX CommunityFor the discussions, documentation, and support throughout this project.
Sony's NuttX Developers, Past and PresentFor their contributions to NuttX and the foundation they built.
The Apache Software Foundation & Community Over Code OrganizersFor bringing the open-source community together, organizers and volunteers alike.
PART 7 · 3/435 / 36

Community Over Code · Glasgow 2026

Thank You

The slides and the code are here.

Satoru Akita · Sony Semiconductor Solutions

QR code for the slidesSCAN TO VIEW THE SLIDES

Testing: What Ping Misses

Same key on every boot?

SPRESENSE 3 resets, 3 different keys.

A quick check, not a proof of good randomness.

Keys left in memory after down?

sim session keys all zero after down.

The static key stays, on purpose, so up works again.

A leak that shows after hours?

sim 151 rekeys, 100 down/up: nothing lost.

Memory back to the start-up count. Not a week-long run.

Takeaway

Each risk needs its own test. A passing tunnel is not one of them.

APPENDIXA1 / A2

Design Choice: Trust the Clock?

Each handshake needs a newer timestamp than the peer has seen, even after a reboot.

Chosen

Real-time clock + the highest value used this boot. Same rule as Linux and wireguard-go, plus a warning when the clock was never set.

Not chosen

Save every timestamp: wears out flash.
Reserve a range in flash: needs a write guarantee I could not verify.
Wait: as long as it last ran.

Same board, nothing sent to it: clock unset → no handshake in 75 s. Clock set → 4.1 s.

Takeaway

Without a clock, a device may not reconnect by itself, and a ping test will not show it.

APPENDIXA2 / A2