Skip to content

arch/arm/src/stm32h7: Extend crypto interface to support HW CRC32#19449

Closed
pbarada wants to merge 10 commits into
apache:masterfrom
pbarada:test/stmh32h7-hash-crypt7
Closed

arch/arm/src/stm32h7: Extend crypto interface to support HW CRC32#19449
pbarada wants to merge 10 commits into
apache:masterfrom
pbarada:test/stmh32h7-hash-crypt7

Conversation

@pbarada

@pbarada pbarada commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Add stm32h7 support for CRC32 HW accelerator.

Extend stm32_crypto.c to add CRYPTO_CRC32 HW acceleration.

Impact

  • User experience: No adaptation required. This fix extends existing behavior.
  • Build: No impact.
  • Hardware: Affects nucleo-h753zi board (and other stm32h7 based boards)
  • Documentation: No impact.
  • Security: No impact.
  • Compatibility: Backward compatible - adds functionality.

Testing

Build Host:

  • OS: Ubuntu 24.04.4 LTS
  • Compiler: arm-none-eabi-gcc 13.2.1

Target:

  • Architecture: ARM (STM32H753ZI)
  • Board: Nucleo-h753zi
  • Configuration: nucleo-h753zi:crypto, then run "make menuconfig":
    • Under System Type / STM32 Configuration / STM32 Peripheral Support:
      • Enable CRC
    • Under Application Configuration / Testing / drivers:
      • Enable crc32 crypto test

Testing performed:

  • Booted board and ran crc32 test utility; verify test used HW acceleration

Runtime testing:

From target console:

nsh> uname -a
NuttX 13.0.0 05832a4e62-dirty Jul 15 2026 15:58:20 arm nucleo-h753zi
nsh> crc32
crc32 test case 1 success
crc32 test case 2 success
crc32 test case 3 success
crc32 test case 4 success
crc32 test case 5 success
crc32 test case 6 success
crc32 test case 7 success
crc32 test case 8 success
nsh>

@github-actions github-actions Bot added Arch: arm Issues related to ARM (32-bit) architecture Size: L The size of the change in this PR is large labels Jul 15, 2026
Add stm32h7 support for CRC32 HW accelerator.

Signed-off-by: Peter Barada <peter.barada@gmail.com>
@pbarada
pbarada force-pushed the test/stmh32h7-hash-crypt7 branch from 267a663 to a0b2c54 Compare July 15, 2026 20:37
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

hifive1-revb

anjiahao1 and others added 9 commits July 16, 2026 10:37
The ihm07m1_b16 (FOC motor control) configuration overflows the
STM32F302R8 64 KiB flash region by ~470 bytes, so it no longer links.
Enable GNU Full LTO (CONFIG_LTO_FULL=y); cross-module dead-code
elimination brings the image back under the limit (flash drops from
~66.0 KiB to ~57.7 KiB, 88%).

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
xcp.ustkptr is only assigned once in up_initial_state() when a task is
created and, since the syscall fast path was optimized in
e6973c7, is never updated afterwards. up_backtrace() used
"ustkptr != NULL" to decide whether a task is currently blocked
inside a syscall, and *(ustkptr + 1) as the frame pointer to resume
tracing from. Since ustkptr is now a dead value fixed at task
creation time, the check is always true and the "frame pointer" it
derives points at stale data near the initial stack top, unrelated
to where the task is actually blocked.

Use rtcb->flags & TCB_FLAG_SYSCALL together with xcp.sregs, which
dispatch_syscall() maintains precisely across the entire syscall
execution window (including any nested context switches caused by
blocking), to locate the frame pointer/return address saved at
syscall entry instead.

Signed-off-by: liang.huang <liang.huang@houmo.ai>
up_backtrace() on a different tcb dereferences that task's own stack
to walk its frame pointer chain, but never selected that task's
address environment first. Under CONFIG_ARCH_ADDRENV each task's
stack lives behind its own page tables mapped at the same fixed
virtual range, so reading tcb->stack_base_ptr without first switching
to that task's addrenv reads whatever physical page the caller's own
mapping of that virtual range happens to point to, not the target
task's real stack. A cross-tid dumpstack of a task running in a
different address environment therefore returns garbage or an
all-zero backtrace instead of failing cleanly or resolving the real
call chain.

