Add DH Group 16 and HMAC-SHA2-512

This adds the `diffie-hellman-group16-sha512` key exchange and
`hmac-sha2-512` mac support.

Echoserver can now take `-x` for key exchange and `-m` for mac setting,
 and `-c` for cipher so that this can be used in the test suite.
pull/767/head
Andrew Hutchings 2025-02-04 07:49:50 +00:00
parent 60f90dfad2
commit f73a76e064
10 changed files with 602 additions and 8 deletions

View File

@ -2369,7 +2369,10 @@ static void ShowUsage(void)
#ifdef WOLFSSH_CERTS
printf(" -a <file> load in a root CA certificate file\n");
#endif
printf(" -k set the list of key algos to use\n");
printf(" -k <list> set the comma separated list of key algos to use\n");
printf(" -x <list> set the comma separated list of key exchange algos "
"to use\n");
printf(" -m <list> set the comma separated list of mac algos to use\n");
printf(" -b <num> test user auth would block\n");
}
@ -2412,6 +2415,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK;
word32 threadCount = 0;
const char* keyList = NULL;
const char* kexList = NULL;
const char* macList = NULL;
const char* cipherList = NULL;
ES_HEAP_HINT* heap = NULL;
int multipleConnections = 1;
int userEcc = 0;
@ -2435,7 +2441,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
kbAuthData.promptCount = 0;
if (argc > 0) {
const char* optlist = "?1a:d:efEp:R:Ni:j:i:I:J:K:P:k:b:";
const char* optlist = "?1a:d:efEp:R:Ni:j:i:I:J:K:P:k:b:x:m:c:";
myoptind = 0;
while ((ch = mygetopt(argc, argv, optlist)) != -1) {
switch (ch) {
@ -2527,6 +2533,18 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
userAuthWouldBlock = atoi(myoptarg);
break;
case 'x':
kexList = myoptarg;
break;
case 'm':
macList = myoptarg;
break;
case 'c':
cipherList = myoptarg;
break;
default:
ShowUsage();
serverArgs->return_code = MY_EX_USAGE;
@ -2585,6 +2603,24 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
}
}
if (kexList) {
if (wolfSSH_CTX_SetAlgoListKex(ctx, kexList) != WS_SUCCESS) {
ES_ERROR("Error setting kex list.\n");
}
}
if (macList) {
if (wolfSSH_CTX_SetAlgoListMac(ctx, macList) != WS_SUCCESS) {
ES_ERROR("Error setting mac list.\n");
}
}
if (cipherList) {
if (wolfSSH_CTX_SetAlgoListCipher(ctx, cipherList) != WS_SUCCESS) {
ES_ERROR("Error setting cipher list.\n");
}
}
WMEMSET(&pwMapList, 0, sizeof(pwMapList));
if (serverArgs->user_auth == NULL)
wolfSSH_SetUserAuth(ctx, wsUserAuth);

View File

@ -93,6 +93,9 @@ Flags:
WOLFSSH_NO_HMAC_SHA2_256
Set when HMAC or SHA2-256 are disabled. Set to disable HMAC-SHA2-256
support.
WOLFSSH_NO_HMAC_SHA2_512
Set when HMAC or SHA2-512 are disabled. Set to disable HMAC-SHA2-512
support.
WOLFSSH_NO_DH_GROUP1_SHA1
Set when DH or SHA1 are disabled. Set to disable use of DH (Oakley 1) and
SHA1 support.
@ -102,6 +105,9 @@ Flags:
WOLFSSH_NO_DH_GROUP14_SHA256
Set when DH or SHA256 are disabled. Set to disable use of DH (Oakley 14)
and SHA256 support.
WOLFSSH_NO_DH_GROUP16_SHA512
Set when DH or SHA512 are disabled. Set to disable use of DH (Oakley 16)
and SHA512 support.
WOLFSSH_NO_DH_GEX_SHA256
Set when DH or SHA2-256 are disabled. Set to disable use of DH group
exchange and SHA2-256 support.
@ -691,6 +697,9 @@ static const char cannedKexAlgoNames[] =
#if !defined(WOLFSSH_NO_DH_GROUP14_SHA256)
"diffie-hellman-group14-sha256,"
#endif
#if !defined(WOLFSSH_NO_DH_GROUP16_SHA512)
"diffie-hellman-group16-sha512,"
#endif
#if !defined(WOLFSSH_NO_DH_GEX_SHA256)
"diffie-hellman-group-exchange-sha256,"
#endif
@ -798,6 +807,9 @@ static const char cannedMacAlgoNames[] =
#if !defined(WOLFSSH_NO_HMAC_SHA2_256)
"hmac-sha2-256,"
#endif
#if !defined(WOLFSSH_NO_HMAC_SHA2_512)
"hmac-sha2-512,"
#endif
#if defined(WOLFSSH_NO_SHA1_SOFT_DISABLE)
#if !defined(WOLFSSH_NO_HMAC_SHA1_96)
"hmac-sha1-96,"
@ -2444,6 +2456,9 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_HMAC_SHA2_256
{ ID_HMAC_SHA2_256, TYPE_MAC, "hmac-sha2-256" },
#endif
#ifndef WOLFSSH_NO_HMAC_SHA2_512
{ ID_HMAC_SHA2_512, TYPE_MAC, "hmac-sha2-512" },
#endif
/* Key Exchange IDs */
#ifndef WOLFSSH_NO_DH_GROUP1_SHA1
@ -2455,6 +2470,9 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_DH_GROUP14_SHA256
{ ID_DH_GROUP14_SHA256, TYPE_KEX, "diffie-hellman-group14-sha256" },
#endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
{ ID_DH_GROUP16_SHA512, TYPE_KEX, "diffie-hellman-group16-sha512" },
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256
{ ID_DH_GEX_SHA256, TYPE_KEX, "diffie-hellman-group-exchange-sha256" },
#endif
@ -3626,6 +3644,10 @@ static INLINE byte MacSzForId(byte id)
#ifndef WOLFSSH_NO_HMAC_SHA2_256
case ID_HMAC_SHA2_256:
return WC_SHA256_DIGEST_SIZE;
#endif
#ifndef WOLFSSH_NO_HMAC_SHA2_512
case ID_HMAC_SHA2_512:
return WC_SHA512_DIGEST_SIZE;
#endif
default:
return 0;
@ -3648,6 +3670,10 @@ static INLINE byte KeySzForId(byte id)
case ID_HMAC_SHA2_256:
return WC_SHA256_DIGEST_SIZE;
#endif
#ifndef WOLFSSH_NO_HMAC_SHA2_512
case ID_HMAC_SHA2_512:
return WC_SHA512_DIGEST_SIZE;
#endif
#ifndef WOLFSSH_NO_AES_CBC
case ID_AES128_CBC:
return AES_128_KEY_SIZE;
@ -3760,6 +3786,10 @@ enum wc_HashType HashForId(byte id)
#endif
return WC_HASH_TYPE_SHA512;
#endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
case ID_DH_GROUP16_SHA512:
return WC_HASH_TYPE_SHA512;
#endif
#ifndef WOLFSSH_NO_RSA_SHA2_512
case ID_RSA_SHA2_512:
return WC_HASH_TYPE_SHA512;
@ -4350,6 +4380,76 @@ static const byte dhPrimeGroup14[] = {
static const word32 dhPrimeGroup14Sz = (word32)sizeof(dhPrimeGroup14);
#endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
static const byte dhPrimeGroup16[] = {
/* SSH DH Group 16 (Oakley Group 16, 4096-bit MODP Group, RFC 3526) */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static const word32 dhPrimeGroup16Sz = (word32)sizeof(dhPrimeGroup16);
#endif
static int DoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
{
@ -9513,6 +9613,27 @@ static INLINE int CreateMac(WOLFSSH* ssh, const byte* in, word32 inSz,
}
break;
#ifndef WOLFSSH_NO_HMAC_SHA2_512
case ID_HMAC_SHA2_512:
{
Hmac hmac;
ret = wc_HmacInit(&hmac, ssh->ctx->heap, INVALID_DEVID);
if (ret == WS_SUCCESS)
ret = wc_HmacSetKey(&hmac, WC_SHA512,
ssh->keys.macKey,
ssh->keys.macKeySz);
if (ret == WS_SUCCESS)
ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
if (ret == WS_SUCCESS)
ret = wc_HmacUpdate(&hmac, in, inSz);
if (ret == WS_SUCCESS)
ret = wc_HmacFinal(&hmac, mac);
wc_HmacFree(&hmac);
}
break;
#endif
default:
WLOG(WS_LOG_DEBUG, "Invalid Mac ID");
ret = WS_FATAL_ERROR;
@ -9575,6 +9696,19 @@ static INLINE int VerifyMac(WOLFSSH* ssh, const byte* in, word32 inSz,
ret = WS_VERIFY_MAC_E;
break;
case ID_HMAC_SHA2_512:
ret = wc_HmacSetKey(&hmac, WC_SHA512, ssh->peerKeys.macKey,
ssh->peerKeys.macKeySz);
if (ret == WS_SUCCESS)
ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
if (ret == WS_SUCCESS)
ret = wc_HmacUpdate(&hmac, in, inSz);
if (ret == WS_SUCCESS)
ret = wc_HmacFinal(&hmac, checkMac);
if (ConstantCompare(checkMac, mac, ssh->peerMacSz) != 0)
ret = WS_VERIFY_MAC_E;
break;
default:
ret = WS_INVALID_ALGO_ID;
}
@ -9714,6 +9848,8 @@ int DoReceive(WOLFSSH* ssh)
/* Peek at the packet_length field. */
ato32(ssh->inputBuffer.buffer + ssh->inputBuffer.idx, &ssh->curSz);
if (ssh->curSz > MAX_PACKET_SZ - (word32)peerMacSz - UINT32_SZ) {
WLOG(WS_LOG_DEBUG, "Packet length overflow: size = %u",
ssh->curSz);
ssh->error = WS_OVERFLOW_E;
return WS_FATAL_ERROR;
}
@ -10341,6 +10477,8 @@ struct wolfSSH_sigKeyBlockFull {
/* Size of Kyber public key (bigger than ciphertext) and some extra for the
* ECC hybrid component. */
#define KEX_F_SIZE 1024
#elif !defined(WOLFSSH_NO_DH_GROUP16_SHA512)
#define KEX_F_SIZE (512 + 1)
#else
#define KEX_F_SIZE (256 + 1)
#endif
@ -10480,6 +10618,14 @@ static int GetDHPrimeGroup(int kexId, const byte** primeGroup,
*generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
case ID_DH_GROUP16_SHA512:
*primeGroup = dhPrimeGroup16;
*primeGroupSz = dhPrimeGroup16Sz;
*generator = dhGenerator;
*generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256:
*primeGroup = dhPrimeGroup14;
@ -11764,6 +11910,12 @@ int SendKexDhReply(WOLFSSH* ssh)
msgId = MSGID_KEXDH_REPLY;
break;
#endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
case ID_DH_GROUP16_SHA512:
useDh = 1;
msgId = MSGID_KEXDH_REPLY;
break;
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256:
useDh = 1;
@ -12333,6 +12485,15 @@ int SendKexDhInit(WOLFSSH* ssh)
generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
case ID_DH_GROUP16_SHA512:
ssh->handshake->useDh = 1;
primeGroup = dhPrimeGroup16;
primeGroupSz = dhPrimeGroup16Sz;
generator = dhGenerator;
generatorSz = dhGeneratorSz;
break;
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256:
ssh->handshake->useDh = 1;

View File

@ -428,7 +428,7 @@ int wsEmbedSend(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
return WS_CBIO_ERR_CONN_CLOSE;
}
else {
WLOG(WS_LOG_DEBUG," General error");
WLOG(WS_LOG_DEBUG," General error %d", err);
return WS_CBIO_ERR_GENERAL;
}
}

View File

@ -2961,6 +2961,9 @@ static const char* MacNameForId(byte macid, byte cipherid)
case ID_HMAC_SHA2_256:
return "HMAC-SHA-256";
case ID_HMAC_SHA2_512:
return "HMAC-SHA-512";
}
}
else {
@ -3050,6 +3053,11 @@ size_t wolfSSH_GetText(WOLFSSH *ssh, WS_Text id, char *str, size_t strSz)
ssh->primeGroupSz*8, 14);
break;
case ID_DH_GROUP16_SHA512:
ret = WSNPRINTF(str, strSz, standard_dh_format,
ssh->primeGroupSz*8, 16);
break;
case ID_DH_GEX_SHA256:
ret = WSNPRINTF(str, strSz,
"%d-bit Diffie-Hellman with server-supplied group",

View File

@ -3,9 +3,7 @@
# All paths should be given relative to the root
check_PROGRAMS += tests/unit.test tests/api.test \
tests/testsuite.test tests/auth.test
noinst_PROGRAMS += tests/unit.test tests/api.test \
tests/testsuite.test tests/auth.test
tests/testsuite.test tests/auth.test tests/kex.test
tests_unit_test_SOURCES = tests/unit.c tests/unit.h
tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER
@ -131,3 +129,36 @@ endif
tests_auth_test_LDADD = src/libwolfssh.la
tests_auth_test_DEPENDENCIES = src/libwolfssh.la
tests_kex_test_SOURCES = tests/kex.c tests/kex.h \
examples/echoserver/echoserver.c \
examples/client/client.c \
examples/client/common.c \
examples/client/common.h
tests_kex_test_CPPFLAGS = -DNO_MAIN_DRIVER
if BUILD_KEYGEN
tests_kex_test_CPPFLAGS += -DWOLFSSH_KEYGEN
endif
if BUILD_SCP
tests_kex_test_CPPFLAGS += -DWOLFSSH_SCP
endif
if BUILD_SFTP
tests_kex_test_CPPFLAGS += -DWOLFSSH_SFTP
endif
if BUILD_TERM
tests_kex_test_CPPFLAGS += -DWOLFSSH_TERM
endif
if BUILD_SHELL
tests_kex_test_CPPFLAGS += -DWOLFSSH_SHELL
endif
if BUILD_AGENT
tests_kex_test_CPPFLAGS += -DWOLFSSH_AGENT
endif
if BUILD_FWD
tests_kex_test_CPPFLAGS += -DWOLFSSH_FWD
endif
if BUILD_CERTS
tests_kex_test_CPPFLAGS += -DWOLFSSH_CERTS
endif
tests_kex_test_LDADD = src/libwolfssh.la
tests_kex_test_DEPENDENCIES = src/libwolfssh.la

317
tests/kex.c 100644
View File

@ -0,0 +1,317 @@
/* kex.c
*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfSSH.
*
* wolfSSH is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#else
#include <wolfssl/options.h>
#endif
#define WOLFSSH_TEST_CLIENT
#define WOLFSSH_TEST_SERVER
#ifndef SINGLE_THREADED
#define WOLFSSH_TEST_THREADING
#endif
#define WOLFSSH_TEST_LOCKING
#include <wolfssh/settings.h>
#include <wolfssh/ssh.h>
#include <wolfssh/internal.h>
#include <wolfssh/test.h>
#include "examples/echoserver/echoserver.h"
#include "examples/client/client.h"
#include "tests/kex.h"
#ifdef HAVE_FIPS
#include <wolfssl/wolfcrypt/fips_test.h>
#endif
#ifndef WOLFSSH_NO_ABORT
#define WABORT() abort()
#else
#define WABORT()
#endif
#define PrintError(description, result) do { \
printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \
printf("\n expected: "); printf description; \
printf("\n result: "); printf result; printf("\n\n"); \
} while(0)
#ifdef WOLFSSH_ZEPHYR
#define Fail(description, result) do { \
PrintError(description, result); \
WABORT(); \
} while(0)
#else
#define Fail(description, result) do { \
PrintError(description, result); \
WFFLUSH(stdout); \
WABORT(); \
} while(0)
#endif
#define Assert(test, description, result) if (!(test)) Fail(description, result)
#define AssertTrue(x) Assert( (x), ("%s is true", #x), (#x " => FALSE"))
#define AssertFalse(x) Assert(!(x), ("%s is false", #x), (#x " => TRUE"))
#define AssertNotNull(x) Assert( (x), ("%s is not null", #x), (#x " => NULL"))
#define AssertNull(x) do { \
PEDANTIC_EXTENSION void* _x = (void*)(x); \
\
Assert(!_x, ("%s is null", #x), (#x " => %p", _x)); \
} while(0)
#define AssertInt(x, y, op, er) do { \
int _x = (int)(x); \
int _y = (int)(y); \
Assert(_x op _y, ("%s " #op " %s", #x, #y), ("%d " #er " %d", _x, _y)); \
} while(0)
#define AssertIntEQ(x, y) AssertInt(x, y, ==, !=)
#define AssertIntNE(x, y) AssertInt(x, y, !=, ==)
#define AssertIntGT(x, y) AssertInt(x, y, >, <=)
#define AssertIntLT(x, y) AssertInt(x, y, <, >=)
#define AssertIntGE(x, y) AssertInt(x, y, >=, <)
#define AssertIntLE(x, y) AssertInt(x, y, <=, >)
#define AssertStr(x, y, op, er) do { \
const char* _x = (const char*)(x); \
const char* _y = (const char*)(y); \
int _z = (_x && _y) ? strcmp(_x, _y) : -1; \
Assert(_z op 0, ("%s " #op " %s", #x, #y), \
("\"%s\" " #er " \"%s\"", _x, _y));\
} while(0)
#define AssertStrEQ(x, y) AssertStr(x, y, ==, !=)
#define AssertStrNE(x, y) AssertStr(x, y, !=, ==)
#define AssertStrGT(x, y) AssertStr(x, y, >, <=)
#define AssertStrLT(x, y) AssertStr(x, y, <, >=)
#define AssertStrGE(x, y) AssertStr(x, y, >=, <)
#define AssertStrLE(x, y) AssertStr(x, y, <=, >)
#define AssertPtr(x, y, op, er) do { \
PRAGMA_GCC_DIAG_PUSH \
/* remarkably, without this inhibition, */ \
/* the _Pragma()s make the declarations warn. */ \
PRAGMA_GCC("GCC diagnostic ignored \"-Wdeclaration-after-statement\"") \
/* inhibit "ISO C forbids conversion of function pointer */ \
/* to object pointer type [-Werror=pedantic]" */ \
PRAGMA_GCC("GCC diagnostic ignored \"-Wpedantic\"") \
void* _x = (void*)(x); \
void* _y = (void*)(y); \
Assert(_x op _y, ("%s " #op " %s", #x, #y), ("%p " #er " %p", _x, _y)); \
PRAGMA_GCC_DIAG_POP; \
} while(0)
#define AssertPtrEq(x, y) AssertPtr(x, y, ==, !=)
#define AssertPtrNE(x, y) AssertPtr(x, y, !=, ==)
#define AssertPtrGT(x, y) AssertPtr(x, y, >, <=)
#define AssertPtrLT(x, y) AssertPtr(x, y, <, >=)
#define AssertPtrGE(x, y) AssertPtr(x, y, >=, <)
#define AssertPtrLE(x, y) AssertPtr(x, y, <=, >)
#if !defined(NO_WOLFSSH_SERVER) && !defined(NO_WOLFSSH_CLIENT) && \
!defined(SINGLE_THREADED) && !defined(WOLFSSH_TEST_BLOCK) && \
!defined(WOLFSSH_NO_DH_GROUP16_SHA512) && !defined(WOLFSSH_NO_HMAC_SHA2_512)
static int tsClientUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
{
static char password[] = "upthehill";
(void)authType;
(void)ctx;
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
authData->sf.password.password = (byte*)password;
authData->sf.password.passwordSz = (word32)WSTRLEN(password);
}
else {
return WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
}
return WOLFSSH_USERAUTH_SUCCESS;
}
#define NUMARGS 12
#define ARGLEN 32
static int wolfSSH_wolfSSH_Group16_512(void)
{
tcp_ready ready;
THREAD_TYPE serverThread;
func_args serverArgs;
func_args clientArgs;
char sA[NUMARGS][ARGLEN];
char *serverArgv[NUMARGS] =
{ sA[0], sA[1], sA[2], sA[3], sA[4], sA[5], sA[6], sA[7], sA[8], sA[9],
sA[10], sA[11] };
char cA[NUMARGS][ARGLEN];
char *clientArgv[NUMARGS] =
{ cA[0], cA[1], cA[2], cA[3], cA[4] };
int serverArgc = 0;
int clientArgc = 0;
WSTARTTCP();
#if defined(DEBUG_WOLFSSH)
wolfSSH_Debugging_ON();
#endif
wolfSSH_Init();
#if defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,2)
{
int i;
for (i = 0; i < FIPS_CAST_COUNT; i++) {
wc_RunCast_fips(i);
}
}
#endif /* HAVE_FIPS */
#if !defined(WOLFSSL_TIRTOS)
ChangeToWolfSshRoot();
#endif
InitTcpReady(&ready);
WSTRNCPY(serverArgv[serverArgc++], "echoserver", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "-1", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "-f", ARGLEN);
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR)
WSTRNCPY(serverArgv[serverArgc++], "-p", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "-0", ARGLEN);
#endif
WSTRNCPY(serverArgv[serverArgc++], "-x", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "diffie-hellman-group16-sha512", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "-m", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "hmac-sha2-512", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "-c", ARGLEN);
WSTRNCPY(serverArgv[serverArgc++], "aes256-cbc", ARGLEN);
serverArgs.argc = serverArgc;
serverArgs.argv = serverArgv;
serverArgs.return_code = EXIT_SUCCESS;
serverArgs.signal = &ready;
serverArgs.user_auth = NULL;
ThreadStart(echoserver_test, &serverArgs, &serverThread);
WaitTcpReady(&ready);
WSTRNCPY(cA[clientArgc++], "client", ARGLEN);
WSTRNCPY(cA[clientArgc++], "-u", ARGLEN);
WSTRNCPY(cA[clientArgc++], "jill", ARGLEN);
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR)
WSTRNCPY(cA[clientArgc++], "-p", ARGLEN);
WSNPRINTF(cA[clientArgc++], ARGLEN, "%d", ready.port);
#endif
clientArgs.argc = clientArgc;
clientArgs.argv = clientArgv;
clientArgs.return_code = EXIT_SUCCESS;
clientArgs.signal = &ready;
clientArgs.user_auth = tsClientUserAuth;
client_test(&clientArgs);
#ifdef WOLFSSH_ZEPHYR
/* Weird deadlock without this sleep */
k_sleep(Z_TIMEOUT_TICKS(100));
#endif
ThreadJoin(serverThread);
if (clientArgs.return_code == WS_SOCKET_ERROR_E) {
clientArgs.return_code = WS_SUCCESS;
}
if (serverArgs.return_code == WS_SOCKET_ERROR_E) {
serverArgs.return_code = WS_SUCCESS;
}
#if DEFAULT_HIGHWATER_MARK < 8000
if (serverArgs.return_code == WS_REKEYING) {
serverArgs.return_code = WS_SUCCESS;
}
if (serverArgs.return_code == WS_REKEYING) {
serverArgs.return_code = WS_SUCCESS;
}
#endif
/* Socket error may printf, but this is fine */
AssertIntEQ(WS_SUCCESS, clientArgs.return_code);
AssertIntEQ(WS_SUCCESS, serverArgs.return_code);
FreeTcpReady(&ready);
return EXIT_SUCCESS;
}
#endif
int wolfSSH_KexTest(int argc, char** argv)
{
(void)argc;
(void)argv;
#if defined(NO_WOLFSSH_SERVER) || defined(NO_WOLFSSH_CLIENT) || \
defined(SINGLE_THREADED) || defined(WOLFSSH_TEST_BLOCK)
return 77;
#else
AssertIntEQ(wolfSSH_Init(), WS_SUCCESS);
#if defined(FIPS_VERSION_GE) && FIPS_VERSION_GE(5,2)
{
int i;
for (i = 0; i < FIPS_CAST_COUNT; i++) {
AssertIntEQ(wc_RunCast_fips(i), WS_SUCCESS);
}
}
#endif /* HAVE_FIPS */
#if !defined(WOLFSSH_NO_DH_GROUP16_SHA512) && !defined(WOLFSSH_NO_HMAC_SHA2_512)
wolfSSH_wolfSSH_Group16_512();
#endif
AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS);
return 0;
#endif
}
#ifndef NO_TESTSUITE_MAIN_DRIVER
int main(int argc, char** argv)
{
return wolfSSH_KexTest(argc, argv);
}
int myoptind = 0;
char* myoptarg = NULL;
#endif /* !NO_TESTSUITE_MAIN_DRIVER */

26
tests/kex.h 100644
View File

@ -0,0 +1,26 @@
/* kex.h
*
* Copyright (C) 2025 wolfSSL Inc.
*
* This file is part of wolfSSH.
*
* wolfSSH is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WOLFSSH_TESTS_KEX_H_
#define _WOLFSSH_TESTS_KEX_H_
int wolfSSH_KexTest(int argc, char** argv);
#endif /* _WOLFSSH_TESTS_KEX_H_ */

View File

@ -125,9 +125,14 @@ extern "C" {
#undef WOLFSSH_NO_HMAC_SHA2_256
#define WOLFSSH_NO_HMAC_SHA2_256
#endif
#if defined(NO_HMAC) || defined(NO_SHA512)
#undef WOLFSSH_NO_HMAC_SHA2_512
#define WOLFSSH_NO_HMAC_SHA2_512
#endif
#if defined(WOLFSSH_NO_HMAC_SHA1) && \
defined(WOLFSSH_NO_HMAC_SHA1_96) && \
defined(WOLFSSH_NO_HMAC_SHA2_256)
defined(WOLFSSH_NO_HMAC_SHA2_256) && \
defined(WOLFSSH_NO_HMAC_SHA2_512)
#error "You need at least one MAC algorithm."
#endif
@ -144,6 +149,10 @@ extern "C" {
#undef WOLFSSH_NO_DH_GROUP14_SHA256
#define WOLFSSH_NO_DH_GROUP14_SHA256
#endif
#if defined(WOLFSSH_NO_DH) || defined(WOLFSSH_NO_SHA512)
#undef WOLFSSH_NO_DH_GROUP16_SHA512
#define WOLFSSH_NO_DH_GROUP16_SHA512
#endif
#if defined(WOLFSSH_NO_DH) || defined(NO_SHA256)
#undef WOLFSSH_NO_DH_GEX_SHA256
#define WOLFSSH_NO_DH_GEX_SHA256
@ -178,6 +187,7 @@ extern "C" {
#if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA256) && \
defined(WOLFSSH_NO_DH_GROUP16_SHA512) && \
defined(WOLFSSH_NO_DH_GEX_SHA256) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \
@ -190,6 +200,7 @@ extern "C" {
#if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA256) && \
defined(WOLFSSH_NO_DH_GROUP16_SHA512) && \
defined(WOLFSSH_NO_DH_GEX_SHA256)
#undef WOLFSSH_NO_DH
#define WOLFSSH_NO_DH
@ -313,11 +324,13 @@ enum {
ID_HMAC_SHA1,
ID_HMAC_SHA1_96,
ID_HMAC_SHA2_256,
ID_HMAC_SHA2_512,
/* Key Exchange IDs */
ID_DH_GROUP1_SHA1,
ID_DH_GROUP14_SHA1,
ID_DH_GROUP14_SHA256,
ID_DH_GROUP16_SHA512,
ID_DH_GEX_SHA256,
ID_ECDH_SHA2_NISTP256,
ID_ECDH_SHA2_NISTP384,
@ -391,7 +404,7 @@ enum NameIdType {
#define MAX_KEY_EXCHANGE 2
#define MAX_PUBLIC_KEY 1
#define MIN_RSA_SIG_SZ 2
#define MAX_HMAC_SZ WC_SHA256_DIGEST_SIZE
#define MAX_HMAC_SZ WC_SHA512_DIGEST_SIZE
#define MIN_BLOCK_SZ 8
#define COOKIE_SZ 16
#define PAD_LENGTH_SZ 1

View File

@ -38,6 +38,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_DATA_SIZE=256
# Logging
CONFIG_PRINTK=y

View File

@ -37,6 +37,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_DATA_SIZE=256
# Logging
CONFIG_PRINTK=y