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 690ec808e netutils/dropbear: back hmac-sha2-256 with NuttX /dev/crypto
690ec808e is described below
commit 690ec808e54168459b127122bc0791044388118d
Author: Felipe Moura <[email protected]>
AuthorDate: Sat Jul 11 20:14:39 2026 -0300
netutils/dropbear: back hmac-sha2-256 with NuttX /dev/crypto
Replace the bundled libtomcrypt HMAC modules with an adapter that computes
the hmac-sha2-256 packet MAC through the NuttX crypto device using
CRYPTO_SHA2_256_HMAC sessions.
Require CRYPTO, CRYPTO_RANDOM_POOL, CRYPTO_CRYPTODEV and
CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO explicitly instead of selecting crypto support.
Signed-off-by: Felipe Moura <[email protected]>
---
netutils/dropbear/CMakeLists.txt | 7 +
netutils/dropbear/Kconfig | 11 +
netutils/dropbear/Makefile | 10 +
netutils/dropbear/port/dropbear_ltc_hmac_sha256.c | 255 ++++++++++++++++++++++
4 files changed, 283 insertions(+)
diff --git a/netutils/dropbear/CMakeLists.txt b/netutils/dropbear/CMakeLists.txt
index eb31d0012..96cbcc233 100644
--- a/netutils/dropbear/CMakeLists.txt
+++ b/netutils/dropbear/CMakeLists.txt
@@ -135,6 +135,13 @@ if(CONFIG_NETUTILS_DROPBEAR)
file(GLOB_RECURSE LIBTOMCRYPT_SRCS CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtomcrypt/src/*.c")
list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/prngs/sober128tab\\.c$")
+
+ # Drop the bundled libtomcrypt HMAC modules replaced by the NuttX adapter.
+ list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/mac/hmac/hmac_init\\.c$")
+ list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/mac/hmac/hmac_process\\.c$")
+ list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/mac/hmac/hmac_done\\.c$")
+ list(APPEND DROPBEAR_SRCS port/dropbear_ltc_hmac_sha256.c)
+
list(APPEND DROPBEAR_SRCS ${LIBTOMCRYPT_SRCS})
if(CONFIG_NETUTILS_DROPBEAR_SCP)
diff --git a/netutils/dropbear/Kconfig b/netutils/dropbear/Kconfig
index 43a2c4a51..ae37135cb 100644
--- a/netutils/dropbear/Kconfig
+++ b/netutils/dropbear/Kconfig
@@ -21,11 +21,22 @@ menuconfig NETUTILS_DROPBEAR
depends on LIBC_GAISTRERROR
depends on CRYPTO
depends on CRYPTO_RANDOM_POOL
+ depends on ALLOW_BSD_COMPONENTS
+ depends on CRYPTO_CRYPTODEV
+ depends on CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
---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.
+ The port computes the hmac-sha2-256 packet MAC through the NuttX
+ crypto device (/dev/crypto, CRYPTO_SHA2_256_HMAC) instead of the
+ bundled libtomcrypt implementation, which is dropped from the
+ build. The SHA-256 hash descriptor itself stays in the
+ application: Dropbear's key derivation clones partially-updated
+ hash states (hashkeys() in common-kex.c), which cannot be
+ represented by a kernel crypto session.
+
if NETUTILS_DROPBEAR
config NETUTILS_DROPBEAR_STACKSIZE
diff --git a/netutils/dropbear/Makefile b/netutils/dropbear/Makefile
index 17e5ec8db..145e5c5ae 100644
--- a/netutils/dropbear/Makefile
+++ b/netutils/dropbear/Makefile
@@ -119,6 +119,16 @@ CSRCS += \
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)
+# Drop the bundled libtomcrypt HMAC modules replaced by the NuttX adapter.
+
+TOMCRYPT_SRCS := $(filter-out \
+ %/mac/hmac/hmac_init.c \
+ %/mac/hmac/hmac_process.c \
+ %/mac/hmac/hmac_done.c, \
+ $(TOMCRYPT_SRCS))
+
+CSRCS += port/dropbear_ltc_hmac_sha256.c
+
CSRCS += $(TOMMATH_SRCS)
CSRCS += $(TOMCRYPT_SRCS)
diff --git a/netutils/dropbear/port/dropbear_ltc_hmac_sha256.c
b/netutils/dropbear/port/dropbear_ltc_hmac_sha256.c
new file mode 100644
index 000000000..dda511d5f
--- /dev/null
+++ b/netutils/dropbear/port/dropbear_ltc_hmac_sha256.c
@@ -0,0 +1,255 @@
+/****************************************************************************
+ * apps/netutils/dropbear/port/dropbear_ltc_hmac_sha256.c
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+/* LibTomCrypt-compatible incremental HMAC API backed by a
+ * CRYPTO_SHA2_256_HMAC /dev/crypto session (hmac-sha2-256, the only MAC the
+ * NuttX Dropbear configuration enables): init opens the session, process
+ * feeds data with COP_FLAG_UPDATE, done reads the tag and frees the session.
+ */
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "includes.h"
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <crypto/cryptodev.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define DROPBEAR_HMAC_SHA256_DIGESTLEN 32
+#define DROPBEAR_HMAC_SHA256_BLOCKLEN 64
+
+/* Stash the process-local /dev/crypto descriptor and session id in the
+ * unused md hash-state buffer so the upstream hmac_state needs no patch.
+ */
+
+static_assert(sizeof(int) + sizeof(uint32_t) <= sizeof(hash_state),
+ "cryptodev state does not fit in hmac_state.md");
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int dropbear_hmac_cryptodev_open(void)
+{
+ int fd;
+ int cfd;
+
+ fd = open("/dev/crypto", O_RDWR);
+ if (fd < 0)
+ {
+ return -1;
+ }
+
+ if (ioctl(fd, CRIOGET, &cfd) < 0)
+ {
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ if (fcntl(cfd, F_SETFD, FD_CLOEXEC) < 0)
+ {
+ close(cfd);
+ return -1;
+ }
+
+ return cfd;
+}
+
+static int dropbear_hmac_hash_is_sha256(int hash)
+{
+ int ret;
+
+ ret = hash_is_valid(hash);
+ if (ret != CRYPT_OK)
+ {
+ return ret;
+ }
+
+ if (hash_descriptor[hash].hashsize != DROPBEAR_HMAC_SHA256_DIGESTLEN ||
+ hash_descriptor[hash].blocksize != DROPBEAR_HMAC_SHA256_BLOCKLEN)
+ {
+ return CRYPT_INVALID_HASH;
+ }
+
+ return CRYPT_OK;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int hmac_init(hmac_state *hmac, int hash, const unsigned char *key,
+ unsigned long keylen)
+{
+ struct session_op session;
+ int cfd;
+ int ret;
+
+ LTC_ARGCHK(hmac != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if (keylen == 0 || keylen > INT_MAX)
+ {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ ret = dropbear_hmac_hash_is_sha256(hash);
+ if (ret != CRYPT_OK)
+ {
+ return ret;
+ }
+
+ zeromem(hmac, sizeof(*hmac));
+ cfd = dropbear_hmac_cryptodev_open();
+ if (cfd < 0)
+ {
+ return CRYPT_ERROR;
+ }
+
+ memset(&session, 0, sizeof(session));
+ session.mac = CRYPTO_SHA2_256_HMAC;
+ session.mackey = (caddr_t)key;
+ session.mackeylen = (int)keylen;
+ if (ioctl(cfd, CIOCGSESSION, &session) < 0)
+ {
+ close(cfd);
+ zeromem(hmac, sizeof(*hmac));
+ return CRYPT_ERROR;
+ }
+
+ memcpy(&hmac->md, &cfd, sizeof(cfd));
+ memcpy((FAR uint8_t *)&hmac->md + sizeof(cfd),
+ &session.ses, sizeof(session.ses));
+ hmac->hash = hash;
+ return CRYPT_OK;
+}
+
+int hmac_process(hmac_state *hmac, const unsigned char *in,
+ unsigned long inlen)
+{
+ struct crypt_op cryp;
+ uint32_t ses;
+ int cfd;
+ int ret;
+
+ LTC_ARGCHK(hmac != NULL);
+ LTC_ARGCHK(in != NULL || inlen == 0);
+
+ ret = dropbear_hmac_hash_is_sha256(hmac->hash);
+ if (ret != CRYPT_OK)
+ {
+ return ret;
+ }
+
+ if (inlen > UINT_MAX)
+ {
+ return CRYPT_OVERFLOW;
+ }
+
+ memcpy(&cfd, &hmac->md, sizeof(cfd));
+ memcpy(&ses, (FAR uint8_t *)&hmac->md + sizeof(cfd), sizeof(ses));
+ if (cfd < 0)
+ {
+ return CRYPT_ERROR;
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = ses;
+ cryp.op = COP_ENCRYPT;
+ cryp.flags = COP_FLAG_UPDATE;
+ cryp.len = (unsigned int)inlen;
+ cryp.src = (caddr_t)in;
+ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0)
+ {
+ return CRYPT_ERROR;
+ }
+
+ return CRYPT_OK;
+}
+
+int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)
+{
+ unsigned char digest[DROPBEAR_HMAC_SHA256_DIGESTLEN];
+ struct crypt_op cryp;
+ unsigned long copylen;
+ uint32_t ses;
+ int cfd;
+ int ret = CRYPT_ERROR;
+
+ LTC_ARGCHK(hmac != NULL);
+ LTC_ARGCHK(out != NULL);
+ LTC_ARGCHK(outlen != NULL);
+
+ memcpy(&cfd, &hmac->md, sizeof(cfd));
+ memcpy(&ses, (FAR uint8_t *)&hmac->md + sizeof(cfd), sizeof(ses));
+ if (cfd < 0)
+ {
+ goto out;
+ }
+
+ ret = dropbear_hmac_hash_is_sha256(hmac->hash);
+ if (ret != CRYPT_OK)
+ {
+ goto out;
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = ses;
+ cryp.op = COP_ENCRYPT;
+ cryp.len = 0;
+ cryp.src = (caddr_t)digest;
+ cryp.mac = (caddr_t)digest;
+ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0)
+ {
+ ret = CRYPT_ERROR;
+ goto out;
+ }
+
+ copylen = MIN(*outlen, DROPBEAR_HMAC_SHA256_DIGESTLEN);
+ memcpy(out, digest, copylen);
+ *outlen = copylen;
+ ret = CRYPT_OK;
+
+out:
+ if (cfd >= 0)
+ {
+ ioctl(cfd, CIOCFSESSION, &ses);
+ close(cfd);
+ }
+
+ zeromem(digest, sizeof(digest));
+ zeromem(hmac, sizeof(*hmac));
+ return ret;
+}