Add an addrenv parameter to backtrace() and select the target tcb's
addrenv_own only around the two dereferences that read the target's
saved ra/fp (ra = *(fp - 1), next_fp = *(fp - 2)), then restore the
caller's own addrenv before writing the result into buffer. buffer
belongs to the caller, not the target tcb, so it must always be
written back in the caller's own address environment; writing it
while the target's addrenv is still selected would corrupt the
access instead of fixing it.

Signed-off-by: liang.huang <liang.huang@houmo.ai>
sys_callN() wraps a bare ecall and calls no other function, so the
compiler treats it as a leaf function: with frame pointers enabled,
it only needs to spill the caller's s0, which it places in what
up_backtrace()'s fp-chain walk assumes is ra's stack slot, while the
real ra slot is never written. sched_backtrace() then misreads that
slot as the return address for this frame, either resolving to a
bogus symbol or, if the adjacent garbage happens to look
out-of-range, terminating the backtrace early.

Add "ra" to the ecall clobber list so the compiler spills/reloads ra
around the ecall like a normal call site, keeping ra and the saved
s0 in their expected slots. Gate this on
CONFIG_FRAME_POINTER && CONFIG_SCHED_BACKTRACE, the only combination
where up_backtrace()'s fp-chain walk is both valid (FRAME_POINTER)
and actually exercised (SCHED_BACKTRACE); other configurations keep
the original "memory"-only clobber and pay no extra cost.

This only fixes the syscall boundary. Leaf functions that do not
cross a syscall (e.g. up_idle()) can still lose their ra slot the
same way and are not addressed here.

Signed-off-by: liang.huang <liang.huang@houmo.ai>
The existing CRYPTO_AES_CTR is the RFC 3686 profile: the last 4 bytes of
the key are a nonce, the IV is 8 bytes and only the low 32 bits of the
counter block are incremented. SSH aes128/192/256-ctr (RFC 4344) instead
uses the key as-is (no embedded nonce) and treats the whole 16-byte IV as
the initial counter block, incremented as a 128-bit big-endian integer,
with the first keystream block being E(IV).

Add CRYPTO_AES_CTR_SSH as a new enc_xform mirroring the CRYPTO_CHACHA20_DJB
addition. It reuses struct aes_ctr_ctx and the AES block; only setkey (full
key, no nonce), reinit (full 16-byte counter) and crypt (encrypt-then-
increment over all 16 bytes) differ from the RFC 3686 variant.

Keystream validated against `openssl enc -aes-128-ctr`, including a counter
that carries across byte boundaries and a non-block-aligned tail.

Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
usbdev_register() calls CLASS_BIND, which ends with DEV_CONNECT
(composite_bind/cdcacm_bind) and sets SIE_CTRL.PULLUP_EN, and then
performs a wholesale putreg32 of SIE_CTRL to set EP0_INT_1BUF --
clobbering the pull-up microseconds after it was asserted.

Enumeration only ever succeeded because the host happened to latch the
microsecond pull-up blip and issued a bus reset, whose handler
(CLASS_DISCONNECT -> DEV_CONNECT) re-arms the pull-up.  A warm host
port catches the blip; a cold-plugged port is still in attach debounce,
misses it, and never resets -- PULLUP_EN stays 0 forever and the device
is totally silent on the bus while NuttX runs normally underneath.
This presented as an intermittent, image-dependent "cold boot brick"
(boot timing shifts the blip in or out of the host's blind window).

Fix: set EP0_INT_1BUF with setbits_reg32 so PULLUP_EN survives.

Validated on RP2350 silicon (Raspberry Pi Pico 2 W): an image that
failed 0/10 cold plugs enumerated 10/10 with the fix; a second board
that had never enumerated at all was recovered by it.  The rp2040
driver has the identical code and receives the identical fix
(build-tested; the RP2350 validation exercised the shared logic).

Fixes apache#19434

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
Three defects that together prevented macOS from ever mounting a
composite USBMSC function (Linux was mostly unaffected because its
probe sequence and recovery timing never exercised these paths):

1. usbmsc_setup() compared the class-request wIndex against the
   compile-time constant USBMSC_INTERFACEID (= CONFIG_USBMSC_IFNOBASE,
   i.e. 0) instead of the composite-assigned priv->devinfo.ifnobase.
   In composite mode the MSC interface number is nonzero, so
   GET MAX LUN, Bulk-Only Mass Storage Reset, and GET/SET INTERFACE
   all failed the index check and stalled EP0.  Standalone MSC is
   unaffected (ifnobase == 0), which is why this went unnoticed.

2. usbmsc_deferredresponse() has its entire body inside
   #ifndef CONFIG_USBMSC_COMPOSITE, so the deferred EP0 status stage
   for MSRESET/SETINTERFACE was never sent in composite mode and the
   host's Bulk-Only reset timed out.  (Unreachable before fix 1 --
   MSRESET used to stall at the wrong-interface check.)  Compile the
   body in composite mode too, but suppress the worker's deferred
   response for SETCONFIGURATION there: the composite driver answers
   that request itself, and a duplicate zero-length packet corrupts
   the EP0 state.

