This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new fee2ddbf5 netutils/dropbear: add Dropbear SSH server port for NuttX
fee2ddbf5 is described below

commit fee2ddbf540ddd3639a30a2ed488b34fa10bf862
Author: Felipe Moura <[email protected]>
AuthorDate: Tue Jun 23 19:40:49 2026 -0300

    netutils/dropbear: add Dropbear SSH server port for NuttX
    
    Integrated SSH daemon authenticating against FSUTILS_PASSWD, with an
    ECDSA P-256 host key and an NSH session over a PTY per connection. Built
    from the upstream Dropbear tarball (pinned commit) and patched for
    NuttX, using Dropbear's bundled libtomcrypt for all crypto. setsid()
    (apache/nuttx#19184) and link() now come from NuttX, not local stubs.
    
    Signed-off-by: Felipe Moura <[email protected]>
---
 fsutils/passwd/passwd_append.c                     |   2 +-
 netutils/dropbear/.gitignore                       |   6 +
 netutils/dropbear/CMakeLists.txt                   | 185 ++++++
 netutils/dropbear/Kconfig                          | 120 ++++
 netutils/dropbear/Make.defs                        |  25 +
 netutils/dropbear/Makefile                         | 157 +++++
 netutils/dropbear/dropbear_main.c                  | 329 +++++++++++
 netutils/dropbear/dropbear_nshsession.c            | 633 +++++++++++++++++++++
 .../patch/0001-guard-platform-declarations.patch   |  26 +
 .../patch/0002-use-nuttx-passwd-auth.patch         |  87 +++
 ...-localoptions-to-override-tracking-malloc.patch |  24 +
 .../patch/0004-use-nuttx-unused-macro.patch        | 202 +++++++
 netutils/dropbear/port/config.h                    |  20 +
 netutils/dropbear/port/dropbear_utils.c            | 149 +++++
 netutils/dropbear/port/dropbear_utils.h            |  31 +
 netutils/dropbear/port/localoptions.h              |  81 +++
 netutils/dropbear/port/nuttx_auth.c                | 109 ++++
 netutils/dropbear/port/nuttx_config.h              | 142 +++++
 nshlib/CMakeLists.txt                              |   4 +
 nshlib/Kconfig                                     |  22 +
 nshlib/Makefile                                    |   4 +
 nshlib/nsh.h                                       |   4 +
 .../passwd_append.c => nshlib/nsh_dropbear.c       |  79 +--
 nshlib/nsh_init.c                                  |  12 +
 24 files changed, 2399 insertions(+), 54 deletions(-)

diff --git a/fsutils/passwd/passwd_append.c b/fsutils/passwd/passwd_append.c
index be77c9aed..125a4cfe6 100644
--- a/fsutils/passwd/passwd_append.c
+++ b/fsutils/passwd/passwd_append.c
@@ -69,7 +69,7 @@ int passwd_append(FAR const char *username, FAR const char 
*password)
     {
       int errcode = errno;
       DEBUGASSERT(errcode > 0);
-      return errcode;
+      return -errcode;
     }
 
   /* The format of the password file is:
diff --git a/netutils/dropbear/.gitignore b/netutils/dropbear/.gitignore
new file mode 100644
index 000000000..1dc4834a1
--- /dev/null
+++ b/netutils/dropbear/.gitignore
@@ -0,0 +1,6 @@
+/dropbear
+/*.zip
+*.o
+.built
+.depend
+Make.dep
diff --git a/netutils/dropbear/CMakeLists.txt b/netutils/dropbear/CMakeLists.txt
new file mode 100644
index 000000000..c3187a32d
--- /dev/null
+++ b/netutils/dropbear/CMakeLists.txt
@@ -0,0 +1,185 @@
+# 
##############################################################################
+# apps/netutils/dropbear/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# 
##############################################################################
+
+if(CONFIG_NETUTILS_DROPBEAR)
+
+  set(DROPBEAR_COMMIT "${CONFIG_NETUTILS_DROPBEAR_COMMIT}")
+  string(REPLACE "\"" "" DROPBEAR_COMMIT "${DROPBEAR_COMMIT}")
+
+  set(DROPBEAR_ZIP "${DROPBEAR_COMMIT}.zip")
+  set(DROPBEAR_URL "https://github.com/mkj/dropbear/archive";)
+  set(DROPBEAR_UNPACKNAME "dropbear")
+
+  if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}")
+    if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_ZIP}")
+      message(STATUS "Downloading Dropbear: ${DROPBEAR_URL}/${DROPBEAR_ZIP}")
+      file(DOWNLOAD "${DROPBEAR_URL}/${DROPBEAR_ZIP}"
+           "${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_ZIP}")
+    endif()
+    message(STATUS "Unpacking Dropbear: ${DROPBEAR_ZIP}")
+    execute_process(
+      COMMAND unzip -q -o "${DROPBEAR_ZIP}"
+      WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+      RESULT_VARIABLE result)
+    if(result EQUAL 0)
+      file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/dropbear-${DROPBEAR_COMMIT}"
+           "${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}")
+      execute_process(
+        COMMAND
+          patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
+          
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0001-guard-platform-declarations.patch"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+      execute_process(
+        COMMAND
+          patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
+          "${CMAKE_CURRENT_SOURCE_DIR}/patch/0002-use-nuttx-passwd-auth.patch"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+      execute_process(
+        COMMAND
+          patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
+          
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0003-allow-localoptions-to-override-tracking-malloc.patch"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+      execute_process(
+        COMMAND
+          patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
+          "${CMAKE_CURRENT_SOURCE_DIR}/patch/0004-use-nuttx-unused-macro.patch"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+      message(STATUS "Generating default_options_guard.h")
+      execute_process(
+        COMMAND
+          sh
+          
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}/src/ifndef_wrapper.sh"
+        INPUT_FILE
+          
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}/src/default_options.h"
+        OUTPUT_FILE
+          
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}/src/default_options_guard.h"
+        WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
+    endif()
+  endif()
+
+  set(PROGNAME "${CONFIG_NETUTILS_DROPBEAR_PROGNAME}")
+  string(REPLACE "\"" "" PROGNAME "${PROGNAME}")
+
+  set(DROPBEAR_SRCS
+      dropbear_nshsession.c
+      port/nuttx_auth.c
+      port/dropbear_utils.c
+      dropbear/src/dbutil.c
+      dropbear/src/buffer.c
+      dropbear/src/dbhelpers.c
+      dropbear/src/bignum.c
+      dropbear/src/signkey.c
+      dropbear/src/dbrandom.c
+      dropbear/src/queue.c
+      dropbear/src/atomicio.c
+      dropbear/src/compat.c
+      dropbear/src/fake-rfc2553.c
+      dropbear/src/curve25519.c
+      dropbear/src/chachapoly.c
+      dropbear/src/ltc_prng.c
+      dropbear/src/ecc.c
+      dropbear/src/ecdsa.c
+      dropbear/src/crypto_desc.c
+      dropbear/src/dbmalloc.c
+      dropbear/src/gensignkey.c
+      dropbear/src/common-session.c
+      dropbear/src/packet.c
+      dropbear/src/common-algo.c
+      dropbear/src/common-kex.c
+      dropbear/src/common-channel.c
+      dropbear/src/common-chansession.c
+      dropbear/src/termcodes.c
+      dropbear/src/tcp-accept.c
+      dropbear/src/listener.c
+      dropbear/src/process-packet.c
+      dropbear/src/common-runopts.c
+      dropbear/src/circbuffer.c
+      dropbear/src/list.c
+      dropbear/src/netio.c
+      dropbear/src/gcm.c
+      dropbear/src/kex-x25519.c
+      dropbear/src/svr-kex.c
+      dropbear/src/svr-auth.c
+      dropbear/src/svr-authpasswd.c
+      dropbear/src/svr-session.c
+      dropbear/src/svr-service.c
+      dropbear/src/svr-runopts.c
+      dropbear/src/svr-tcpfwd.c
+      dropbear/src/svr-forward.c
+      dropbear/src/svr-streamfwd.c
+      dropbear/src/svr-authpam.c)
+
+  file(GLOB LIBTOMMATH_SRCS CONFIGURE_DEPENDS
+       "${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtommath/*.c")
+  list(APPEND DROPBEAR_SRCS ${LIBTOMMATH_SRCS})
+
+  file(GLOB_RECURSE LIBTOMCRYPT_SRCS CONFIGURE_DEPENDS
+       "${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtomcrypt/src/*.c")
+  list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/prngs/sober128tab\\.c$")
+  list(APPEND DROPBEAR_SRCS ${LIBTOMCRYPT_SRCS})
+
+  nuttx_add_application(
+    NAME
+    ${PROGNAME}
+    SRCS
+    ${DROPBEAR_SRCS}
+    dropbear_main.c
+    STACKSIZE
+    ${CONFIG_NETUTILS_DROPBEAR_STACKSIZE}
+    PRIORITY
+    ${CONFIG_NETUTILS_DROPBEAR_PRIORITY}
+    DEPENDS
+    ${DROPBEAR_UNPACKNAME})
+
+  target_include_directories(
+    ${PROGNAME}
+    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+            ${CMAKE_CURRENT_SOURCE_DIR}/port
+            ${CMAKE_CURRENT_SOURCE_DIR}/dropbear
+            ${CMAKE_CURRENT_SOURCE_DIR}/dropbear/src
+            ${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtomcrypt/src/headers
+            ${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtommath
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../nshlib)
+
+  if(CONFIG_NETUTILS_DROPBEAR_COMPRESSION)
+    target_include_directories(
+      ${PROGNAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../system/zlib/zlib)
+  endif()
+
+  target_compile_definitions(
+    ${PROGNAME} PRIVATE LOCALOPTIONS_H_EXISTS=1 DROPBEAR_NUTTX=1
+                        DROPBEAR_NUTTX_PASSWD=1)
+
+  set_source_files_properties(
+    dropbear_nshsession.c
+    PROPERTIES COMPILE_DEFINITIONS
+               "Channel=dropbear_channel;ChanType=dropbear_chantype")
+
+  # LTC_SOURCE must be set only for libtomcrypt sources.
+  set_source_files_properties(${LIBTOMCRYPT_SRCS} PROPERTIES 
COMPILE_DEFINITIONS
+                                                             LTC_SOURCE=1)
+
+  target_compile_options(${PROGNAME} PRIVATE -Wno-pointer-sign -Wno-format)
+
+  target_sources(apps PRIVATE ${DROPBEAR_SRCS})
+
+endif()
diff --git a/netutils/dropbear/Kconfig b/netutils/dropbear/Kconfig
new file mode 100644
index 000000000..507c85068
--- /dev/null
+++ b/netutils/dropbear/Kconfig
@@ -0,0 +1,120 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menuconfig NETUTILS_DROPBEAR
+       tristate "Dropbear SSH server"
+       default n
+       depends on NET && NET_TCP
+       depends on !DISABLE_PSEUDOFS_OPERATIONS
+       depends on !DISABLE_PTHREAD
+       depends on SCHED_WAITPID
+       depends on NSH_LIBRARY
+       depends on FSUTILS_PASSWD
+       depends on PSEUDOTERM
+       depends on SERIAL
+       depends on ARCH_HAVE_RNG
+       depends on DEV_RANDOM
+       depends on DEV_URANDOM
+       depends on LIBC_NETDB
+       depends on LIBC_GAISTRERROR
+       select CRYPTO
+       select CRYPTO_RANDOM_POOL
+       ---help---
+               Enable a minimal Dropbear SSH server port for NuttX.  This 
initial
+               port is based on the ESP-IDF MCU test port and provides a single
+               foreground SSH server process with SSH sessions backed by NSH.
+
+if NETUTILS_DROPBEAR
+
+config NETUTILS_DROPBEAR_STACKSIZE
+       int "Dropbear main stack size"
+       default 65536
+       ---help---
+               Stack size for the Dropbear server built-in.
+               This is architecture-specific, so adjust it according to your 
setup.
+
+config NETUTILS_DROPBEAR_PRIORITY
+       int "Dropbear main priority"
+       default 100
+
+config NETUTILS_DROPBEAR_SHELL_PRIORITY
+       int "Dropbear NSH session priority"
+       default 100
+
+config NETUTILS_DROPBEAR_PROGNAME
+       string "Dropbear program name"
+       default "dropbear"
+       ---help---
+               This is the name of the program that will be used when the NSH 
ELF
+               program is installed.
+
+config NETUTILS_DROPBEAR_LISTEN_RETRIES
+       int "Dropbear listen retries"
+       default 0
+       ---help---
+               Number of times to retry listen setup when no listen socket 
could
+               be opened.  Zero means to retry forever.
+
+config NETUTILS_DROPBEAR_LISTEN_RETRY_MAX
+       int "Dropbear maximum listen retry interval"
+       default 120
+       range 1 3600
+       ---help---
+               Maximum number of seconds to wait between listen setup retries.
+               The retry delay starts at one second and doubles until it 
reaches
+               this value.
+
+config NETUTILS_DROPBEAR_SHELL_STACKSIZE
+       int "Dropbear NSH session task stack size"
+       default 8192
+
+config NETUTILS_DROPBEAR_PORT
+       int "Dropbear listen port"
+       default 2222
+
+config NETUTILS_DROPBEAR_HOSTKEY_PATH
+       string "Dropbear ECDSA P-256 host key path"
+       default "/etc/dropbear/dropbear_ecdsa_host_key"
+       ---help---
+               Path to the persistent ECDSA P-256 host key used by the Dropbear
+               server.  The file is stored in Dropbear's native host key 
format.
+
+config NETUTILS_DROPBEAR_GENERATE_HOSTKEY
+       bool "Generate host key if missing"
+       default y
+       ---help---
+               Pass -R so Dropbear generates an ECDSA P-256 host key on demand 
and
+               persists it at NETUTILS_DROPBEAR_HOSTKEY_PATH when it does not 
exist.
+               Product builds can disable this and provision the host key
+               externally (loaded with -r).
+
+config NETUTILS_DROPBEAR_COMPRESSION
+       bool "Enable SSH compression (zlib)"
+       default n
+       depends on LIB_ZLIB
+       ---help---
+               Enable zlib compression for SSH sessions.  Requires the zlib
+               library (LIB_ZLIB).  When disabled, Dropbear is built with
+               DISABLE_ZLIB and negotiates no compression.
+
+               WARNING: each session allocates a zlib deflate state of about
+               256 KiB (DROPBEAR_ZLIB_WINDOW_BITS=15, 
DROPBEAR_ZLIB_MEM_LEVEL=8),
+               and the state is allocated even for the delayed [email protected]
+               method, right after key exchange.
+
+config NETUTILS_DROPBEAR_SYSLOG
+       bool "Log via syslog"
+       default n
+       ---help---
+               Route Dropbear log messages through syslog().  When disabled,
+               Dropbear is built with DISABLE_SYSLOG.
+
+config NETUTILS_DROPBEAR_COMMIT
+       string "Dropbear upstream commit"
+       default "54ef47adf8c99b422be6a8f694f2866e62f88b9e"
+       ---help---
+               Upstream Dropbear (mkj/dropbear) commit to download and build.
+
+endif
diff --git a/netutils/dropbear/Make.defs b/netutils/dropbear/Make.defs
new file mode 100644
index 000000000..9fcb635f7
--- /dev/null
+++ b/netutils/dropbear/Make.defs
@@ -0,0 +1,25 @@
+############################################################################
+# apps/netutils/dropbear/Make.defs
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_NETUTILS_DROPBEAR),)
+CONFIGURED_APPS += $(APPDIR)/netutils/dropbear
+endif
diff --git a/netutils/dropbear/Makefile b/netutils/dropbear/Makefile
new file mode 100644
index 000000000..039b0d0b3
--- /dev/null
+++ b/netutils/dropbear/Makefile
@@ -0,0 +1,157 @@
+############################################################################
+# apps/netutils/dropbear/Makefile
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+ifneq ($(CONFIG_NETUTILS_DROPBEAR),)
+
+DROPBEAR_COMMIT = $(patsubst "%",%,$(strip $(CONFIG_NETUTILS_DROPBEAR_COMMIT)))
+DROPBEAR_ZIP = $(DROPBEAR_COMMIT).zip
+DROPBEAR_UNPACKNAME = dropbear
+DROPBEAR_URL = https://github.com/mkj/dropbear/archive
+UNPACK ?= unzip -q -o
+ifeq ($(CONFIG_HOST_MACOS),y)
+PATCH ?= gpatch
+else
+PATCH ?= patch
+endif
+
+MODULE = $(CONFIG_NETUTILS_DROPBEAR)
+PROGNAME = $(CONFIG_NETUTILS_DROPBEAR_PROGNAME)
+PRIORITY = $(CONFIG_NETUTILS_DROPBEAR_PRIORITY)
+STACKSIZE = $(CONFIG_NETUTILS_DROPBEAR_STACKSIZE)
+
+CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear"
+CFLAGS += 
${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)port"
+CFLAGS += 
${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear"
+CFLAGS += 
${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear$(DELIM)src"
+CFLAGS += 
${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear$(DELIM)libtomcrypt$(DELIM)src$(DELIM)headers"
+CFLAGS += 
${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear$(DELIM)libtommath"
+CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)nshlib"
+
+ifneq ($(CONFIG_NETUTILS_DROPBEAR_COMPRESSION),)
+CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)system$(DELIM)zlib$(DELIM)zlib"
+endif
+
+CFLAGS += ${DEFINE_PREFIX}LOCALOPTIONS_H_EXISTS=1
+CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX=1
+CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX_PASSWD=1
+CFLAGS += -Wno-pointer-sign -Wno-format
+
+dropbear_nshsession.c_CFLAGS += ${DEFINE_PREFIX}Channel=dropbear_channel
+dropbear_nshsession.c_CFLAGS += ${DEFINE_PREFIX}ChanType=dropbear_chantype
+
+CSRCS = dropbear_nshsession.c
+CSRCS += port/nuttx_auth.c
+CSRCS += port/dropbear_utils.c
+
+CSRCS += \
+       dropbear/src/dbutil.c \
+       dropbear/src/buffer.c \
+       dropbear/src/dbhelpers.c \
+       dropbear/src/bignum.c \
+       dropbear/src/signkey.c \
+       dropbear/src/dbrandom.c \
+       dropbear/src/queue.c \
+       dropbear/src/atomicio.c \
+       dropbear/src/compat.c \
+       dropbear/src/fake-rfc2553.c \
+       dropbear/src/curve25519.c \
+       dropbear/src/chachapoly.c \
+       dropbear/src/ltc_prng.c \
+       dropbear/src/ecc.c \
+       dropbear/src/ecdsa.c \
+       dropbear/src/crypto_desc.c \
+       dropbear/src/dbmalloc.c \
+       dropbear/src/gensignkey.c \
+       dropbear/src/common-session.c \
+       dropbear/src/packet.c \
+       dropbear/src/common-algo.c \
+       dropbear/src/common-kex.c \
+       dropbear/src/common-channel.c \
+       dropbear/src/common-chansession.c \
+       dropbear/src/termcodes.c \
+       dropbear/src/tcp-accept.c \
+       dropbear/src/listener.c \
+       dropbear/src/process-packet.c \
+       dropbear/src/common-runopts.c \
+       dropbear/src/circbuffer.c \
+       dropbear/src/list.c \
+       dropbear/src/netio.c \
+       dropbear/src/gcm.c \
+       dropbear/src/kex-x25519.c \
+       dropbear/src/svr-kex.c \
+       dropbear/src/svr-auth.c \
+       dropbear/src/svr-authpasswd.c \
+       dropbear/src/svr-session.c \
+       dropbear/src/svr-service.c \
+       dropbear/src/svr-runopts.c \
+       dropbear/src/svr-tcpfwd.c \
+       dropbear/src/svr-forward.c \
+       dropbear/src/svr-streamfwd.c \
+       dropbear/src/svr-authpam.c
+
+TOMMATH_SRCS = $(shell if [ -d "$(DROPBEAR_UNPACKNAME)/libtommath" ]; then 
find "$(DROPBEAR_UNPACKNAME)/libtommath" -name "*.c"; fi)
+TOMCRYPT_SRCS = $(shell if [ -d "$(DROPBEAR_UNPACKNAME)/libtomcrypt/src" ]; 
then find "$(DROPBEAR_UNPACKNAME)/libtomcrypt/src" -name "*.c" ! -name 
"sober128tab.c"; fi)
+
+CSRCS += $(TOMMATH_SRCS)
+CSRCS += $(TOMCRYPT_SRCS)
+
+# Match the ESP-IDF port behavior: LTC_SOURCE is only for libtomcrypt sources.
+$(foreach src,$(TOMCRYPT_SRCS),$(eval $(src)_CFLAGS += 
${DEFINE_PREFIX}LTC_SOURCE=1))
+
+MAINSRC = dropbear_main.c
+
+$(DROPBEAR_ZIP):
+       @echo "Downloading: $(DROPBEAR_ZIP)"
+       $(Q) curl -L -o $(DROPBEAR_ZIP) $(DROPBEAR_URL)/$(DROPBEAR_ZIP)
+
+$(DROPBEAR_UNPACKNAME): $(DROPBEAR_ZIP)
+       @echo "Unpacking: $(DROPBEAR_ZIP) -> $(DROPBEAR_UNPACKNAME)"
+       $(Q) $(UNPACK) $(DROPBEAR_ZIP)
+       $(Q) rm -rf $(DROPBEAR_UNPACKNAME)
+       $(Q) mv dropbear-$(DROPBEAR_COMMIT) $(DROPBEAR_UNPACKNAME)
+       @echo "Patching $(DROPBEAR_UNPACKNAME)"
+       $(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i 
$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0001-guard-platform-declarations.patch;
 true
+       $(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i 
$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0002-use-nuttx-passwd-auth.patch;
 true
+       $(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i 
$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0003-allow-localoptions-to-override-tracking-malloc.patch;
 true
+       $(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i 
$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0004-use-nuttx-unused-macro.patch;
 true
+       @echo "Generating default_options_guard.h"
+       $(Q) sh $(DROPBEAR_UNPACKNAME)$(DELIM)src$(DELIM)ifndef_wrapper.sh \
+               < $(DROPBEAR_UNPACKNAME)$(DELIM)src$(DELIM)default_options.h \
+               > 
$(DROPBEAR_UNPACKNAME)$(DELIM)src$(DELIM)default_options_guard.h
+       $(Q) touch $(DROPBEAR_UNPACKNAME)
+
+ifeq ($(wildcard $(DROPBEAR_UNPACKNAME)/.git),)
+context:: $(DROPBEAR_UNPACKNAME)
+
+clean::
+       $(call DELFILE, port$(DELIM)*.o)
+
+distclean::
+       $(call DELDIR, $(DROPBEAR_UNPACKNAME))
+       $(call DELFILE, $(DROPBEAR_ZIP))
+endif
+
+endif
+
+include $(APPDIR)/Application.mk
diff --git a/netutils/dropbear/dropbear_main.c 
b/netutils/dropbear/dropbear_main.c
new file mode 100644
index 000000000..798ba2b55
--- /dev/null
+++ b/netutils/dropbear/dropbear_main.c
@@ -0,0 +1,329 @@
+/****************************************************************************
+ * apps/netutils/dropbear/dropbear_main.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/socket.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "includes.h"
+#include "algo.h"
+#include "crypto_desc.h"
+#define dropbear_main dropbear_multi_entry
+#include "dbutil.h"
+#undef dropbear_main
+#include "dbrandom.h"
+#include "netio.h"
+#include "runopts.h"
+#include "session.h"
+#include "signkey.h"
+#include "gensignkey.h"
+#include "ssh.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DROPBEAR_PORT_STRING_HELPER(n) #n
+#define DROPBEAR_PORT_STRING(n) DROPBEAR_PORT_STRING_HELPER(n)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef void (*dropbear_exit_handler_t)(int exitcode, FAR const char *format,
+                                        va_list param) ATTRIB_NORETURN;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static jmp_buf g_session_exit_jmp;
+static int g_session_exitcode;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void dropbear_session_exit(int exitcode, FAR const char *format,
+                                  va_list param) noreturn_function;
+static void dropbear_session_exit(int exitcode, FAR const char *format,
+                                  va_list param)
+{
+  char exitmsg[150];
+  char fullmsg[300];
+  char fromaddr[60];
+  int signal_pipe[2];
+
+  vsnprintf(exitmsg, sizeof(exitmsg), format, param);
+
+  fromaddr[0] = '\0';
+
+  if (svr_ses.addrstring != NULL)
+    {
+      snprintf(fromaddr, sizeof(fromaddr), " from <%s>", svr_ses.addrstring);
+    }
+
+  if (!ses.init_done)
+    {
+      snprintf(fullmsg, sizeof(fullmsg), "Early exit%s: %s", fromaddr,
+               exitmsg);
+    }
+  else if (ses.authstate.authdone)
+    {
+      snprintf(fullmsg, sizeof(fullmsg), "Exit (%s)%s: %s",
+               ses.authstate.pw_name, fromaddr, exitmsg);
+    }
+  else if (ses.authstate.pw_name != NULL)
+    {
+      snprintf(fullmsg, sizeof(fullmsg),
+               "Exit before auth%s: (user '%s', %u fails): %s",
+               fromaddr, ses.authstate.pw_name, ses.authstate.failcount,
+               exitmsg);
+    }
+  else
+    {
+      snprintf(fullmsg, sizeof(fullmsg), "Exit before auth%s: %s", fromaddr,
+               exitmsg);
+    }
+
+  dropbear_log(LOG_INFO, "%s", fullmsg);
+
+  signal_pipe[0] = ses.signal_pipe[0];
+  signal_pipe[1] = ses.signal_pipe[1];
+  session_cleanup();
+
+  if (signal_pipe[0] > STDERR_FILENO)
+    {
+      m_close(signal_pipe[0]);
+    }
+
+  if (signal_pipe[1] > STDERR_FILENO && signal_pipe[1] != signal_pipe[0])
+    {
+      m_close(signal_pipe[1]);
+    }
+
+  memset(&ses, 0, sizeof(ses));
+  memset(&svr_ses, 0, sizeof(svr_ses));
+
+  g_session_exitcode = exitcode;
+  longjmp(g_session_exit_jmp, 1);
+
+  while (1)
+    {
+    }
+}
+
+static void dropbear_setup(FAR const char *port)
+{
+  /* Load the host key with -r so it lives in the persistent (epoch 0)
+   * allocation rather than being created lazily inside a per-session malloc
+   * epoch (-R), which would free it when the first session ends and leave a
+   * dangling svr_opts.hostkey for the next connection.
+   */
+
+  FAR char *argv[] =
+  {
+    "dropbear",
+    "-F",
+    "-p",
+    (FAR char *)port,
+    "-r",
+    CONFIG_NETUTILS_DROPBEAR_HOSTKEY_PATH,
+    NULL
+  };
+
+  _dropbear_exit = svr_dropbear_exit;
+  _dropbear_log = svr_dropbear_log;
+
+  disallow_core();
+  svr_getopts(6, argv);
+  seedrandom();
+  crypto_init();
+
+#ifdef CONFIG_NETUTILS_DROPBEAR_GENERATE_HOSTKEY
+  /* Generate the ECDSA host key now if it is missing.  signkey_generate()
+   * with skip_exist=1 silently succeeds when the file already exists.
+   */
+
+  if (signkey_generate(DROPBEAR_SIGNKEY_ECDSA_NISTP256, 0,
+                       CONFIG_NETUTILS_DROPBEAR_HOSTKEY_PATH, 1)
+      == DROPBEAR_FAILURE)
+    {
+      dropbear_exit("failed to generate host key");
+    }
+#endif
+
+  load_all_hostkeys();
+
+  if (dropbear_auth_initialize() < 0)
+    {
+      dropbear_exit("failed to initialize password auth");
+    }
+}
+
+static void dropbear_run_session(int childsock)
+{
+  dropbear_exit_handler_t saved_exit;
+
+  saved_exit = _dropbear_exit;
+  _dropbear_exit = dropbear_session_exit;
+
+  m_malloc_set_epoch(1);
+
+  if (setjmp(g_session_exit_jmp) == 0)
+    {
+      svr_session(childsock, -1);
+    }
+
+  m_malloc_free_epoch(1, 1);
+  m_malloc_set_epoch(0);
+
+  _dropbear_exit = saved_exit;
+
+  if (g_session_exitcode != EXIT_SUCCESS)
+    {
+      dropbear_log(LOG_WARNING, "session exited with status %d",
+                   g_session_exitcode);
+    }
+}
+
+static size_t dropbear_listen_sockets(FAR int *socks, size_t sockcount,
+                                      FAR int *maxfd)
+{
+  FAR char *errstring = NULL;
+  size_t sockpos = 0;
+  unsigned int i;
+
+  for (i = 0; i < svr_opts.portcount; i++)
+    {
+      int nsock;
+      unsigned int n;
+
+      nsock = dropbear_listen(svr_opts.addresses[i], svr_opts.ports[i],
+                              &socks[sockpos], sockcount - sockpos,
+                              &errstring, maxfd, svr_opts.interface);
+
+      if (nsock < 0)
+        {
+          dropbear_log(LOG_WARNING, "failed listening on '%s': %s",
+                       svr_opts.ports[i],
+                       errstring != NULL ? errstring : "unknown error");
+          m_free(errstring);
+          errstring = NULL;
+          continue;
+        }
+
+      for (n = 0; n < (unsigned int)nsock; n++)
+        {
+          set_sock_priority(socks[sockpos + n], DROPBEAR_PRIO_LOWDELAY);
+        }
+
+      sockpos += (size_t)nsock;
+    }
+
+  return sockpos;
+}
+
+static size_t dropbear_wait_listen_sockets(FAR int *socks, size_t sockcount,
+                                           FAR int *maxfd)
+{
+  int retries = 0;
+  int retry_delay = 1;
+
+  while (1)
+    {
+      size_t count;
+
+      *maxfd = -1;
+      count = dropbear_listen_sockets(socks, sockcount, maxfd);
+
+      if (count > 0)
+        {
+          return count;
+        }
+
+#if CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRIES > 0
+      if (retries++ >= CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRIES)
+        {
+          dropbear_exit("no listening ports available");
+        }
+#else
+      retries++;
+#endif
+
+      dropbear_log(LOG_WARNING, "Retry %d in %d seconds...", retries,
+                   retry_delay);
+      sleep(retry_delay);
+
+      retry_delay *= 2;
+
+      if (retry_delay > CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRY_MAX)
+        {
+          retry_delay = CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRY_MAX;
+        }
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  FAR const char *port = DROPBEAR_PORT_STRING(CONFIG_NETUTILS_DROPBEAR_PORT);
+  int listensocks[MAX_LISTEN_ADDR];
+  int maxfd = -1;
+
+  if (argc > 1)
+    {
+      port = argv[1];
+    }
+
+  dropbear_setup(port);
+
+  dropbear_wait_listen_sockets(listensocks, MAX_LISTEN_ADDR, &maxfd);
+
+  printf("dropbear: listening on port %s\n", port);
+
+  while (1)
+    {
+      struct sockaddr_storage remoteaddr;
+      socklen_t remoteaddrlen = sizeof(remoteaddr);
+      FAR char *remote_host = NULL;
+      FAR char *remote_port = NULL;
+      int childsock;
+
+      childsock = accept(listensocks[0], (FAR struct sockaddr *)&remoteaddr,
+                         &remoteaddrlen);
+
+      if (childsock < 0)
+        {
+          continue;
+        }
+
+      getaddrstring(&remoteaddr, &remote_host, &remote_port, 0);
+      dropbear_log(LOG_INFO, "connection from %s:%s",
+                   remote_host != NULL ? remote_host : "?",
+                   remote_port != NULL ? remote_port : "?");
+      m_free(remote_host);
+      m_free(remote_port);
+
+      seedrandom();
+      dropbear_run_session(childsock);
+      close(childsock);
+    }
+
+  return EXIT_SUCCESS;
+}
diff --git a/netutils/dropbear/dropbear_nshsession.c 
b/netutils/dropbear/dropbear_nshsession.c
new file mode 100644
index 000000000..3b2e6cdbd
--- /dev/null
+++ b/netutils/dropbear/dropbear_nshsession.c
@@ -0,0 +1,633 @@
+/****************************************************************************
+ * apps/netutils/dropbear/dropbear_nshsession.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "includes.h"
+#include "channel.h"
+#include "chansession.h"
+#include "dbutil.h"
+#include "session.h"
+
+#include "nsh.h"
+#include "nsh_console.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <pty.h>
+#include <pthread.h>
+#include <sched.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <unistd.h>
+
+struct dropbear_nshsession_s
+{
+  int pty_readfd;
+  int pty_writefd;
+  pid_t nsh_pid;
+  volatile bool done;
+  pthread_t waiter;
+  bool waiter_started;
+  bool have_winsize;
+  struct winsize win;
+};
+
+struct dropbear_signal_name_s
+{
+  FAR const char *name;
+  int signo;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct dropbear_signal_name_s g_dropbear_signals[] =
+{
+  { "ABRT", SIGABRT },
+  { "ALRM", SIGALRM },
+  { "FPE",  SIGFPE },
+  { "HUP",  SIGHUP },
+  { "ILL",  SIGILL },
+  { "INT",  SIGINT },
+  { "KILL", SIGKILL },
+  { "PIPE", SIGPIPE },
+  { "QUIT", SIGQUIT },
+  { "SEGV", SIGSEGV },
+  { "TERM", SIGTERM },
+  { "USR1", SIGUSR1 },
+  { "USR2", SIGUSR2 },
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int dropbear_nsh_main(int argc, FAR char *argv[])
+{
+  FAR struct console_stdio_s *pstate;
+  FAR char *nsh_argv[] =
+  {
+    "nsh",
+    NULL
+  };
+
+  int ret;
+
+  (void)argc;
+  (void)argv;
+
+  pstate = nsh_newconsole(true);
+  if (pstate == NULL)
+    {
+      dropbear_log(LOG_WARNING, "failed to create NSH console");
+      return -ENOMEM;
+    }
+
+  ret = nsh_session(pstate, NSH_LOGIN_NONE, 1, nsh_argv);
+  dropbear_log(LOG_INFO, "NSH session exited: %d", ret);
+
+  nsh_exit(&pstate->cn_vtbl, ret);
+  return ret;
+}
+
+static FAR void *dropbear_nsh_waiter(FAR void *arg)
+{
+  FAR struct dropbear_nshsession_s *sess = arg;
+  unsigned char ch = 0;
+  int status;
+  int ret;
+
+  ret = waitpid(sess->nsh_pid, &status, 0);
+  if (ret < 0)
+    {
+      dropbear_log(LOG_WARNING, "NSH session wait failed: %s",
+                   strerror(errno));
+    }
+
+  sess->nsh_pid = -1;
+  sess->done = true;
+
+  /* Match Dropbear's SIGCHLD wakeup path.  The session loop checks channel
+   * close conditions when this pipe becomes readable.
+   */
+
+  if (ses.signal_pipe[1] >= 0)
+    {
+      write(ses.signal_pipe[1], &ch, sizeof(ch));
+    }
+
+  return NULL;
+}
+
+static int dropbear_newchansess(FAR struct dropbear_channel *channel)
+{
+  FAR struct dropbear_nshsession_s *sess;
+
+  sess = m_malloc(sizeof(*sess));
+  memset(sess, 0, sizeof(*sess));
+  sess->pty_readfd = -1;
+  sess->pty_writefd = -1;
+  sess->nsh_pid = -1;
+
+  channel->typedata = sess;
+  channel->prio = DROPBEAR_PRIO_LOWDELAY;
+  return 0;
+}
+
+static int dropbear_sesscheckclose(FAR struct dropbear_channel *channel)
+{
+  FAR struct dropbear_nshsession_s *sess = channel->typedata;
+
+  return sess != NULL && sess->done;
+}
+
+static int dropbear_setup_spawn_attrs(FAR posix_spawnattr_t *attr,
+                                      FAR const char **errmsg)
+{
+  struct sched_param param;
+  int rc;
+
+  param.sched_priority = CONFIG_NETUTILS_DROPBEAR_SHELL_PRIORITY;
+  *errmsg = "spawn priority setup";
+  rc = posix_spawnattr_setschedparam(attr, &param);
+  if (rc != 0)
+    {
+      return rc;
+    }
+
+  *errmsg = "spawn stack setup";
+  rc = posix_spawnattr_setstacksize(
+         attr, CONFIG_NETUTILS_DROPBEAR_SHELL_STACKSIZE);
+  if (rc != 0)
+    {
+      return rc;
+    }
+
+  *errmsg = "spawn flags setup";
+  return posix_spawnattr_setflags(attr, POSIX_SPAWN_SETSCHEDPARAM);
+}
+
+static int
+dropbear_setup_spawn_stdio(FAR posix_spawn_file_actions_t *actions,
+                           int slavefd)
+{
+  static const int stdio_fds[] =
+  {
+    STDIN_FILENO,
+    STDOUT_FILENO,
+    STDERR_FILENO
+  };
+
+  int i;
+  int rc;
+
+  for (i = 0; i < nitems(stdio_fds); i++)
+    {
+      rc = posix_spawn_file_actions_adddup2(actions, slavefd, stdio_fds[i]);
+      if (rc != 0)
+        {
+          return rc;
+        }
+    }
+
+  return 0;
+}
+
+static int
+dropbear_setup_spawn_close(FAR posix_spawn_file_actions_t *actions,
+                           int fd)
+{
+  if (fd <= STDERR_FILENO)
+    {
+      return 0;
+    }
+
+  return posix_spawn_file_actions_addclose(actions, fd);
+}
+
+static int dropbear_start_nsh(FAR struct dropbear_channel *channel,
+                              FAR struct dropbear_nshsession_s *sess)
+{
+  posix_spawn_file_actions_t actions;
+  posix_spawnattr_t attr;
+  FAR const char *errmsg;
+  FAR char * const argv[] =
+  {
+    "nsh",
+    NULL
+  };
+
+  int masterfd;
+  int slavefd;
+  int writefd;
+  int rc;
+
+  if (sess->nsh_pid >= 0)
+    {
+      dropbear_log(LOG_WARNING, "NSH session already running");
+      return DROPBEAR_FAILURE;
+    }
+
+  rc = openpty(&masterfd, &slavefd, NULL, NULL,
+               sess->have_winsize ? &sess->win : NULL);
+  if (rc < 0)
+    {
+      dropbear_log(LOG_WARNING, "openpty failed: %s", strerror(errno));
+      return DROPBEAR_FAILURE;
+    }
+
+  writefd = dup(masterfd);
+  if (writefd < 0)
+    {
+      dropbear_log(LOG_WARNING, "pty dup failed: %s", strerror(errno));
+      close(masterfd);
+      close(slavefd);
+      return DROPBEAR_FAILURE;
+    }
+
+  rc = posix_spawn_file_actions_init(&actions);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "spawn actions init failed: %s",
+                   strerror(rc));
+      close(masterfd);
+      close(writefd);
+      close(slavefd);
+      return DROPBEAR_FAILURE;
+    }
+
+  rc = posix_spawnattr_init(&attr);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "spawn attr init failed: %s", strerror(rc));
+      goto err_with_actions;
+    }
+
+  rc = dropbear_setup_spawn_attrs(&attr, &errmsg);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "%s failed: %s", errmsg, strerror(rc));
+      goto err_with_attr;
+    }
+
+  rc = dropbear_setup_spawn_stdio(&actions, slavefd);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "spawn stdio setup failed: %s",
+                   strerror(rc));
+      goto err_with_attr;
+    }
+
+  rc = dropbear_setup_spawn_close(&actions, masterfd);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "spawn master close setup failed: %s",
+                   strerror(rc));
+      goto err_with_attr;
+    }
+
+  rc = dropbear_setup_spawn_close(&actions, writefd);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "spawn write close setup failed: %s",
+                   strerror(rc));
+      goto err_with_attr;
+    }
+
+  rc = dropbear_setup_spawn_close(&actions, slavefd);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "spawn slave close setup failed: %s",
+                   strerror(rc));
+      goto err_with_attr;
+    }
+
+  sess->nsh_pid = task_spawn("dropbear nsh", dropbear_nsh_main, &actions,
+                             &attr, argv, NULL);
+  if (sess->nsh_pid < 0)
+    {
+      dropbear_log(LOG_WARNING, "failed to create NSH task: %s",
+                   strerror(-sess->nsh_pid));
+      goto err_with_attr;
+    }
+
+  close(slavefd);
+  slavefd = -1;
+
+  rc = pthread_create(&sess->waiter, NULL, dropbear_nsh_waiter, sess);
+  if (rc != 0)
+    {
+      dropbear_log(LOG_WARNING, "failed to create NSH waiter: %s",
+                   strerror(rc));
+      close(masterfd);
+      close(writefd);
+      masterfd = -1;
+      writefd = -1;
+      kill(sess->nsh_pid, SIGTERM);
+      waitpid(sess->nsh_pid, NULL, 0);
+      sess->nsh_pid = -1;
+      goto err_with_attr;
+    }
+
+  sess->waiter_started = true;
+  sess->pty_readfd = masterfd;
+  sess->pty_writefd = writefd;
+
+  channel->readfd = masterfd;
+  channel->writefd = writefd;
+  channel->bidir_fd = 0;
+
+  setnonblocking(channel->readfd);
+  setnonblocking(channel->writefd);
+  ses.maxfd = MAX(ses.maxfd, channel->readfd);
+  ses.maxfd = MAX(ses.maxfd, channel->writefd);
+
+  posix_spawnattr_destroy(&attr);
+  posix_spawn_file_actions_destroy(&actions);
+
+  dropbear_log(LOG_INFO, "NSH PTY session started");
+  return DROPBEAR_SUCCESS;
+
+err_with_attr:
+  posix_spawnattr_destroy(&attr);
+
+err_with_actions:
+  posix_spawn_file_actions_destroy(&actions);
+
+  if (masterfd >= 0)
+    {
+      close(masterfd);
+    }
+
+  if (writefd >= 0)
+    {
+      close(writefd);
+    }
+
+  if (slavefd >= 0)
+    {
+      close(slavefd);
+    }
+
+  sess->nsh_pid = -1;
+  return DROPBEAR_FAILURE;
+}
+
+static void dropbear_parse_winsize(FAR struct dropbear_nshsession_s *sess)
+{
+  unsigned int cols = buf_getint(ses.payload);
+  unsigned int rows = buf_getint(ses.payload);
+  unsigned int width = buf_getint(ses.payload);
+  unsigned int height = buf_getint(ses.payload);
+
+  sess->win.ws_col = cols;
+  sess->win.ws_row = rows;
+  sess->win.ws_xpixel = width;
+  sess->win.ws_ypixel = height;
+  sess->have_winsize = true;
+
+  if (sess->pty_readfd >= 0)
+    {
+      ioctl(sess->pty_readfd, TIOCSWINSZ, (unsigned long)&sess->win);
+    }
+}
+
+static int dropbear_handle_pty_req(FAR struct dropbear_nshsession_s *sess)
+{
+  unsigned int len;
+  FAR char *term;
+  FAR char *modes;
+
+  term = buf_getstring(ses.payload, &len);
+  dropbear_parse_winsize(sess);
+  modes = buf_getstring(ses.payload, &len);
+
+  m_free(term);
+  m_free(modes);
+  return DROPBEAR_SUCCESS;
+}
+
+static int dropbear_signal_from_name(FAR const char *name)
+{
+  int i;
+
+  for (i = 0; i < nitems(g_dropbear_signals); i++)
+    {
+      if (strcmp(name, g_dropbear_signals[i].name) == 0)
+        {
+          return g_dropbear_signals[i].signo;
+        }
+    }
+
+  return -EINVAL;
+}
+
+static int dropbear_write_terminal_signal(
+                            FAR struct dropbear_nshsession_s *sess,
+                            int signo)
+{
+#ifdef CONFIG_TTY_SIGINT
+  unsigned char ch;
+  ssize_t nwritten;
+
+  if (signo == SIGINT && sess->pty_writefd >= 0)
+    {
+      ch = CONFIG_TTY_SIGINT_CHAR;
+      nwritten = write(sess->pty_writefd, &ch, sizeof(ch));
+      if (nwritten == sizeof(ch))
+        {
+          return DROPBEAR_SUCCESS;
+        }
+
+      dropbear_log(LOG_WARNING, "SSH terminal INT failed: %s",
+                   strerror(errno));
+      return DROPBEAR_FAILURE;
+    }
+#endif
+
+  return DROPBEAR_FAILURE;
+}
+
+static int dropbear_handle_signal(FAR struct dropbear_nshsession_s *sess)
+{
+  unsigned int len;
+  FAR char *name;
+  int signo;
+  int ret;
+
+  name = buf_getstring(ses.payload, &len);
+  signo = dropbear_signal_from_name(name);
+  if (signo < 0)
+    {
+      dropbear_log(LOG_WARNING, "unsupported SSH signal '%s'", name);
+      m_free(name);
+      return DROPBEAR_FAILURE;
+    }
+
+  ret = dropbear_write_terminal_signal(sess, signo);
+  if (ret == DROPBEAR_SUCCESS)
+    {
+      dropbear_log(LOG_INFO, "SSH signal '%s' sent to PTY", name);
+      m_free(name);
+      return DROPBEAR_SUCCESS;
+    }
+
+  if (sess->nsh_pid <= 0)
+    {
+      dropbear_log(LOG_WARNING, "SSH signal '%s' has no NSH session", name);
+      m_free(name);
+      return DROPBEAR_FAILURE;
+    }
+
+  ret = kill(sess->nsh_pid, signo);
+  if (ret < 0)
+    {
+      dropbear_log(LOG_WARNING, "SSH signal '%s' failed: %s",
+                   name, strerror(errno));
+      m_free(name);
+      return DROPBEAR_FAILURE;
+    }
+
+  dropbear_log(LOG_INFO, "SSH signal '%s' sent to NSH session", name);
+  m_free(name);
+  return DROPBEAR_SUCCESS;
+}
+
+static void dropbear_chansessionrequest(FAR struct dropbear_channel *channel)
+{
+  unsigned int typelen;
+  FAR char *type = buf_getstring(ses.payload, &typelen);
+  unsigned char wantreply = buf_getbool(ses.payload);
+  FAR struct dropbear_nshsession_s *sess = channel->typedata;
+  int ret = DROPBEAR_FAILURE;
+
+  TRACE(("dropbear_chansessionrequest: type='%s'", type))
+
+  if (strcmp(type, "pty-req") == 0)
+    {
+      ret = dropbear_handle_pty_req(sess);
+    }
+  else if (strcmp(type, "shell") == 0)
+    {
+      ret = dropbear_start_nsh(channel, sess);
+    }
+  else if (strcmp(type, "exec") == 0)
+    {
+      dropbear_log(LOG_WARNING, "SSH exec requests are not supported");
+    }
+  else if (strcmp(type, "window-change") == 0)
+    {
+      dropbear_parse_winsize(sess);
+      ret = DROPBEAR_SUCCESS;
+    }
+  else if (strcmp(type, "signal") == 0)
+    {
+      ret = dropbear_handle_signal(sess);
+    }
+  else if (strcmp(type, "break") == 0)
+    {
+      ret = DROPBEAR_SUCCESS;
+    }
+  else
+    {
+      TRACE(("dropbear_chansessionrequest: unhandled type '%s'", type))
+    }
+
+  if (wantreply)
+    {
+      if (ret == DROPBEAR_SUCCESS)
+        {
+          send_msg_channel_success(channel);
+        }
+      else
+        {
+          send_msg_channel_failure(channel);
+        }
+    }
+
+  m_free(type);
+}
+
+static void
+dropbear_closechansess(FAR const struct dropbear_channel *channel)
+{
+  FAR struct dropbear_nshsession_s *sess = channel->typedata;
+
+  if (sess != NULL)
+    {
+      sess->done = true;
+    }
+}
+
+static void
+dropbear_cleanupchansess(FAR const struct dropbear_channel *channel)
+{
+  FAR struct dropbear_nshsession_s *sess = channel->typedata;
+
+  if (sess == NULL)
+    {
+      return;
+    }
+
+  sess->done = true;
+
+  if (sess->nsh_pid > 0)
+    {
+      kill(sess->nsh_pid, SIGTERM);
+    }
+
+  if (sess->waiter_started)
+    {
+      pthread_join(sess->waiter, NULL);
+      sess->waiter_started = false;
+    }
+
+  m_free(sess);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/* Chansession lifecycle hooks invoked from svr-session.c.  Upstream
+ * svr-chansession.c uses these to set up and reap the global childpids[] /
+ * SIGCHLD machinery; the NSH bridge tracks each session's child through its
+ * own waiter thread (dropbear_nsh_waiter), so both are no-ops here.
+ */
+
+void svr_chansessinitialise(void)
+{
+}
+
+void svr_chansess_checksignal(void)
+{
+}
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+const struct dropbear_chantype svrchansess =
+{
+  "session",
+  dropbear_newchansess,
+  dropbear_sesscheckclose,
+  dropbear_chansessionrequest,
+  dropbear_closechansess,
+  dropbear_cleanupchansess,
+};
diff --git a/netutils/dropbear/patch/0001-guard-platform-declarations.patch 
b/netutils/dropbear/patch/0001-guard-platform-declarations.patch
new file mode 100644
index 000000000..7eb1dfcd2
--- /dev/null
+++ b/netutils/dropbear/patch/0001-guard-platform-declarations.patch
@@ -0,0 +1,26 @@
+--- a/src/dbutil.c
++++ b/src/dbutil.c
+@@ -66,6 +66,10 @@
+ #include "session.h"
+ #include "atomicio.h"
+
++#ifdef DROPBEAR_NUTTX
++int execv(const char *path, char * const argv[]);
++#endif
++
+ #define MAX_FMT 100
+
+ static void generic_dropbear_exit(int exitcode, const char* format,
+--- a/src/signkey.h
++++ b/src/signkey.h
+@@ -150,9 +150,9 @@
+ void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, 
const buffer *data_buf);
+ #if DROPBEAR_SIGNKEY_VERIFY
+ int buf_verify(buffer * buf, sign_key *key, enum signature_type 
expect_sigtype, const buffer *data_buf);
+ int sk_buf_verify(buffer * buf, sign_key *key, enum signature_type 
expect_sigtype, const buffer *data_buf, char* app, unsigned int applen);
+-char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int 
keybloblen);
+ #endif
++char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int 
keybloblen);
+ int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
+                                       const unsigned char* algoname, unsigned 
int algolen,
+                                       const buffer * line, char ** 
fingerprint);
diff --git a/netutils/dropbear/patch/0002-use-nuttx-passwd-auth.patch 
b/netutils/dropbear/patch/0002-use-nuttx-passwd-auth.patch
new file mode 100644
index 000000000..5e71d73da
--- /dev/null
+++ b/netutils/dropbear/patch/0002-use-nuttx-passwd-auth.patch
@@ -0,0 +1,87 @@
+--- a/src/svr-authpasswd.c
++++ b/src/svr-authpasswd.c
+@@ -33,6 +33,77 @@
+ 
+ #if DROPBEAR_SVR_PASSWORD_AUTH
+ 
++#if DROPBEAR_NUTTX_PASSWD
++
++/* Process a password auth request, sending success or failure messages as
++ * appropriate */
++void svr_auth_password(int valid_user) {
++
++      char * password = NULL;
++      unsigned int passwordlen;
++      unsigned int changepw;
++      int auth_ok = 0;
++
++      /* check if client wants to change password */
++      changepw = buf_getbool(ses.payload);
++      if (changepw) {
++              /* not implemented by this server */
++              send_msg_userauth_failure(0, 1);
++              return;
++      }
++
++      password = buf_getstring(ses.payload, &passwordlen);
++      if (valid_user && passwordlen <= DROPBEAR_MAX_PASSWORD_LEN &&
++                      strlen(password) == passwordlen) {
++              auth_ok = dropbear_verify_password(ses.authstate.pw_name, 
password);
++      }
++      m_burn(password, passwordlen);
++      m_free(password);
++
++      /* After we have got the payload contents we can exit if the username
++      is invalid. Invalid users have already been logged. */
++      if (!valid_user) {
++              send_msg_userauth_failure(0, 1);
++              return;
++      }
++
++      if (passwordlen > DROPBEAR_MAX_PASSWORD_LEN) {
++              dropbear_log(LOG_WARNING,
++                              "Too-long password attempt for '%s' from %s",
++                              ses.authstate.pw_name,
++                              svr_ses.addrstring);
++              send_msg_userauth_failure(0, 1);
++              return;
++      }
++
++      if (auth_ok == DROPBEAR_SUCCESS) {
++              if (svr_opts.multiauthmethod && (ses.authstate.authtypes & 
~AUTH_TYPE_PASSWORD)) {
++                      /* successful password authentication, but extra auth 
required */
++                      dropbear_log(LOG_NOTICE,
++                                      "Password auth succeeded for '%s' from 
%s, extra auth required",
++                                      ses.authstate.pw_name,
++                                      svr_ses.addrstring);
++                      ses.authstate.authtypes &= ~AUTH_TYPE_PASSWORD; /* 
password auth ok, delete the method flag */
++                      send_msg_userauth_failure(1, 0);  /* Send partial 
success */
++              } else {
++                      /* successful authentication */
++                      dropbear_log(LOG_NOTICE,
++                                      "Password auth succeeded for '%s' from 
%s",
++                                      ses.authstate.pw_name,
++                                      svr_ses.addrstring);
++                      send_msg_userauth_success();
++              }
++      } else {
++              dropbear_log(LOG_WARNING,
++                              "Bad password attempt for '%s' from %s",
++                              ses.authstate.pw_name,
++                              svr_ses.addrstring);
++              send_msg_userauth_failure(0, 1);
++      }
++}
++
++#else
++
+ /* not constant time when strings are differing lengths. 
+  string content isn't leaked, and crypt hashes are predictable length. */
+ static int constant_time_strcmp(const char* a, const char* b) {
+@@ -131,4 +202,6 @@
+       }
+ }
+ 
++#endif /* DROPBEAR_NUTTX_PASSWD */
++
+ #endif
diff --git 
a/netutils/dropbear/patch/0003-allow-localoptions-to-override-tracking-malloc.patch
 
