Skip to content

Commit aea1100

Browse files
committed
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 <moura.fmo@gmail.com>
1 parent 01c6a60 commit aea1100

4 files changed

Lines changed: 257 additions & 2 deletions

File tree

netutils/dropbear/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ if(CONFIG_NETUTILS_DROPBEAR)
135135
file(GLOB_RECURSE LIBTOMCRYPT_SRCS CONFIGURE_DEPENDS
136136
"${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtomcrypt/src/*.c")
137137
list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/prngs/sober128tab\\.c$")
138+
139+
# Drop the bundled libtomcrypt HMAC modules replaced by the NuttX adapter.
140+
list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/mac/hmac/hmac_init\\.c$")
141+
list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/mac/hmac/hmac_process\\.c$")
142+
list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/mac/hmac/hmac_done\\.c$")
143+
list(APPEND DROPBEAR_SRCS port/dropbear_ltc_hmac_sha256.c)
144+
138145
list(APPEND DROPBEAR_SRCS ${LIBTOMCRYPT_SRCS})
139146

140147
if(CONFIG_NETUTILS_DROPBEAR_SCP)

netutils/dropbear/Kconfig

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,24 @@ menuconfig NETUTILS_DROPBEAR
1919
depends on DEV_URANDOM
2020
depends on LIBC_NETDB
2121
depends on LIBC_GAISTRERROR
22-
select CRYPTO
23-
select CRYPTO_RANDOM_POOL
22+
depends on CRYPTO
23+
depends on CRYPTO_RANDOM_POOL
24+
depends on ALLOW_BSD_COMPONENTS
25+
depends on CRYPTO_CRYPTODEV
26+
depends on CRYPTO_CRYPTODEV_SOFTWARE_CRYPTO
2427
---help---
2528
Enable a minimal Dropbear SSH server port for NuttX. This initial
2629
port is based on the ESP-IDF MCU test port and provides a single
2730
foreground SSH server process with SSH sessions backed by NSH.
2831

32+
The port computes the hmac-sha2-256 packet MAC through the NuttX
33+
crypto device (/dev/crypto, CRYPTO_SHA2_256_HMAC) instead of the
34+
bundled libtomcrypt implementation, which is dropped from the
35+
build. The SHA-256 hash descriptor itself stays in the
36+
application: Dropbear's key derivation clones partially-updated
37+
hash states (hashkeys() in common-kex.c), which cannot be
38+
represented by a kernel crypto session.
39+
2940
if NETUTILS_DROPBEAR
3041

3142
config NETUTILS_DROPBEAR_STACKSIZE

netutils/dropbear/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,16 @@ CSRCS += \
119119
TOMMATH_SRCS = $(shell if [ -d "$(DROPBEAR_UNPACKNAME)/libtommath" ]; then find "$(DROPBEAR_UNPACKNAME)/libtommath" -name "*.c"; fi)
120120
TOMCRYPT_SRCS = $(shell if [ -d "$(DROPBEAR_UNPACKNAME)/libtomcrypt/src" ]; then find "$(DROPBEAR_UNPACKNAME)/libtomcrypt/src" -name "*.c" ! -name "sober128tab.c"; fi)
121121

