Skip to content

Commit 0c34602

Browse files
Add regress test for independent algo negotiation
1 parent 928f54c commit 0c34602

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

tests/regress.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,6 +1989,33 @@ static word32 BuildKexInitPayload(WOLFSSH* ssh, const char* kexList,
19891989
return idx;
19901990
}
19911991

1992+
/* Like BuildKexInitPayload but with explicit per-direction cipher/MAC lists. */
1993+
static word32 BuildKexInitPayloadFull(const char* kexList,
1994+
const char* keyList, const char* encC2S, const char* encS2C,
1995+
const char* macC2S, const char* macS2C,
1996+
byte firstPacketFollows, byte* out, word32 outSz)
1997+
{
1998+
word32 idx = 0;
1999+
2000+
AssertTrue(idx + COOKIE_SZ <= outSz);
2001+
WMEMSET(out + idx, 0, COOKIE_SZ);
2002+
idx += COOKIE_SZ;
2003+
idx = AppendString(out, outSz, idx, kexList);
2004+
idx = AppendString(out, outSz, idx, keyList);
2005+
idx = AppendString(out, outSz, idx, encC2S);
2006+
idx = AppendString(out, outSz, idx, encS2C);
2007+
idx = AppendString(out, outSz, idx, macC2S);
2008+
idx = AppendString(out, outSz, idx, macS2C);
2009+
idx = AppendString(out, outSz, idx, "none");
2010+
idx = AppendString(out, outSz, idx, "none");
2011+
idx = AppendString(out, outSz, idx, "");
2012+
idx = AppendString(out, outSz, idx, "");
2013+
idx = AppendByte(out, outSz, idx, firstPacketFollows);
2014+
idx = AppendUint32(out, outSz, idx, 0); /* reserved */
2015+
2016+
return idx;
2017+
}
2018+
19922019
typedef struct {
19932020
const char* description;
19942021
const char* kexList;
@@ -2107,6 +2134,79 @@ static void TestFirstPacketFollows(void)
21072134
TestFirstPacketFollowsSkipped();
21082135
}
21092136

2137+
#if !defined(WOLFSSH_NO_AES_CBC) && !defined(WOLFSSH_NO_AES_CTR) \
2138+
&& !defined(WOLFSSH_NO_HMAC_SHA1) && !defined(WOLFSSH_NO_HMAC_SHA2_256)
2139+
static void TestIndependentAlgoNegotiation(void)
2140+
{
2141+
WOLFSSH_CTX* ctx;
2142+
WOLFSSH* ssh;
2143+
byte payload[512];
2144+
word32 payloadSz;
2145+
word32 idx;
2146+
2147+
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
2148+
AssertNotNull(ctx);
2149+
2150+
/* Sub-test A: different non-AEAD cipher and MAC per direction */
2151+
ssh = wolfSSH_new(ctx);
2152+
AssertNotNull(ssh);
2153+
AssertIntEQ(wolfSSH_SetAlgoListKex(ssh, FPF_KEX_GOOD), WS_SUCCESS);
2154+
AssertIntEQ(wolfSSH_SetAlgoListKey(ssh, FPF_KEY_GOOD), WS_SUCCESS);
2155+
AssertIntEQ(wolfSSH_SetAlgoListCipher(ssh,
2156+
"aes128-cbc,aes256-ctr"), WS_SUCCESS);
2157+
AssertIntEQ(wolfSSH_SetAlgoListMac(ssh,
2158+
"hmac-sha1,hmac-sha2-256"), WS_SUCCESS);
2159+
idx = 0;
2160+
payloadSz = BuildKexInitPayloadFull(
2161+
FPF_KEX_GOOD, FPF_KEY_GOOD,
2162+
"aes128-cbc", /* C2S enc */
2163+
"aes256-ctr", /* S2C enc */
2164+
"hmac-sha1", /* C2S MAC */
2165+
"hmac-sha2-256", /* S2C MAC */
2166+
0, payload, (word32)sizeof(payload));
2167+
(void)wolfSSH_TestDoKexInit(ssh, payload, payloadSz, &idx);
2168+
AssertNotNull(ssh->handshake);
2169+
AssertIntEQ(ssh->handshake->peerEncryptId, ID_AES128_CBC);
2170+
AssertIntEQ(ssh->handshake->encryptId, ID_AES256_CTR);
2171+
AssertIntEQ(ssh->handshake->peerMacId, ID_HMAC_SHA1);
2172+
AssertIntEQ(ssh->handshake->macId, ID_HMAC_SHA2_256);
2173+
AssertIntEQ(ssh->handshake->peerAeadMode, 0);
2174+
AssertIntEQ(ssh->handshake->aeadMode, 0);
2175+
wolfSSH_free(ssh);
2176+
2177+
#ifndef WOLFSSH_NO_AES_GCM
2178+
/* Sub-test B: AEAD S2C, non-AEAD C2S — MAC only negotiated for C2S */
2179+
ssh = wolfSSH_new(ctx);
2180+
AssertNotNull(ssh);
2181+
AssertIntEQ(wolfSSH_SetAlgoListKex(ssh, FPF_KEX_GOOD), WS_SUCCESS);
2182+
AssertIntEQ(wolfSSH_SetAlgoListKey(ssh, FPF_KEY_GOOD), WS_SUCCESS);
2183+
AssertIntEQ(wolfSSH_SetAlgoListCipher(ssh,
2184+
"aes128-cbc,aes256-gcm@openssh.com"), WS_SUCCESS);
2185+
AssertIntEQ(wolfSSH_SetAlgoListMac(ssh,
2186+
"hmac-sha1,hmac-sha2-256"), WS_SUCCESS);
2187+
idx = 0;
2188+
payloadSz = BuildKexInitPayloadFull(
2189+
FPF_KEX_GOOD, FPF_KEY_GOOD,
2190+
"aes128-cbc", /* C2S enc: non-AEAD */
2191+
"aes256-gcm@openssh.com", /* S2C enc: AEAD */
2192+
"hmac-sha1", /* C2S MAC: negotiated */
2193+
"hmac-sha2-256", /* S2C MAC: skipped (aeadMode) */
2194+
0, payload, (word32)sizeof(payload));
2195+
(void)wolfSSH_TestDoKexInit(ssh, payload, payloadSz, &idx);
2196+
AssertNotNull(ssh->handshake);
2197+
AssertIntEQ(ssh->handshake->peerEncryptId, ID_AES128_CBC);
2198+
AssertIntEQ(ssh->handshake->encryptId, ID_AES256_GCM);
2199+
AssertIntEQ(ssh->handshake->peerAeadMode, 0);
2200+
AssertIntEQ(ssh->handshake->aeadMode, 1);
2201+
AssertIntEQ(ssh->handshake->peerMacId, ID_HMAC_SHA1);
2202+
AssertIntEQ(ssh->handshake->macId, ID_NONE);
2203+
wolfSSH_free(ssh);
2204+
#endif /* !WOLFSSH_NO_AES_GCM */
2205+
2206+
wolfSSH_CTX_free(ctx);
2207+
}
2208+
#endif /* AES_CBC + AES_CTR + HMAC guards */
2209+
21102210
#endif /* first_packet_follows coverage guard */
21112211

21122212

@@ -2155,6 +2255,13 @@ int main(int argc, char** argv)
21552255
&& !defined(WOLFSSH_NO_CURVE25519_SHA256) \
21562256
&& !defined(WOLFSSH_NO_RSA_SHA2_256)
21572257
TestFirstPacketFollows();
2258+
#endif
2259+
#if !defined(WOLFSSH_NO_ECDH_SHA2_NISTP256) && !defined(WOLFSSH_NO_RSA) \
2260+
&& !defined(WOLFSSH_NO_CURVE25519_SHA256) \
2261+
&& !defined(WOLFSSH_NO_RSA_SHA2_256) \
2262+
&& !defined(WOLFSSH_NO_AES_CBC) && !defined(WOLFSSH_NO_AES_CTR) \
2263+
&& !defined(WOLFSSH_NO_HMAC_SHA1) && !defined(WOLFSSH_NO_HMAC_SHA2_256)
2264+
TestIndependentAlgoNegotiation();
21582265
#endif
21592266
TestDisconnectSetsDisconnectError();
21602267
TestClientBuffersIdempotent();

0 commit comments

Comments
 (0)