b/netutils/dropbear/patch/0003-allow-localoptions-to-override-tracking-malloc.patch
new file mode 100644
index 000000000..b1dc3e52c
--- /dev/null
+++ 
b/netutils/dropbear/patch/0003-allow-localoptions-to-override-tracking-malloc.patch
@@ -0,0 +1,24 @@
+--- a/src/sysoptions.h
++++ b/src/sysoptions.h
+@@ -183,7 +183,9 @@ defined(__has_feature)
+ #define LTC_ECC521
+ #endif
+
+-#define DROPBEAR_LTC_PRNG (DROPBEAR_ECC)
++#ifndef DROPBEAR_LTC_PRNG
++#define DROPBEAR_LTC_PRNG (DROPBEAR_ECC)
++#endif
+
+ /* RSA can be vulnerable to timing attacks which use the time required for
+  * signing to guess the private key. Blinding avoids this attack, though makes
+@@ -436,7 +438,9 @@ defined(__has_feature)
+ #define DROPBEAR_CLIENT_TCP_FAST_OPEN 0
+ #endif
+
+-#define DROPBEAR_TRACKING_MALLOC (DROPBEAR_FUZZ)
++#ifndef DROPBEAR_TRACKING_MALLOC
++#define DROPBEAR_TRACKING_MALLOC (DROPBEAR_FUZZ)
++#endif
+
+ /* Used to work around Memory Sanitizer false positives */
+ #if defined(__has_feature)
diff --git a/netutils/dropbear/patch/0004-use-nuttx-unused-macro.patch 
b/netutils/dropbear/patch/0004-use-nuttx-unused-macro.patch
new file mode 100644
index 000000000..2ea588057
--- /dev/null
+++ b/netutils/dropbear/patch/0004-use-nuttx-unused-macro.patch
@@ -0,0 +1,202 @@
+--- a/src/compat.c
++++ b/src/compat.c
+@@ -89,6 +89,6 @@
+ #ifndef HAVE_GETUSERSHELL
+ static char **curshell, **shells, *strings;
+-static char **initshells();
++static char **initshells(void);
+ #endif
+
+ #ifndef HAVE_STRLCPY
+@@ -234,7 +234,7 @@
+       curshell = initshells();
+ }
+
+-static char **initshells() {
++static char **initshells(void) {
+       static const char *okshells[] = { COMPAT_USER_SHELLS, NULL };
+       register char **sp, *cp;
+       register FILE *fp;
+--- a/src/common-algo.c
++++ b/src/common-algo.c
+@@ -39,16 +39,25 @@
+ /* This file (algo.c) organises the ciphers which can be used, and is used to
+  * decide which ciphers/hashes/compression/signing to use during key 
exchange*/
+
+-static int void_cipher(const unsigned char* in, unsigned char* out,
+-              unsigned long len, void* UNUSED(cipher_state)) {
++static int void_cipher(const unsigned char* in, unsigned char* out,
++              unsigned long len, void* cipher_state) {
++      UNUSED(cipher_state);
++
+       if (in != out) {
+               memmove(out, in, len);
+       }
+       return CRYPT_OK;
+ }
+
+-static int void_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
+-                      const unsigned char* UNUSED(key),
+-                      int UNUSED(keylen), int UNUSED(num_rounds), void* 
UNUSED(cipher_state)) {
++static int void_start(int cipher, const unsigned char* IV,
++                      const unsigned char* key,
++                      int keylen, int num_rounds, void* cipher_state) {
++      UNUSED(cipher);
++      UNUSED(IV);
++      UNUSED(key);
++      UNUSED(keylen);
++      UNUSED(num_rounds);
++      UNUSED(cipher_state);
++
+       return CRYPT_OK;
+ }
+
+--- a/src/common-channel.c
++++ b/src/common-channel.c
+@@ -410,7 +410,9 @@
+
+ #ifndef HAVE_WRITEV
+ static int writechannel_fallback(struct Channel* channel, int fd, circbuffer 
*cbuf,
+-      const unsigned char *UNUSED(moredata), unsigned int *morelen) {
++      const unsigned char *moredata, unsigned int *morelen) {
++      UNUSED(moredata);
++
+
+       unsigned char *circ_p1, *circ_p2;
+       unsigned int circ_len1, circ_len2;
+--- a/src/dbutil.c
++++ b/src/dbutil.c
+@@ -138,7 +138,9 @@
+ }
+
+-static void generic_dropbear_log(int UNUSED(priority), const char* format,
++static void generic_dropbear_log(int priority, const char* format,
+               va_list param) {
++      UNUSED(priority);
++
+
+       char printbuf[1024];
+
+--- a/src/netio.c
++++ b/src/netio.c
+@@ -47,7 +47,10 @@
+       }
+ }
+
+-static void cancel_callback(int result, int sock, void* UNUSED(data), const 
char* UNUSED(errstring)) {
++static void cancel_callback(int result, int sock, void* data, const char* 
errstring) {
++      UNUSED(data);
++      UNUSED(errstring);
++
+       if (result == DROPBEAR_SUCCESS)
+       {
+               m_close(sock);
+--- a/src/ltc_prng.c
++++ b/src/ltc_prng.c
+@@ -32,8 +32,10 @@
+   @param prng     [out] The PRNG state to initialize
+   @return CRYPT_OK if successful
+ */  
+-int dropbear_prng_start(prng_state* UNUSED(prng))
++int dropbear_prng_start(prng_state* prng)
+ {
++   UNUSED(prng);
++
+    return CRYPT_OK;  
+ }
+ 
+@@ -44,8 +46,12 @@
+   @param prng     PRNG state to update
+   @return CRYPT_OK if successful
+ */  
+-int dropbear_prng_add_entropy(const unsigned char* UNUSED(in), unsigned long 
UNUSED(inlen), prng_state* UNUSED(prng))
++int dropbear_prng_add_entropy(const unsigned char* in, unsigned long inlen, 
prng_state* prng)
+ {
++   UNUSED(in);
++   UNUSED(inlen);
++   UNUSED(prng);
++
+    return CRYPT_OK;
+ }
+ 
+@@ -54,8 +60,10 @@
+   @param prng   The PRNG to make active
+   @return CRYPT_OK if successful
+ */  
+-int dropbear_prng_ready(prng_state* UNUSED(prng))
++int dropbear_prng_ready(prng_state* prng)
+ {
++   UNUSED(prng);
++
+    return CRYPT_OK;
+ }
+ 
+@@ -66,8 +74,10 @@
+   @param prng     The active PRNG to read from
+   @return Number of octets read
+ */  
+-unsigned long dropbear_prng_read(unsigned char* out, unsigned long outlen, 
prng_state* UNUSED(prng))
++unsigned long dropbear_prng_read(unsigned char* out, unsigned long outlen, 
prng_state* prng)
+ {
++   UNUSED(prng);
++
+    LTC_ARGCHK(out != NULL);
+    genrandom(out, outlen);
+    return outlen;
+@@ -78,8 +88,10 @@
+   @param prng   The PRNG to terminate
+   @return CRYPT_OK if successful
+ */  
+-int dropbear_prng_done(prng_state* UNUSED(prng))
++int dropbear_prng_done(prng_state* prng)
+ {
++   UNUSED(prng);
++
+    return CRYPT_OK;
+ }
+ 
+@@ -90,8 +102,11 @@
+   @param prng      The PRNG to export
+   @return CRYPT_OK if successful
+ */  
+-int dropbear_prng_export(unsigned char* UNUSED(out), unsigned long* outlen, 
prng_state* UNUSED(prng))
++int dropbear_prng_export(unsigned char* out, unsigned long* outlen, 
prng_state* prng)
+ {
++   UNUSED(out);
++   UNUSED(prng);
++
+    LTC_ARGCHK(outlen != NULL);
+ 
+    *outlen = 0;
+@@ -105,8 +120,12 @@
+   @param prng     The PRNG to import
+   @return CRYPT_OK if successful
+ */  
+-int dropbear_prng_import(const unsigned char* UNUSED(in), unsigned long 
UNUSED(inlen), prng_state* UNUSED(prng))
++int dropbear_prng_import(const unsigned char* in, unsigned long inlen, 
prng_state* prng)
+ {
++   UNUSED(in);
++   UNUSED(inlen);
++   UNUSED(prng);
++
+    return CRYPT_OK;
+ }
+ 
+--- a/src/chachapoly.c
++++ b/src/chachapoly.c
+@@ -43,9 +43,13 @@
+ const struct dropbear_cipher dropbear_chachapoly =
+       {&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE};
+ 
+-static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* 
UNUSED(IV),
++static int dropbear_chachapoly_start(int cipher, const unsigned char* IV,
+                       const unsigned char *key, int keylen,
+-                      int UNUSED(num_rounds), dropbear_chachapoly_state 
*state) {
++                      int num_rounds, dropbear_chachapoly_state *state) {
++      UNUSED(cipher);
++      UNUSED(IV);
++      UNUSED(num_rounds);
++
+       int err;
+ 
+       TRACE2(("enter dropbear_chachapoly_start"))
diff --git a/netutils/dropbear/port/config.h b/netutils/dropbear/port/config.h
new file mode 100644
index 000000000..0f5355fd7
--- /dev/null
+++ b/netutils/dropbear/port/config.h
@@ -0,0 +1,20 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/config.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+#ifndef __APPS_NETUTILS_DROPBEAR_PORT_CONFIG_H
+#define __APPS_NETUTILS_DROPBEAR_PORT_CONFIG_H
+
+/* Dropbear looks for a file named config.h. Keep this wrapper name stable;
+ * NuttX-specific autoconf replacements live in nuttx_config.h.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "nuttx_config.h"
+
+#endif /* __APPS_NETUTILS_DROPBEAR_PORT_CONFIG_H */
diff --git a/netutils/dropbear/port/dropbear_utils.c 
b/netutils/dropbear/port/dropbear_utils.c
new file mode 100644
index 000000000..73619cbe7
--- /dev/null
+++ b/netutils/dropbear/port/dropbear_utils.c
@@ -0,0 +1,149 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/dropbear_utils.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "dropbear_utils.h"
+
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int dropbear_hex_value(char ch)
+{
+  if (ch >= '0' && ch <= '9')
+    {
+      return ch - '0';
+    }
+
+  if (ch >= 'a' && ch <= 'f')
+    {
+      return ch - 'a' + 10;
+    }
+
+  if (ch >= 'A' && ch <= 'F')
+    {
+      return ch - 'A' + 10;
+    }
+
+  return -1;
+}
+
+static int dropbear_try_mkdir(FAR const char *path)
+{
+  if (mkdir(path, 0700) < 0 && errno != EEXIST)
+    {
+      return -errno;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+void dropbear_hex_encode(FAR char *dst, FAR const uint8_t *src,
+                         size_t srclen)
+{
+  static const char hex[] = "0123456789abcdef";
+  size_t i;
+
+  for (i = 0; i < srclen; i++)
+    {
+      dst[i * 2] = hex[src[i] >> 4];
+      dst[i * 2 + 1] = hex[src[i] & 0x0f];
+    }
+
+  dst[srclen * 2] = '\0';
+}
+
+int dropbear_hex_decode(FAR const char *src, size_t srclen,
+                        FAR uint8_t *dst, size_t dstlen)
+{
+  size_t i;
+
+  if (srclen != dstlen * 2)
+    {
+      return -EINVAL;
+    }
+
+  for (i = 0; i < dstlen; i++)
+    {
+      int hi = dropbear_hex_value(src[i * 2]);
+      int lo = dropbear_hex_value(src[i * 2 + 1]);
+
+      if (hi < 0 || lo < 0)
+        {
+          return -EINVAL;
+        }
+
+      dst[i] = (uint8_t)((hi << 4) | lo);
+    }
+
+  return OK;
+}
+
+int dropbear_try_prepare_parent(FAR const char *path)
+{
+  char dir[PATH_MAX];
+  struct stat st;
+  FAR char *slash;
+  FAR char *p;
+  int ret;
+
+  if (strlcpy(dir, path, sizeof(dir)) >= sizeof(dir))
+    {
+      return -ENAMETOOLONG;
+    }
+
+  slash = strrchr(dir, '/');
+  if (slash == NULL || slash == dir)
+    {
+      return OK;
+    }
+
+  *slash = '\0';
+  if (stat(dir, &st) == 0)
+    {
+      return OK;
+    }
+
+  for (p = dir + 1; *p != '\0'; p++)
+    {
+      if (*p == '/')
+        {
+          *p = '\0';
+          ret = dropbear_try_mkdir(dir);
+          if (ret < 0)
+            {
+              return ret;
+            }
+
+          *p = '/';
+        }
+    }
+
+  return dropbear_try_mkdir(dir);
+}
+
+#ifndef CONFIG_SCHED_USER_IDENTITY
+int dropbear_getgroups(int size, gid_t list[])
+{
+  (void)size;
+  (void)list;
+  set_errno(ENOSYS);
+  return ERROR;
+}
+#endif
diff --git a/netutils/dropbear/port/dropbear_utils.h 
b/netutils/dropbear/port/dropbear_utils.h
new file mode 100644
index 000000000..3e7d2722e
--- /dev/null
+++ b/netutils/dropbear/port/dropbear_utils.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/dropbear_utils.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+#ifndef __APPS_NETUTILS_DROPBEAR_PORT_DROPBEAR_UTILS_H
+#define __APPS_NETUTILS_DROPBEAR_PORT_DROPBEAR_UTILS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "config.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+void dropbear_hex_encode(FAR char *dst, FAR const uint8_t *src,
+                         size_t srclen);
+
+int dropbear_hex_decode(FAR const char *src, size_t srclen,
+                        FAR uint8_t *dst, size_t dstlen);
+
+int dropbear_try_prepare_parent(FAR const char *path);
+
+#endif /* __APPS_NETUTILS_DROPBEAR_PORT_DROPBEAR_UTILS_H */
diff --git a/netutils/dropbear/port/localoptions.h 
b/netutils/dropbear/port/localoptions.h
new file mode 100644
index 000000000..28ac5a3b5
--- /dev/null
+++ b/netutils/dropbear/port/localoptions.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/localoptions.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+#ifndef __APPS_NETUTILS_DROPBEAR_PORT_LOCALOPTIONS_H
+#define __APPS_NETUTILS_DROPBEAR_PORT_LOCALOPTIONS_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DROPBEAR_TRACKING_MALLOC 1
+
+/* Persist the native Dropbear ECDSA host key at the configured path. */
+
+#define ECDSA_PRIV_FILENAME CONFIG_NETUTILS_DROPBEAR_HOSTKEY_PATH
+
+#define DROPBEAR_SVR_DROP_PRIVS 0
+
+#ifdef CONFIG_SCHED_USER_IDENTITY
+#  define DROPBEAR_SVR_MULTIUSER 1
+#else
+#  define DROPBEAR_SVR_MULTIUSER 0
+#endif
+
+#define DROPBEAR_SVR_PASSWORD_AUTH 1
+#define DROPBEAR_SVR_PUBKEY_AUTH 0
+#define DROPBEAR_SVR_PUBKEY_OPTIONS 0
+
+#define DROPBEAR_REEXEC 0
+#define DROPBEAR_SMALL_CODE 1
+#define DROPBEAR_USER_ALGO_LIST 0
+
+#define DROPBEAR_X11FWD 0
+#define DROPBEAR_SVR_AGENTFWD 0
+#define DROPBEAR_SVR_LOCALTCPFWD 0
+#define DROPBEAR_SVR_REMOTETCPFWD 0
+#define DROPBEAR_SVR_LOCALSTREAMFWD 0
+#define DROPBEAR_SVR_REMOTESTREAMFWD 0
+
+#define DROPBEAR_DSS 0
+#define DROPBEAR_RSA 0
+#define DROPBEAR_ECDSA 1
+#define DROPBEAR_ED25519 0
+#define DROPBEAR_SK_KEYS 0
+#define DROPBEAR_ECC_256 1
+#define DROPBEAR_ECC_384 0
+#define DROPBEAR_ECC_521 0
+
+#define DROPBEAR_AES128 1
+#define DROPBEAR_AES256 0
+#define DROPBEAR_CHACHA20POLY1305 1
+#define DROPBEAR_ENABLE_CBC_MODE 0
+#define DROPBEAR_ENABLE_GCM_MODE 0
+
+#define DROPBEAR_SHA1_HMAC 0
+#define DROPBEAR_SHA2_256_HMAC 1
+#define DROPBEAR_SHA2_512_HMAC 0
+#define DROPBEAR_SHA1_96_HMAC 0
+
+#define DROPBEAR_CURVE25519 1
+#define DROPBEAR_DH_GROUP14_SHA1 0
+#define DROPBEAR_DH_GROUP14_SHA256 0
+#define DROPBEAR_DH_GROUP16 0
+#define DROPBEAR_DH_GROUP1 0
+#define DROPBEAR_ECDH 0
+#define DROPBEAR_SNTRUP761 0
+#define DROPBEAR_MLKEM768 0
+
+#define DROPBEAR_DEFAULT_CLI_AUTHKEY "/etc/dropbear/authorized_keys"
+#define DROPBEAR_SFTPSERVER 0
+
+#endif /* __APPS_NETUTILS_DROPBEAR_PORT_LOCALOPTIONS_H */
diff --git a/netutils/dropbear/port/nuttx_auth.c 
b/netutils/dropbear/port/nuttx_auth.c
new file mode 100644
index 000000000..83becdcae
--- /dev/null
+++ b/netutils/dropbear/port/nuttx_auth.c
@@ -0,0 +1,109 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/nuttx_auth.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "fsutils/passwd.h"
+
+#include "dbutil.h"
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct passwd g_dropbear_pw;
+static char g_dropbear_name[64];
+static char g_dropbear_dir[] = "/";
+static char g_dropbear_shell[] = "/bin/sh";
+static char g_dropbear_password_marker[] = "x";
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static FAR struct passwd *dropbear_fill_pw(FAR const char *name, uid_t uid)
+{
+  memset(&g_dropbear_pw, 0, sizeof(g_dropbear_pw));
+
+  snprintf(g_dropbear_name, sizeof(g_dropbear_name), "%s", name);
+
+  g_dropbear_pw.pw_uid = uid;
+  g_dropbear_pw.pw_gid = 0;
+  g_dropbear_pw.pw_name = g_dropbear_name;
+  g_dropbear_pw.pw_passwd = g_dropbear_password_marker;
+  g_dropbear_pw.pw_gecos = g_dropbear_name;
+  g_dropbear_pw.pw_dir = g_dropbear_dir;
+  g_dropbear_pw.pw_shell = g_dropbear_shell;
+
+  return &g_dropbear_pw;
+}
+
+FAR struct passwd *dropbear_getpwuid(uid_t uid)
+{
+  return dropbear_fill_pw("root", uid);
+}
+
+FAR struct passwd *dropbear_getpwnam(FAR const char *name)
+{
+  if (name == NULL || name[0] == '\0')
+    {
+      return NULL;
+    }
+
+  return dropbear_fill_pw(name, 0);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+uid_t dropbear_getuid(void)
+{
+  return 0;
+}
+
+uid_t dropbear_geteuid(void)
+{
+  return 0;
+}
+
+int dropbear_auth_initialize(void)
+{
+  dropbear_log(LOG_INFO, "using NuttX passwd auth at %s",
+               CONFIG_FSUTILS_PASSWD_PATH);
+  return OK;
+}
+
+int dropbear_verify_password(FAR const char *username,
+                             FAR const char *password)
+{
+  int ret;
+
+  ret = passwd_verify(username, password);
+  if (PASSWORD_VERIFY_MATCH(ret))
+    {
+      return DROPBEAR_SUCCESS;
+    }
+
+  if (PASSWORD_VERIFY_ERROR(ret) && ret != -ENOENT)
+    {
+      dropbear_log(LOG_WARNING, "passwd_verify failed for '%s': %d",
+                   username, ret);
+    }
+
+  return DROPBEAR_FAILURE;
+}
diff --git a/netutils/dropbear/port/nuttx_config.h 
b/netutils/dropbear/port/nuttx_config.h
new file mode 100644
index 000000000..d91709d1e
--- /dev/null
+++ b/netutils/dropbear/port/nuttx_config.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/nuttx_config.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ ****************************************************************************/
+
+#ifndef __APPS_NETUTILS_DROPBEAR_PORT_NUTTX_CONFIG_H
+#define __APPS_NETUTILS_DROPBEAR_PORT_NUTTX_CONFIG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DROPBEAR_SERVER 1
+#define BUNDLED_LIBTOM 1
+#define DISABLE_LASTLOG 1
+#define DISABLE_PAM 1
+#define DISABLE_PUTUTLINE 1
+#define DISABLE_PUTUTXLINE 1
+#define DISABLE_UTMP 1
+#define DISABLE_UTMPX 1
+#define DISABLE_WTMP 1
+#define DISABLE_WTMPX 1
+
+#ifndef CONFIG_NETUTILS_DROPBEAR_SYSLOG
+#  define DISABLE_SYSLOG 1
+#endif
+
+#ifndef CONFIG_NETUTILS_DROPBEAR_COMPRESSION
+#  define DISABLE_ZLIB 1
+#endif
+
+#define DROPBEAR_FUZZ 0
+#define DROPBEAR_PLUGIN 0
+
+#define HAVE_BASENAME 1
+#define HAVE_CLOCK_GETTIME 1
+#define HAVE_CONST_GAI_STRERROR_PROTO 1
+#define HAVE_CRYPT 1
+#define HAVE_DECL_HTOLE64 1
+#define HAVE_ENDIAN_H 1
+#define HAVE_EXPLICIT_BZERO 1
+#define HAVE_FREEADDRINFO 1
+#define HAVE_GAI_STRERROR 1
+#define HAVE_GETADDRINFO 1
+#define HAVE_GETNAMEINFO 1
+#define HAVE_GETRANDOM 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_LIBGEN_H 1
+#define HAVE_NETDB_H 1
+#define HAVE_NETINET_IN_H 1
+#define HAVE_NETINET_TCP_H 1
+#define HAVE_PATHS_H 1
+#define HAVE_PUTENV 1
+#define HAVE_STATIC_ASSERT 1
+#define HAVE_STDINT_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRUCT_ADDRINFO 1
+#define HAVE_STRUCT_IN6_ADDR 1
+#define HAVE_STRUCT_SOCKADDR_IN6 1
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
+#define HAVE_SYS_RANDOM_H 1
+#define HAVE_SYS_SELECT_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_UIO_H 1
+#define HAVE_SYS_WAIT_H 1
+#define HAVE_UINT16_T 1
+#define HAVE_UINT32_T 1
+#define HAVE_UINT8_T 1
+#define HAVE_U_INT16_T 1
+#define HAVE_U_INT32_T 1
+#define HAVE_U_INT8_T 1
+#define HAVE_UNDERSCORE_STATIC_ASSERT 1
+#define HAVE_UNISTD_H 1
+/* NuttX exposes writev(), but keep this port on Dropbear's simpler write()
+ * path until the SSH-to-NSH channel bridge is validated with vectored
+ * writes.
+ */
+
+#undef HAVE_WRITEV
+#define STDC_HEADERS 1
+
+#define PACKAGE_BUGREPORT ""
+#define PACKAGE_NAME ""
+#define PACKAGE_STRING ""
+#define PACKAGE_TARNAME ""
+#define PACKAGE_URL ""
+#define PACKAGE_VERSION ""
+
+#define SELECT_TYPE_ARG1 int
+#define SELECT_TYPE_ARG234 (fd_set *)
+#define SELECT_TYPE_ARG5 (struct timeval *)
+
+#ifndef PF_UNIX
+#  define PF_UNIX AF_UNIX
+#endif
+
+#ifndef GRND_NONBLOCK
+#  define GRND_NONBLOCK O_NONBLOCK
+#endif
+
+#define IPPORT_RESERVED 1024
+
+#define getuid dropbear_getuid
+#define geteuid dropbear_geteuid
+#define getpwuid dropbear_getpwuid
+#define getpwnam dropbear_getpwnam
+uid_t getuid(void);
+uid_t geteuid(void);
+struct passwd *getpwuid(uid_t uid);
+struct passwd *getpwnam(const char *name);
+int dropbear_auth_initialize(void);
+int dropbear_verify_password(const char *username, const char *password);
+
+#ifndef CONFIG_SCHED_USER_IDENTITY
+/* NuttX has no supplementary-group support, so getgroups() does not exist. */
+
+int dropbear_getgroups(int size, gid_t list[]);
+
+#  define getgroups dropbear_getgroups
+#endif
+
+#endif /* __APPS_NETUTILS_DROPBEAR_PORT_NUTTX_CONFIG_H */
diff --git a/nshlib/CMakeLists.txt b/nshlib/CMakeLists.txt
index 8adab3168..866f8bb6c 100644
--- a/nshlib/CMakeLists.txt
+++ b/nshlib/CMakeLists.txt
@@ -101,6 +101,10 @@ if(CONFIG_NSH_LIBRARY)
     endif()
   endif()
 
+  if(CONFIG_NSH_DROPBEAR)
+    list(APPEND CSRCS nsh_dropbear.c)
+  endif()
+
   if(NOT CONFIG_NSH_DISABLESCRIPT)
     list(APPEND CSRCS nsh_test.c)
   endif()
diff --git a/nshlib/Kconfig b/nshlib/Kconfig
index 80476e7f5..01103ee29 100644
--- a/nshlib/Kconfig
+++ b/nshlib/Kconfig
@@ -1201,6 +1201,28 @@ config NSH_DISABLE_TELNETSTART
 
 endmenu # Telnet Configuration
 
+menu "Dropbear Configuration"
+
+config NSH_DROPBEAR
+       bool "Start Dropbear SSH server"
+       default n
+       depends on NETUTILS_DROPBEAR
+       depends on NSH_BUILTIN_APPS
+       depends on !NSH_DISABLEBG
+       select NSH_LOGIN
+       ---help---
+               If NSH_DROPBEAR is set to 'y', then NSH starts the Dropbear SSH
+               server automatically.
+
+config NSH_DISABLE_DROPBEARSTART
+       bool "Disable to start Dropbear"
+       default n
+       depends on NSH_DROPBEAR
+       ---help---
+               Determines if NSH starts Dropbear automatically.
+
+endmenu # Dropbear Configuration
+
 config NSH_LOGIN
        bool
        default n
diff --git a/nshlib/Makefile b/nshlib/Makefile
index d15ca4aa3..4aba9e3a8 100644
--- a/nshlib/Makefile
+++ b/nshlib/Makefile
@@ -86,6 +86,10 @@ CSRCS += nsh_telnetlogin.c
 endif
 endif
 
+ifeq ($(CONFIG_NSH_DROPBEAR),y)
+CSRCS += nsh_dropbear.c
+endif
+
 ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
 CSRCS += nsh_test.c
 endif
diff --git a/nshlib/nsh.h b/nshlib/nsh.h
index f20fcf773..872c1e4af 100644
--- a/nshlib/nsh.h
+++ b/nshlib/nsh.h
@@ -844,6 +844,10 @@ int nsh_login(FAR struct console_stdio_s *pstate);
 int nsh_telnetlogin(FAR struct console_stdio_s *pstate);
 #endif
 
+#if defined(CONFIG_NSH_DROPBEAR) && !defined(CONFIG_NSH_DISABLE_DROPBEARSTART)
+int nsh_dropbearstart(void);
+#endif
+
 /* Application interface */
 
 int nsh_command(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char *argv[]);
diff --git a/fsutils/passwd/passwd_append.c b/nshlib/nsh_dropbear.c
similarity index 55%
copy from fsutils/passwd/passwd_append.c
copy to nshlib/nsh_dropbear.c
index be77c9aed..9e7753f11 100644
--- a/fsutils/passwd/passwd_append.c
+++ b/nshlib/nsh_dropbear.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * apps/fsutils/passwd/passwd_append.c
+ * apps/nshlib/nsh_dropbear.c
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -24,80 +24,53 @@
  * Included Files
  ****************************************************************************/
 
-#include <stdio.h>
+#include <nuttx/config.h>
+
 #include <assert.h>
-#include <errno.h>
+#include <debug.h>
+
+#include "nsh.h"
+#include "nsh_console.h"
 
-#include "passwd.h"
+#ifdef CONFIG_NSH_DROPBEAR
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: passwd_append
+ * Name: nsh_dropbearstart
  *
  * Description:
- *  Append a new record to the end of the /etc/passwd file
+ *   nsh_dropbearstart() starts the Dropbear SSH server.  This function
+ *   returns immediately after the daemon has been started.
  *
- * Input Parameters:
- *
- * Returned Value:
- *   Zero (OK) is returned on success; a negated errno value is returned on
- *   failure.
+ * Returned Values:
+ *   Zero is returned if Dropbear was started.  A negated errno value will be
+ *   returned on failure.
  *
  ****************************************************************************/
 
-int passwd_append(FAR const char *username, FAR const char *password)
+#ifndef CONFIG_NSH_DISABLE_DROPBEARSTART
+int nsh_dropbearstart(void)
 {
-  char encrypted[MAX_ENCRYPTED + 1];
-  FILE *stream;
+  FAR struct console_stdio_s *pstate = nsh_newconsole(false);
+  char cmdline[] = CONFIG_NETUTILS_DROPBEAR_PROGNAME " &";
   int ret;
 
-  /* Encrypt the raw password */
-
-  ret = passwd_encrypt(password, encrypted);
-  if (ret < 0)
-    {
-      return ret;
-    }
-
-  /* Append the new user record to the end of the password file */
-
-  stream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "a");
-  if (stream == NULL)
-    {
-      int errcode = errno;
-      DEBUGASSERT(errcode > 0);
-      return errcode;
-    }
+  DEBUGASSERT(pstate != NULL);
 
-  /* The format of the password file is:
-   *
-   *   user:x:uid:gid:home
-   *
-   * Where:
-   *   user:  User name
-   *   x:     Encrypted password
-   *   uid:   User ID (0 for now)
-   *   gid:   Group ID (0 for now)
-   *   home:  Login directory (/ for now)
-   */
+  ninfo("Starting the Dropbear SSH server\n");
 
-  ret = fprintf(stream, "%s:%s:0:0:/\n", username, encrypted);
+  ret = nsh_parse(&pstate->cn_vtbl, cmdline);
   if (ret < 0)
     {
-      int errcode = errno;
-      DEBUGASSERT(errcode > 0);
-      ret = -errcode;
-      goto errout_with_stream;
+      nerr("ERROR: Failed to start Dropbear: %d\n", ret);
     }
 
-  /* Return success */
-
-  ret = OK;
-
-errout_with_stream:
-  fclose(stream);
+  nsh_release(&pstate->cn_vtbl);
   return ret;
 }
+#endif
+
+#endif /* CONFIG_NSH_DROPBEAR */
diff --git a/nshlib/nsh_init.c b/nshlib/nsh_init.c
index aea095e34..49c1488e6 100644
--- a/nshlib/nsh_init.c
+++ b/nshlib/nsh_init.c
@@ -175,4 +175,16 @@ void nsh_initialize(void)
 
   nsh_telnetstart(AF_UNSPEC);
 #endif
+
+#if defined(CONFIG_NSH_DROPBEAR) && \
+    !defined(CONFIG_NSH_DISABLE_DROPBEARSTART) && \
+    !defined(CONFIG_NETINIT_NETLOCAL)
+  /* If Dropbear is selected as an SSH front-end, then start the daemon
+   * UNLESS network initialization is deferred via CONFIG_NETINIT_NETLOCAL.
+   * In that case, Dropbear must be started manually with the dropbear
+   * command after the network has been initialized.
+   */
+
+  nsh_dropbearstart();
+#endif
 }

Reply via email to