122+
# Drop the bundled libtomcrypt HMAC modules replaced by the NuttX adapter.
123+
124+
TOMCRYPT_SRCS := $(filter-out \
125+
%/mac/hmac/hmac_init.c \
126+
%/mac/hmac/hmac_process.c \
127+
%/mac/hmac/hmac_done.c, \
128+
$(TOMCRYPT_SRCS))
129+
130+
CSRCS += port/dropbear_ltc_hmac_sha256.c
131+
122132
CSRCS += $(TOMMATH_SRCS)
123133
CSRCS += $(TOMCRYPT_SRCS)
124134

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/****************************************************************************
2+
* apps/netutils/dropbear/port/dropbear_ltc_hmac_sha256.c
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one or more
7+
* contributor license agreements. See the NOTICE file distributed with
8+
* this work for additional information regarding copyright ownership. The
9+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
* "License"); you may not use this file except in compliance with the
11+
* License. You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
* License for the specific language governing permissions and limitations
19+
* under the License.
20+
*
21+
****************************************************************************/
22+
23+
/* LibTomCrypt-compatible incremental HMAC API backed by a
24+
* CRYPTO_SHA2_256_HMAC /dev/crypto session (hmac-sha2-256, the only MAC the
25+
* NuttX Dropbear configuration enables): init opens the session, process
26+
* feeds data with COP_FLAG_UPDATE, done reads the tag and frees the session.
27+
*/
28+
29+
/****************************************************************************
30+
* Included Files
31+
****************************************************************************/
32+
33+
#include "includes.h"
34+
35+
#include <sys/ioctl.h>
36+
#include <fcntl.h>
37+
#include <string.h>
38+
#include <unistd.h>
39+
40+
#include <crypto/cryptodev.h>
41+
42+
/****************************************************************************
43+
* Pre-processor Definitions
44+
****************************************************************************/
45+
46+
#define DROPBEAR_HMAC_SHA256_DIGESTLEN 32
47+
#define DROPBEAR_HMAC_SHA256_BLOCKLEN 64
48+
49+
/* Stash the /dev/crypto session id in the unused md hash-state buffer so the
50+
* upstream hmac_state needs no patch (hash index uses the existing field).
51+
*/
52+
53+
#define HMAC_SES(h) (*(FAR unsigned int *)&(h)->md)
54+
55+
/****************************************************************************
56+
* Private Data
57+
****************************************************************************/
58+
59+
static int g_dropbear_hmac_cryptofd = -1;
60+
61+
/****************************************************************************
62+
* Private Functions
63+
****************************************************************************/
64+
65+
static int dropbear_hmac_cryptodev_fd(void)
66+
{
67+
int fd;
68+
int cfd;
69+
70+
if (g_dropbear_hmac_cryptofd >= 0)
71+
{
72+
return g_dropbear_hmac_cryptofd;
73+
}
74+
75+
fd = open("/dev/crypto", O_RDWR);
76+
if (fd < 0)
77+
{
78+
return -1;
79+
}
80+
81+
if (ioctl(fd, CRIOGET, &cfd) < 0)
82+
{
83+
close(fd);
84+
return -1;
85+
}
86+
87+
close(fd);
88+
g_dropbear_hmac_cryptofd = cfd;
89+
return g_dropbear_hmac_cryptofd;
90+
}
91+
92+
static int dropbear_hmac_hash_is_sha256(int hash)
93+
{
94+
int ret;
95+
96+
ret = hash_is_valid(hash);
97+
if (ret != CRYPT_OK)
98+
{
99+
return ret;
100+
}
101+
102+
if (hash_descriptor[hash].hashsize != DROPBEAR_HMAC_SHA256_DIGESTLEN ||
103+
hash_descriptor[hash].blocksize != DROPBEAR_HMAC_SHA256_BLOCKLEN)
104+
{
105+
return CRYPT_INVALID_HASH;
106+
}
107+
108+
return CRYPT_OK;
109+
}
110+
111+
/****************************************************************************
112+
* Public Functions
113+
****************************************************************************/
114+
115+
int hmac_init(hmac_state *hmac, int hash, const unsigned char *key,
116+
unsigned long keylen)
117+
{
118+
struct session_op session;
119+
int cfd;
120+
int ret;
121+
122+
LTC_ARGCHK(hmac != NULL);
123+
LTC_ARGCHK(key != NULL);
124+
125+
if (keylen == 0)
126+
{
127+
return CRYPT_INVALID_KEYSIZE;
128+
}
129+
130+
ret = dropbear_hmac_hash_is_sha256(hash);
131+
if (ret != CRYPT_OK)
132+
{
133+
return ret;
134+
}
135+
136+
cfd = dropbear_hmac_cryptodev_fd();
137+
if (cfd < 0)
138+
{
139+
return CRYPT_ERROR;
140+
}
141+
142+
memset(&session, 0, sizeof(session));
143+
session.mac = CRYPTO_SHA2_256_HMAC;
144+
session.mackey = (caddr_t)key;
145+
session.mackeylen = keylen;
146+
if (ioctl(cfd, CIOCGSESSION, &session) < 0)
147+
{
148+
return CRYPT_ERROR;
149+
}
150+
151+
hmac->hash = hash;
152+
HMAC_SES(hmac) = session.ses;
153+
return CRYPT_OK;
154+
}
155+
156+
int hmac_process(hmac_state *hmac, const unsigned char *in,
157+
unsigned long inlen)
158+
{
159+
struct crypt_op cryp;
160+
int cfd;
161+
162+
LTC_ARGCHK(hmac != NULL);
163+
LTC_ARGCHK(in != NULL || inlen == 0);
164+
165+
cfd = dropbear_hmac_cryptodev_fd();
166+
if (cfd < 0)
167+
{
168+
return CRYPT_ERROR;
169+
}
170+
171+
memset(&cryp, 0, sizeof(cryp));
172+
cryp.ses = HMAC_SES(hmac);
173+
cryp.op = COP_ENCRYPT;
174+
cryp.flags = COP_FLAG_UPDATE;
175+
cryp.len = inlen;
176+
cryp.src = (caddr_t)in;
177+
if (ioctl(cfd, CIOCCRYPT, &cryp) < 0)
178+
{
179+
return CRYPT_ERROR;
180+
}
181+
182+
return CRYPT_OK;
183+
}
184+
185+
int hmac_done(hmac_state *hmac, unsigned char *out, unsigned long *outlen)
186+
{
187+
unsigned char digest[DROPBEAR_HMAC_SHA256_DIGESTLEN];
188+
struct crypt_op cryp;
189+
unsigned long copylen;
190+
int cfd;
191+
int ret = CRYPT_ERROR;
192+
193+
LTC_ARGCHK(hmac != NULL);
194+
LTC_ARGCHK(out != NULL);
195+
LTC_ARGCHK(outlen != NULL);
196+
197+
cfd = dropbear_hmac_cryptodev_fd();
198+
if (cfd < 0)
199+
{
200+
goto out;
201+
}
202+
203+
memset(&cryp, 0, sizeof(cryp));
204+
cryp.ses = HMAC_SES(hmac);
205+
cryp.op = COP_ENCRYPT;
206+
cryp.len = 0;
207+
cryp.mac = (caddr_t)digest;
208+
if (ioctl(cfd, CIOCCRYPT, &cryp) < 0)
209+
{
210+
goto out;
211+
}
212+
213+
copylen = MIN(*outlen, DROPBEAR_HMAC_SHA256_DIGESTLEN);
214+
memcpy(out, digest, copylen);
215+
*outlen = copylen;
216+
ret = CRYPT_OK;
217+
218+
out:
219+
if (cfd >= 0)
220+
{
221+
ioctl(cfd, CIOCFSESSION, &HMAC_SES(hmac));
222+
}
223+
224+
zeromem(digest, sizeof(digest));
225+
zeromem(hmac, sizeof(*hmac));
226+
return ret;
227+
}

0 commit comments

Comments
 (0)