mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
netutils/dropbear: use NuttX /dev/crypto for chacha20-poly1305
Replace the bundled libtomcrypt chacha20-poly1305@openssh.com with an adapter backed by the NuttX crypto framework: CRYPTO_CHACHA20 for the two keystreams (payload and packet-length) and CRYPTO_POLY1305 for the per-packet MAC, both routed through /dev/crypto ioctls. Gated behind CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY (default y when NETUTILS_DROPBEAR_NUTTX_CRYPTO is enabled). Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
This commit is contained in:
parent
81b2a1be26
commit
7840ea5bdb
5 changed files with 406 additions and 0 deletions
|
|
@ -68,6 +68,11 @@ if(CONFIG_NETUTILS_DROPBEAR)
|
|||
patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0005-use-nuttx-sha256-hmac.patch"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0006-use-nuttx-chachapoly-cryptodev.patch"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
message(STATUS "Generating default_options_guard.h")
|
||||
execute_process(
|
||||
COMMAND
|
||||
|
|
@ -151,6 +156,12 @@ if(CONFIG_NETUTILS_DROPBEAR)
|
|||
port/dropbear_ltc_hmac_sha256.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY)
|
||||
# Replace the bundled chacha20-poly1305 with the /dev/crypto adapter.
|
||||
list(REMOVE_ITEM DROPBEAR_SRCS dropbear/src/chachapoly.c)
|
||||
list(APPEND DROPBEAR_SRCS port/dropbear_chachapoly.c)
|
||||
endif()
|
||||
|
||||
list(APPEND DROPBEAR_SRCS ${LIBTOMCRYPT_SRCS})
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_SCP)
|
||||
|
|
@ -216,6 +227,10 @@ if(CONFIG_NETUTILS_DROPBEAR)
|
|||
DROPBEAR_NUTTX_HMAC_SHA256=1)
|
||||
endif()
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY)
|
||||
target_compile_definitions(${PROGNAME} PRIVATE DROPBEAR_NUTTX_CHACHAPOLY=1)
|
||||
endif()
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_SCP)
|
||||
target_compile_definitions(
|
||||
scp PRIVATE LOCALOPTIONS_H_EXISTS=1 DROPBEAR_NUTTX=1
|
||||
|
|
@ -246,6 +261,17 @@ if(CONFIG_NETUTILS_DROPBEAR)
|
|||
set_source_files_properties(${LIBTOMCRYPT_SRCS} PROPERTIES COMPILE_DEFINITIONS
|
||||
LTC_SOURCE=1)
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY)
|
||||
# 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)
|
||||
endif()
|
||||
|
||||
target_compile_options(${PROGNAME} PRIVATE -Wno-pointer-sign -Wno-format)
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_SCP)
|
||||
|
|
|
|||
|
|
@ -100,6 +100,19 @@ config NETUTILS_DROPBEAR_NUTTX_CRYPTO
|
|||
modules, reducing flash usage. This requires a flat build because
|
||||
Dropbear calls the kernel crypto functions directly.
|
||||
|
||||
config NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY
|
||||
bool "Use NuttX /dev/crypto for chacha20-poly1305"
|
||||
default y
|
||||
depends on NETUTILS_DROPBEAR_NUTTX_CRYPTO
|
||||
select CRYPTO_CRYPTODEV
|
||||
select CRYPTO_SW_AES
|
||||
select CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
|
||||
---help---
|
||||
Implement the chacha20-poly1305@openssh.com cipher through the NuttX
|
||||
crypto device (/dev/crypto) using the CRYPTO_CHACHA20 and
|
||||
CRYPTO_POLY1305 algorithms instead of the bundled libtomcrypt
|
||||
implementation.
|
||||
|
||||
config NETUTILS_DROPBEAR_PORT
|
||||
int "Dropbear listen port"
|
||||
default 2222
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX_SHA256=1
|
|||
CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX_HMAC_SHA256=1
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY),)
|
||||
CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX_CHACHAPOLY=1
|
||||
endif
|
||||
|
||||
dropbear_nshsession.c_CFLAGS += ${DEFINE_PREFIX}Channel=dropbear_channel
|
||||
dropbear_nshsession.c_CFLAGS += ${DEFINE_PREFIX}ChanType=dropbear_chantype
|
||||
|
||||
|
|
@ -138,6 +142,13 @@ CSRCS += port/dropbear_ltc_sha256.c
|
|||
CSRCS += port/dropbear_ltc_hmac_sha256.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY),)
|
||||
# Replace the bundled chacha20-poly1305 with the /dev/crypto adapter.
|
||||
|
||||
CSRCS := $(filter-out dropbear/src/chachapoly.c,$(CSRCS))
|
||||
CSRCS += port/dropbear_chachapoly.c
|
||||
endif
|
||||
|
||||
CSRCS += $(TOMMATH_SRCS)
|
||||
CSRCS += $(TOMCRYPT_SRCS)
|
||||
|
||||
|
|
@ -149,6 +160,13 @@ 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))
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR_NUTTX_CHACHAPOLY),)
|
||||
# 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
|
||||
endif
|
||||
|
||||
MAINSRC = dropbear_main.c
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR_SCP),)
|
||||
|
|
@ -181,6 +199,7 @@ $(DROPBEAR_UNPACKNAME): $(DROPBEAR_ZIP)
|
|||
$(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
|
||||
$(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i $(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0005-use-nuttx-sha256-hmac.patch; true
|
||||
$(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i $(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0006-use-nuttx-chachapoly-cryptodev.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 \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
--- a/src/chachapoly.h
|
||||
+++ b/src/chachapoly.h
|
||||
@@ -31,10 +31,17 @@
|
||||
|
||||
#if DROPBEAR_CHACHA20POLY1305
|
||||
|
||||
+#ifdef DROPBEAR_NUTTX_CHACHAPOLY
|
||||
+typedef struct {
|
||||
+ unsigned char key_main[32];
|
||||
+ unsigned char key_header[32];
|
||||
+} dropbear_chachapoly_state;
|
||||
+#else
|
||||
typedef struct {
|
||||
chacha_state chacha;
|
||||
chacha_state header;
|
||||
} dropbear_chachapoly_state;
|
||||
+#endif
|
||||
|
||||
extern const struct dropbear_cipher dropbear_chachapoly;
|
||||
extern const struct dropbear_cipher_mode dropbear_mode_chachapoly;
|
||||
328
netutils/dropbear/port/dropbear_chachapoly.c
Normal file
328
netutils/dropbear/port/dropbear_chachapoly.c
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/dropbear_chachapoly.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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <crypto/cryptodev.h>
|
||||
|
||||
#include "algo.h"
|
||||
#include "dbutil.h"
|
||||
#include "chachapoly.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define CHACHA20_KEY_LEN 32
|
||||
#define CHACHA20_BLOCKSIZE 8
|
||||
#define CHACHA20_IV_LEN 16
|
||||
#define POLY1305_KEY_LEN 32
|
||||
#define POLY1305_TAG_LEN 16
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct ltc_cipher_descriptor g_dropbear_chachapoly_dummy =
|
||||
{
|
||||
.name = NULL
|
||||
};
|
||||
|
||||
static const struct dropbear_hash g_dropbear_chachapoly_mac =
|
||||
{
|
||||
NULL,
|
||||
POLY1305_KEY_LEN,
|
||||
POLY1305_TAG_LEN
|
||||
};
|
||||
|
||||
static int g_dropbear_cryptofd = -1;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct dropbear_cipher dropbear_chachapoly =
|
||||
{
|
||||
&g_dropbear_chachapoly_dummy,
|
||||
CHACHA20_KEY_LEN * 2,
|
||||
CHACHA20_BLOCKSIZE
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int dropbear_cryptodev_fd(void)
|
||||
{
|
||||
int fd;
|
||||
int cfd;
|
||||
|
||||
if (g_dropbear_cryptofd >= 0)
|
||||
{
|
||||
return g_dropbear_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_cryptofd = cfd;
|
||||
return g_dropbear_cryptofd;
|
||||
}
|
||||
|
||||
static int dropbear_chacha(FAR const unsigned char *key, unsigned int seq,
|
||||
uint64_t counter, FAR const unsigned char *in,
|
||||
FAR unsigned char *out, size_t len)
|
||||
{
|
||||
struct session_op session;
|
||||
struct crypt_op cryp;
|
||||
unsigned char iv[CHACHA20_IV_LEN];
|
||||
int cfd;
|
||||
int ret = CRYPT_ERROR;
|
||||
int i;
|
||||
|
||||
cfd = dropbear_cryptodev_fd();
|
||||
if (cfd < 0)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
memset(iv, 0, sizeof(iv));
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
iv[i] = (unsigned char)(counter >> (8 * i));
|
||||
}
|
||||
|
||||
STORE64H((uint64_t)seq, iv + 8);
|
||||
|
||||
memset(&session, 0, sizeof(session));
|
||||
session.cipher = CRYPTO_CHACHA20;
|
||||
session.key = (caddr_t)key;
|
||||
session.keylen = CHACHA20_KEY_LEN;
|
||||
if (ioctl(cfd, CIOCGSESSION, &session) < 0)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
memset(&cryp, 0, sizeof(cryp));
|
||||
cryp.ses = session.ses;
|
||||
cryp.op = COP_ENCRYPT;
|
||||
cryp.len = len;
|
||||
cryp.src = (caddr_t)in;
|
||||
cryp.dst = (caddr_t)out;
|
||||
cryp.iv = (caddr_t)iv;
|
||||
cryp.ivlen = sizeof(iv);
|
||||
if (ioctl(cfd, CIOCCRYPT, &cryp) == 0)
|
||||
{
|
||||
ret = CRYPT_OK;
|
||||
}
|
||||
|
||||
ioctl(cfd, CIOCFSESSION, &session.ses);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dropbear_poly1305(FAR const unsigned char *key,
|
||||
FAR const unsigned char *in, size_t len,
|
||||
FAR unsigned char *tag)
|
||||
{
|
||||
struct session_op session;
|
||||
struct crypt_op cryp;
|
||||
int cfd;
|
||||
int ret = CRYPT_ERROR;
|
||||
|
||||
cfd = dropbear_cryptodev_fd();
|
||||
if (cfd < 0)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
memset(&session, 0, sizeof(session));
|
||||
session.mac = CRYPTO_POLY1305;
|
||||
session.mackey = (caddr_t)key;
|
||||
session.mackeylen = POLY1305_KEY_LEN;
|
||||
if (ioctl(cfd, CIOCGSESSION, &session) < 0)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
memset(&cryp, 0, sizeof(cryp));
|
||||
cryp.ses = session.ses;
|
||||
cryp.op = COP_ENCRYPT;
|
||||
cryp.flags = COP_FLAG_UPDATE;
|
||||
cryp.len = len;
|
||||
cryp.src = (caddr_t)in;
|
||||
if (ioctl(cfd, CIOCCRYPT, &cryp) == 0)
|
||||
{
|
||||
cryp.flags = 0;
|
||||
cryp.len = 0;
|
||||
cryp.mac = (caddr_t)tag;
|
||||
if (ioctl(cfd, CIOCCRYPT, &cryp) == 0)
|
||||
{
|
||||
ret = CRYPT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
ioctl(cfd, CIOCFSESSION, &session.ses);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dropbear_chachapoly_start(int cipher,
|
||||
FAR const unsigned char *iv,
|
||||
FAR const unsigned char *key,
|
||||
int keylen, int num_rounds,
|
||||
FAR dropbear_chachapoly_state *state)
|
||||
{
|
||||
UNUSED(cipher);
|
||||
UNUSED(iv);
|
||||
|
||||
if (keylen != CHACHA20_KEY_LEN * 2 || num_rounds != 0)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
if (dropbear_cryptodev_fd() < 0)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
memcpy(state->key_main, key, CHACHA20_KEY_LEN);
|
||||
memcpy(state->key_header, key + CHACHA20_KEY_LEN, CHACHA20_KEY_LEN);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
static int dropbear_chachapoly_crypt(unsigned int seq,
|
||||
FAR const unsigned char *in,
|
||||
FAR unsigned char *out,
|
||||
unsigned long len, unsigned long taglen,
|
||||
FAR dropbear_chachapoly_state *state,
|
||||
int direction)
|
||||
{
|
||||
unsigned char key[POLY1305_KEY_LEN];
|
||||
unsigned char tag[POLY1305_TAG_LEN];
|
||||
unsigned char zero[POLY1305_KEY_LEN];
|
||||
int ret = CRYPT_ERROR;
|
||||
|
||||
if (len < 4 || taglen != POLY1305_TAG_LEN)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
memset(zero, 0, sizeof(zero));
|
||||
if (dropbear_chacha(state->key_main, seq, 0, zero, key,
|
||||
sizeof(key)) != CRYPT_OK)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (direction == LTC_DECRYPT)
|
||||
{
|
||||
if (dropbear_poly1305(key, in, len, tag) != CRYPT_OK)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (constant_time_memcmp(in + len, tag, sizeof(tag)) != 0)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (dropbear_chacha(state->key_header, seq, 0, in, out, 4) != CRYPT_OK)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dropbear_chacha(state->key_main, seq, 1, in + 4, out + 4,
|
||||
len - 4) != CRYPT_OK)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (direction == LTC_ENCRYPT)
|
||||
{
|
||||
if (dropbear_poly1305(key, out, len, out + len) != CRYPT_OK)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = CRYPT_OK;
|
||||
|
||||
out:
|
||||
zeromem(key, sizeof(key));
|
||||
zeromem(tag, sizeof(tag));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
dropbear_chachapoly_getlength(unsigned int seq, FAR const unsigned char *in,
|
||||
FAR unsigned int *outlen, unsigned long len,
|
||||
FAR dropbear_chachapoly_state *state)
|
||||
{
|
||||
unsigned char buf[4];
|
||||
|
||||
if (len < sizeof(buf))
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
if (dropbear_chacha(state->key_header, seq, 0, in, buf,
|
||||
sizeof(buf)) != CRYPT_OK)
|
||||
{
|
||||
return CRYPT_ERROR;
|
||||
}
|
||||
|
||||
LOAD32H(*outlen, buf);
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct dropbear_cipher_mode dropbear_mode_chachapoly =
|
||||
{
|
||||
(void *)dropbear_chachapoly_start,
|
||||
NULL,
|
||||
NULL,
|
||||
(void *)dropbear_chachapoly_crypt,
|
||||
(void *)dropbear_chachapoly_getlength,
|
||||
&g_dropbear_chachapoly_mac
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue