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 #ifdef WOLFSSH_CERTS
printf(" -a <file> load in a root CA certificate file\n"); printf(" -a <file> load in a root CA certificate file\n");
#endif #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"); 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 defaultHighwater = EXAMPLE_HIGHWATER_MARK;
word32 threadCount = 0; word32 threadCount = 0;
const char* keyList = NULL; const char* keyList = NULL;
const char* kexList = NULL;
const char* macList = NULL;
const char* cipherList = NULL;
ES_HEAP_HINT* heap = NULL; ES_HEAP_HINT* heap = NULL;
int multipleConnections = 1; int multipleConnections = 1;
int userEcc = 0; int userEcc = 0;
@ -2435,7 +2441,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
kbAuthData.promptCount = 0; kbAuthData.promptCount = 0;
if (argc > 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; myoptind = 0;
while ((ch = mygetopt(argc, argv, optlist)) != -1) { while ((ch = mygetopt(argc, argv, optlist)) != -1) {
switch (ch) { switch (ch) {
@ -2527,6 +2533,18 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
userAuthWouldBlock = atoi(myoptarg); userAuthWouldBlock = atoi(myoptarg);
break; break;
case 'x':
kexList = myoptarg;
break;
case 'm':
macList = myoptarg;
break;
case 'c':
cipherList = myoptarg;
break;
default: default:
ShowUsage(); ShowUsage();
serverArgs->return_code = MY_EX_USAGE; 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)); WMEMSET(&pwMapList, 0, sizeof(pwMapList));
if (serverArgs->user_auth == NULL) if (serverArgs->user_auth == NULL)
wolfSSH_SetUserAuth(ctx, wsUserAuth); wolfSSH_SetUserAuth(ctx, wsUserAuth);

View File

@ -93,6 +93,9 @@ Flags:
WOLFSSH_NO_HMAC_SHA2_256 WOLFSSH_NO_HMAC_SHA2_256
Set when HMAC or SHA2-256 are disabled. Set to disable HMAC-SHA2-256 Set when HMAC or SHA2-256 are disabled. Set to disable HMAC-SHA2-256
support. 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 WOLFSSH_NO_DH_GROUP1_SHA1
Set when DH or SHA1 are disabled. Set to disable use of DH (Oakley 1) and Set when DH or SHA1 are disabled. Set to disable use of DH (Oakley 1) and
SHA1 support. SHA1 support.
@ -102,6 +105,9 @@ Flags:
WOLFSSH_NO_DH_GROUP14_SHA256 WOLFSSH_NO_DH_GROUP14_SHA256
Set when DH or SHA256 are disabled. Set to disable use of DH (Oakley 14) Set when DH or SHA256 are disabled. Set to disable use of DH (Oakley 14)
and SHA256 support. 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 WOLFSSH_NO_DH_GEX_SHA256
Set when DH or SHA2-256 are disabled. Set to disable use of DH group Set when DH or SHA2-256 are disabled. Set to disable use of DH group
exchange and SHA2-256 support. exchange and SHA2-256 support.
@ -691,6 +697,9 @@ static const char cannedKexAlgoNames[] =
#if !defined(WOLFSSH_NO_DH_GROUP14_SHA256) #if !defined(WOLFSSH_NO_DH_GROUP14_SHA256)
"diffie-hellman-group14-sha256," "diffie-hellman-group14-sha256,"
#endif #endif
#if !defined(WOLFSSH_NO_DH_GROUP16_SHA512)
"diffie-hellman-group16-sha512,"
#endif
#if !defined(WOLFSSH_NO_DH_GEX_SHA256) #if !defined(WOLFSSH_NO_DH_GEX_SHA256)
"diffie-hellman-group-exchange-sha256," "diffie-hellman-group-exchange-sha256,"
#endif #endif
@ -798,6 +807,9 @@ static const char cannedMacAlgoNames[] =
#if !defined(WOLFSSH_NO_HMAC_SHA2_256) #if !defined(WOLFSSH_NO_HMAC_SHA2_256)
"hmac-sha2-256," "hmac-sha2-256,"
#endif #endif
#if !defined(WOLFSSH_NO_HMAC_SHA2_512)
"hmac-sha2-512,"
#endif
#if defined(WOLFSSH_NO_SHA1_SOFT_DISABLE) #if defined(WOLFSSH_NO_SHA1_SOFT_DISABLE)
#if !defined(WOLFSSH_NO_HMAC_SHA1_96) #if !defined(WOLFSSH_NO_HMAC_SHA1_96)
"hmac-sha1-96," "hmac-sha1-96,"
@ -2444,6 +2456,9 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_HMAC_SHA2_256 #ifndef WOLFSSH_NO_HMAC_SHA2_256
{ ID_HMAC_SHA2_256, TYPE_MAC, "hmac-sha2-256" }, { ID_HMAC_SHA2_256, TYPE_MAC, "hmac-sha2-256" },
#endif #endif
#ifndef WOLFSSH_NO_HMAC_SHA2_512
{ ID_HMAC_SHA2_512, TYPE_MAC, "hmac-sha2-512" },
#endif
/* Key Exchange IDs */ /* Key Exchange IDs */
#ifndef WOLFSSH_NO_DH_GROUP1_SHA1 #ifndef WOLFSSH_NO_DH_GROUP1_SHA1
@ -2455,6 +2470,9 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_DH_GROUP14_SHA256 #ifndef WOLFSSH_NO_DH_GROUP14_SHA256
{ ID_DH_GROUP14_SHA256, TYPE_KEX, "diffie-hellman-group14-sha256" }, { ID_DH_GROUP14_SHA256, TYPE_KEX, "diffie-hellman-group14-sha256" },
#endif #endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
{ ID_DH_GROUP16_SHA512, TYPE_KEX, "diffie-hellman-group16-sha512" },
#endif
#ifndef WOLFSSH_NO_DH_GEX_SHA256 #ifndef WOLFSSH_NO_DH_GEX_SHA256
{ ID_DH_GEX_SHA256, TYPE_KEX, "diffie-hellman-group-exchange-sha256" }, { ID_DH_GEX_SHA256, TYPE_KEX, "diffie-hellman-group-exchange-sha256" },
#endif #endif
@ -3626,6 +3644,10 @@ static INLINE byte MacSzForId(byte id)
#ifndef WOLFSSH_NO_HMAC_SHA2_256 #ifndef WOLFSSH_NO_HMAC_SHA2_256
case ID_HMAC_SHA2_256: case ID_HMAC_SHA2_256:
return WC_SHA256_DIGEST_SIZE; return WC_SHA256_DIGEST_SIZE;
#endif
#ifndef WOLFSSH_NO_HMAC_SHA2_512
case ID_HMAC_SHA2_512:
return WC_SHA512_DIGEST_SIZE;
#endif #endif
default: default:
return 0; return 0;
@ -3648,6 +3670,10 @@ static INLINE byte KeySzForId(byte id)
case ID_HMAC_SHA2_256: case ID_HMAC_SHA2_256:
return WC_SHA256_DIGEST_SIZE; return WC_SHA256_DIGEST_SIZE;
#endif #endif
#ifndef WOLFSSH_NO_HMAC_SHA2_512
case ID_HMAC_SHA2_512:
return WC_SHA512_DIGEST_SIZE;
#endif
#ifndef WOLFSSH_NO_AES_CBC #ifndef WOLFSSH_NO_AES_CBC
case ID_AES128_CBC: case ID_AES128_CBC:
return AES_128_KEY_SIZE; return AES_128_KEY_SIZE;
@ -3760,6 +3786,10 @@ enum wc_HashType HashForId(byte id)
#endif #endif
return WC_HASH_TYPE_SHA512; return WC_HASH_TYPE_SHA512;
#endif #endif
#ifndef WOLFSSH_NO_DH_GROUP16_SHA512
case ID_DH_GROUP16_SHA512:
return WC_HASH_TYPE_SHA512;
#endif
#ifndef WOLFSSH_NO_RSA_SHA2_512 #ifndef WOLFSSH_NO_RSA_SHA2_512
case ID_RSA_SHA2_512: case ID_RSA_SHA2_512:
return WC_HASH_TYPE_SHA512; return WC_HASH_TYPE_SHA512;
@ -4350,6 +4380,76 @@ static const byte dhPrimeGroup14[] = {
static const word32 dhPrimeGroup14Sz = (word32)sizeof(dhPrimeGroup14); static const word32 dhPrimeGroup14Sz = (word32)sizeof(dhPrimeGroup14);
#endif #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) 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; 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: default:
WLOG(WS_LOG_DEBUG, "Invalid Mac ID"); WLOG(WS_LOG_DEBUG, "Invalid Mac ID");
ret = WS_FATAL_ERROR; ret = WS_FATAL_ERROR;
@ -9575,6 +9696,19 @@ static INLINE int VerifyMac(WOLFSSH* ssh, const byte* in, word32 inSz,
ret = WS_VERIFY_MAC_E; ret = WS_VERIFY_MAC_E;
break; 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: default:
ret = WS_INVALID_ALGO_ID; ret = WS_INVALID_ALGO_ID;
} }
@ -9714,6 +9848,8 @@ int DoReceive(WOLFSSH* ssh)
/* Peek at the packet_length field. */ /* Peek at the packet_length field. */
ato32(ssh->inputBuffer.buffer + ssh->inputBuffer.idx, &ssh->curSz); ato32(ssh->inputBuffer.buffer + ssh->inputBuffer.idx, &ssh->curSz);
if (ssh->curSz > MAX_PACKET_SZ - (word32)peerMacSz - UINT32_SZ) { 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; ssh->error = WS_OVERFLOW_E;
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
@ -10341,6 +10477,8 @@ struct wolfSSH_sigKeyBlockFull {
/* Size of Kyber public key (bigger than ciphertext) and some extra for the /* Size of Kyber public key (bigger than ciphertext) and some extra for the
* ECC hybrid component. */ * ECC hybrid component. */
#define KEX_F_SIZE 1024 #define KEX_F_SIZE 1024
#elif !defined(WOLFSSH_NO_DH_GROUP16_SHA512)
#define KEX_F_SIZE (512 + 1)
#else #else
#define KEX_F_SIZE (256 + 1) #define KEX_F_SIZE (256 + 1)
#endif #endif
@ -10480,6 +10618,14 @@ static int GetDHPrimeGroup(int kexId, const byte** primeGroup,
*generatorSz = dhGeneratorSz; *generatorSz = dhGeneratorSz;
break; break;
#endif #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 #ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256: case ID_DH_GEX_SHA256:
*primeGroup = dhPrimeGroup14; *primeGroup = dhPrimeGroup14;
@ -11764,6 +11910,12 @@ int SendKexDhReply(WOLFSSH* ssh)
msgId = MSGID_KEXDH_REPLY; msgId = MSGID_KEXDH_REPLY;
break; break;
#endif #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 #ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256: case ID_DH_GEX_SHA256:
useDh = 1; useDh = 1;
@ -12333,6 +12485,15 @@ int SendKexDhInit(WOLFSSH* ssh)
generatorSz = dhGeneratorSz; generatorSz = dhGeneratorSz;
break; break;
#endif #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 #ifndef WOLFSSH_NO_DH_GEX_SHA256
case ID_DH_GEX_SHA256: case ID_DH_GEX_SHA256:
ssh->handshake->useDh = 1; 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; return WS_CBIO_ERR_CONN_CLOSE;
} }
else { else {
WLOG(WS_LOG_DEBUG," General error"); WLOG(WS_LOG_DEBUG," General error %d", err);
return WS_CBIO_ERR_GENERAL; return WS_CBIO_ERR_GENERAL;
} }
} }

View File

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

View File

@ -3,9 +3,7 @@
# All paths should be given relative to the root # All paths should be given relative to the root
check_PROGRAMS += tests/unit.test tests/api.test \ check_PROGRAMS += tests/unit.test tests/api.test \
tests/testsuite.test tests/auth.test tests/testsuite.test tests/auth.test tests/kex.test
noinst_PROGRAMS += tests/unit.test tests/api.test \
tests/testsuite.test tests/auth.test
tests_unit_test_SOURCES = tests/unit.c tests/unit.h tests_unit_test_SOURCES = tests/unit.c tests/unit.h
tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER
@ -131,3 +129,36 @@ endif
tests_auth_test_LDADD = src/libwolfssh.la tests_auth_test_LDADD = src/libwolfssh.la
tests_auth_test_DEPENDENCIES = 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 #undef WOLFSSH_NO_HMAC_SHA2_256
#define WOLFSSH_NO_HMAC_SHA2_256 #define WOLFSSH_NO_HMAC_SHA2_256
#endif #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) && \ #if defined(WOLFSSH_NO_HMAC_SHA1) && \
defined(WOLFSSH_NO_HMAC_SHA1_96) && \ 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." #error "You need at least one MAC algorithm."
#endif #endif
@ -144,6 +149,10 @@ extern "C" {
#undef WOLFSSH_NO_DH_GROUP14_SHA256 #undef WOLFSSH_NO_DH_GROUP14_SHA256
#define WOLFSSH_NO_DH_GROUP14_SHA256 #define WOLFSSH_NO_DH_GROUP14_SHA256
#endif #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) #if defined(WOLFSSH_NO_DH) || defined(NO_SHA256)
#undef WOLFSSH_NO_DH_GEX_SHA256 #undef WOLFSSH_NO_DH_GEX_SHA256
#define WOLFSSH_NO_DH_GEX_SHA256 #define WOLFSSH_NO_DH_GEX_SHA256
@ -178,6 +187,7 @@ extern "C" {
#if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \ #if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \ defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA256) && \ defined(WOLFSSH_NO_DH_GROUP14_SHA256) && \
defined(WOLFSSH_NO_DH_GROUP16_SHA512) && \
defined(WOLFSSH_NO_DH_GEX_SHA256) && \ defined(WOLFSSH_NO_DH_GEX_SHA256) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && \ defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && \
defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \ defined(WOLFSSH_NO_ECDH_SHA2_NISTP384) && \
@ -190,6 +200,7 @@ extern "C" {
#if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \ #if defined(WOLFSSH_NO_DH_GROUP1_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \ defined(WOLFSSH_NO_DH_GROUP14_SHA1) && \
defined(WOLFSSH_NO_DH_GROUP14_SHA256) && \ defined(WOLFSSH_NO_DH_GROUP14_SHA256) && \
defined(WOLFSSH_NO_DH_GROUP16_SHA512) && \
defined(WOLFSSH_NO_DH_GEX_SHA256) defined(WOLFSSH_NO_DH_GEX_SHA256)
#undef WOLFSSH_NO_DH #undef WOLFSSH_NO_DH
#define WOLFSSH_NO_DH #define WOLFSSH_NO_DH
@ -313,11 +324,13 @@ enum {
ID_HMAC_SHA1, ID_HMAC_SHA1,
ID_HMAC_SHA1_96, ID_HMAC_SHA1_96,
ID_HMAC_SHA2_256, ID_HMAC_SHA2_256,
ID_HMAC_SHA2_512,
/* Key Exchange IDs */ /* Key Exchange IDs */
ID_DH_GROUP1_SHA1, ID_DH_GROUP1_SHA1,
ID_DH_GROUP14_SHA1, ID_DH_GROUP14_SHA1,
ID_DH_GROUP14_SHA256, ID_DH_GROUP14_SHA256,
ID_DH_GROUP16_SHA512,
ID_DH_GEX_SHA256, ID_DH_GEX_SHA256,
ID_ECDH_SHA2_NISTP256, ID_ECDH_SHA2_NISTP256,
ID_ECDH_SHA2_NISTP384, ID_ECDH_SHA2_NISTP384,
@ -391,7 +404,7 @@ enum NameIdType {
#define MAX_KEY_EXCHANGE 2 #define MAX_KEY_EXCHANGE 2
#define MAX_PUBLIC_KEY 1 #define MAX_PUBLIC_KEY 1
#define MIN_RSA_SIG_SZ 2 #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 MIN_BLOCK_SZ 8
#define COOKIE_SZ 16 #define COOKIE_SZ 16
#define PAD_LENGTH_SZ 1 #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_CONFIG_MY_IPV4_GW="192.0.2.2"
CONFIG_NET_PKT_TX_COUNT=10 CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_DATA_SIZE=256
# Logging # Logging
CONFIG_PRINTK=y 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_CONFIG_MY_IPV4_GW="192.0.2.2"
CONFIG_NET_PKT_TX_COUNT=10 CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_DATA_SIZE=256
# Logging # Logging
CONFIG_PRINTK=y CONFIG_PRINTK=y