3. usbmsc_cmdfinishstate() stalled the bulk IN endpoint whenever a
   device-to-host command left a residue, even when the response had
   already been sent and terminated by a short packet (or ZLP).  The
   stall is BOT-legal (USB MSC BOT 6.7.2) but gratuitous: the short
   packet already ended the data phase and the residue is reported in
   dCSWDataResidue.  Hosts such as macOS answer any bulk-IN halt during
   device probing with a full Bulk-Only reset sequence, which costs
   seconds per command or aborts the probe entirely (macOS probes
   MODE SENSE(6) with allocation lengths that exceed the response;
   Linux's probe does not).  Only halt the endpoint when nothing
   terminated the data phase.

Root-cause analysis and host traces in apache#19435.

Validated on RP2350 silicon (Raspberry Pi Pico 2 W, composite
CDC-ACM + CDC-NCM + USBMSC): GET MAX LUN answers 1 LUN (previously
EP0 stall and a garbage LUN count on macOS), MSRESET completes 10/10
(previously ETIMEDOUT), MODE SENSE(6) alloc=0xC0 returns short data
plus a CSW with dCSWDataResidue and zero bulk-IN stalls across the
exact-length suite, and macOS now mounts the volume (together with the
companion DCD fixes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
Summary

Permissions (Part 3)

Description:

In kernel builds, any unprivileged process running on the NuttX device can
open /dev/efuse and attempt to read/write fuse content. Reading the fuses
may provide valuable information to an attacker controlling the user process.
The write operation, in extreme cases where the fuse blocks are not locked,
may brick the device.

DISCLAIMER: I tried to be strict with the settings, better to relax them
later if it's needed.

This is part of apache#19410

Impact

See apache#19410

Testing

Compiles ok.

Signed-off-by: Catalin Visinescu <catalin_visinescu@yahoo.com>
New RISC-V chip port for the GigaDevice GD32VW55x (Nuclei N307, Wi-Fi 6
and BLE 5.3 combo), with the GD32VW553K-START board.

Core:
- ECLIC interrupt controller, clock tree (160 MHz / 40 MHz HXTAL),
  64-bit machine timer, serial (USART0/UART1/UART2) and RTC.
- The instruction cache must be enabled in head.S or the UART drops
  characters under load; the mask ROM uses the first 0x200 bytes of SRAM
  so the image is linked at 0x20000200; the RTC needs PMU_CTL0.BKPWEN or
  the register writes are silently discarded.
- The ECLIC only auto-clears the interrupt pending bit in hardware-vectored
  mode, so the trap dispatch clears it for edge-triggered sources or they
  re-fire forever (level-triggered peripherals clear their own).

Peripherals: DMA (8 channels), GPIO + EXTI, SPI (optional DMA), I2C0/I2C1
(the new STM32-v2-style IP, not the GD32F4 one), ADC, PWM and input
capture on the timers, both watchdogs, PROGMEM, TRNG and CRC.  All use
the standard NuttX lower-half interfaces and direct register access, not
the vendor SPL.  Three user LEDs (GPIOC), and a software reset through the
Nuclei SysTimer.

Internal flash: it is a system-in-package NOR die behind the real-time
decryption block, so it is not programmed through the FMC registers -- the
driver goes through the mask ROM API (rom_flash_*), the same way the
vendor code does.  PROGMEM can be mounted as LittleFS; the region sits
below the Wi-Fi NVDS and must not overlap it.

Wi-Fi (wlan0), station and softAP:
- The MAC/PHY, RF and WPA supplicant are linked as prebuilt BSD-3
  libraries.  They are RTOS-agnostic, so the OS binding is a sys_* facade
  on NuttX primitives (gdwifi/wrapper_nuttx.c).  Critical sections mask by
  ECLIC priority threshold, not by disabling every interrupt, or the MAC
  misses its microsecond deadlines.
- The lwIP stack of the SDK is not used: the interface is a
  netdev_lowerhalf driver driven by the standard tools (wapi, ifup, renew,
  ping, dhcpd).  EAPOL is handed to the supplicant instead of the IP
  stack.  The lowerhalf "priority" field is the work-queue id (HPWORK/
  LPWORK), not a task priority -- a wrong value makes receive() never run
  and every packet is dropped.
- The vendor gives the radio 32 KB of shared SRAM as an extra heap; this
  needs CONFIG_MM_REGIONS >= 2 or the kernel silently drops the region.
- The DHCP client needs CONFIG_NETUTILS_DHCPC_BOOTP_FLAGS=0x8000 so the
  server answers the OFFER by broadcast.
- softAP (wapi master mode -> wifi_management_ap_start): the single-VIF
  firmware does station or AP at a time.  Use WPA2, not WPA3: the SAE
  handshake is deep on the stack and overflows the elliptic-curve crypto
  with the default task stacks, so the Wi-Fi configs raise
  CONFIG_INIT_STACKSIZE/DEFAULT_TASK_STACKSIZE.

Vendor SDK: cloned by the build at "context" time, pinned to a validated
commit and patched in place -- so CI can build with nothing preinstalled,
the same pattern as esp-hal-3rdparty.  The prebuilt libraries are built
for the hard-float ilp32f ABI.

BLE 5.3, marked EXPERIMENTAL and off by default: the prebuilt libble is an
all-in-one controller plus RivieraWaves host (GAP/GATT/SMP inside the blob)
with no HCI transport, so the port drives the vendor host directly
(ble_adp_*, ble_adv_*, ble_gap_*) instead of registering a bt_driver_s.
The SDK's radio interrupt handlers must be attached to the NuttX IRQ table
(they are reached through the ECLIC hardware vector table in the vendor
build); attaching also keeps --gc-sections from dropping them.  It ships
with no configuration; enabling it advertises as "NuttX", connectable.

Boards: gd32vw553k-start with nsh, wapi, sta_softap, periph and littlefs
configurations, and the board added to the CI build list.

Tested on hardware (GD32VW553K-START): NSH, the peripheral drivers
(TRNG entropy and the LEDs exercised), LittleFS (write, read, survives a
reboot), the full Wi-Fi station path (scan, WPA2, DHCP, ping to the
internet), the softAP (a client associates with WPA2, gets an address
from the board's DHCP server, and pings the board), and BLE (advertises as
"NuttX"; a central connects and enumerates the GATT database).

Assisted-by: Claude Opus 4.8
Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
@pbarada
pbarada requested a review from lupyuen as a code owner July 16, 2026 14:38
@github-actions github-actions Bot added Area: Build system Arch: risc-v Issues related to the RISC-V (32-bit or 64-bit) architecture Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces. Board: arm Board: risc-v and removed Size: L The size of the change in this PR is large labels Jul 16, 2026
@pbarada

pbarada commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Closing - mis-merged master into my branch(caused rebase instead of merge); will recreate branch from updated master and resubmit PR.

@pbarada pbarada closed this Jul 16, 2026
@pbarada

pbarada commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Closing - mismerged master. Will recreate branch/PR from latest master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Arch: risc-v Issues related to the RISC-V (32-bit or 64-bit) architecture Area: Build system Board: arm Board: risc-v 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.

7 participants