Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions netutils/dropbear/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -225,6 +232,15 @@ if(CONFIG_NETUTILS_DROPBEAR)
set_source_files_properties(${LIBTOMCRYPT_SRCS} PROPERTIES COMPILE_DEFINITIONS
LTC_SOURCE=1)

# The NuttX crypto backend pulled in by /dev/crypto also exports ecc_make_key.
# Dropbear only uses libtomcrypt's ecc_make_key_ex, so rename the unused plain
# wrapper to avoid a multiple definition. Append so the LTC_SOURCE define set
# above is preserved.
set_property(
SOURCE dropbear/libtomcrypt/src/pk/ecc/ecc_make_key.c
APPEND
PROPERTY COMPILE_DEFINITIONS ecc_make_key=dropbear_ltc_ecc_make_key)

target_compile_options(${PROGNAME} PRIVATE -Wno-pointer-sign -Wno-format)

if(CONFIG_NETUTILS_DROPBEAR_SCP)
Expand Down
12 changes: 11 additions & 1 deletion netutils/dropbear/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,23 @@ menuconfig NETUTILS_DROPBEAR
depends on DEV_URANDOM
depends on LIBC_NETDB
depends on LIBC_GAISTRERROR
select CRYPTO
depends on ALLOW_BSD_COMPONENTS
depends on CRYPTO_CRYPTODEV
depends on CRYPTO_CRYPTODEV_SOFTWARE_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.

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
Expand Down
15 changes: 15 additions & 0 deletions netutils/dropbear/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -130,6 +140,11 @@ endif
# 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))

# The NuttX crypto backend pulled in by /dev/crypto also exports
# ecc_make_key. Dropbear only uses libtomcrypt's ecc_make_key_ex, so rename
# the unused plain wrapper to avoid a link-time multiple definition.
dropbear/libtomcrypt/src/pk/ecc/ecc_make_key.c_CFLAGS += ${DEFINE_PREFIX}ecc_make_key=dropbear_ltc_ecc_make_key

MAINSRC = dropbear_main.c

ifneq ($(CONFIG_NETUTILS_DROPBEAR_SCP),)
Expand Down
227 changes: 227 additions & 0 deletions netutils/dropbear/port/dropbear_ltc_hmac_sha256.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/****************************************************************************
* 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 <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 /dev/crypto session id in the unused md hash-state buffer so the
* upstream hmac_state needs no patch (hash index uses the existing field).
*/

#define HMAC_SES(h) (*(FAR unsigned int *)&(h)->md)

/****************************************************************************
* Private Data
****************************************************************************/

static int g_dropbear_hmac_cryptofd = -1;

/****************************************************************************
* Private Functions
****************************************************************************/

static int dropbear_hmac_cryptodev_fd(void)
{
int fd;
int cfd;

if (g_dropbear_hmac_cryptofd >= 0)
{
return g_dropbear_hmac_cryptofd;
}

fd = open("/dev/crypto", O_RDWR);
if (fd < 0)
{
return -1;
}

if (ioctl(fd, CRIOGET, &cfd) < 0)
{
close(fd);
return -1;
}

close(fd);
g_dropbear_hmac_cryptofd = cfd;
return g_dropbear_hmac_cryptofd;
}

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)
{
return CRYPT_INVALID_KEYSIZE;
}

ret = dropbear_hmac_hash_is_sha256(hash);
if (ret != CRYPT_OK)
{
return ret;
}

cfd = dropbear_hmac_cryptodev_fd();
if (cfd < 0)
{
return CRYPT_ERROR;
}

memset(&session, 0, sizeof(session));
session.mac = CRYPTO_SHA2_256_HMAC;
session.mackey = (caddr_t)key;
session.mackeylen = keylen;
if (ioctl(cfd, CIOCGSESSION, &session) < 0)
{
return CRYPT_ERROR;
}

hmac->hash = hash;
HMAC_SES(hmac) = session.ses;
return CRYPT_OK;
}

int hmac_process(hmac_state *hmac, const unsigned char *in,
unsigned long inlen)
{
struct crypt_op cryp;
int cfd;

LTC_ARGCHK(hmac != NULL);
LTC_ARGCHK(in != NULL || inlen == 0);

cfd = dropbear_hmac_cryptodev_fd();
if (cfd < 0)
{
return CRYPT_ERROR;
}

memset(&cryp, 0, sizeof(cryp));
cryp.ses = HMAC_SES(hmac);
cryp.op = COP_ENCRYPT;
cryp.flags = COP_FLAG_UPDATE;
cryp.len = 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;
int cfd;
int ret = CRYPT_ERROR;

LTC_ARGCHK(hmac != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);

cfd = dropbear_hmac_cryptodev_fd();
if (cfd < 0)
{
goto out;
}

memset(&cryp, 0, sizeof(cryp));
cryp.ses = HMAC_SES(hmac);
cryp.op = COP_ENCRYPT;
cryp.len = 0;
cryp.mac = (caddr_t)digest;
if (ioctl(cfd, CIOCCRYPT, &cryp) < 0)
{
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, &HMAC_SES(hmac));
}

zeromem(digest, sizeof(digest));
zeromem(hmac, sizeof(*hmac));
return ret;
}
Loading