Skip to content

Commit e53ecf4

Browse files
Add unit test for VerifyMac
1 parent b71670f commit e53ecf4

4 files changed

Lines changed: 171 additions & 3 deletions

File tree

src/internal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10502,6 +10502,13 @@ int DoReceive(WOLFSSH* ssh)
1050210502
return ret;
1050310503
}
1050410504

10505+
#ifdef WOLFSSH_TEST_INTERNAL
10506+
int wolfSSH_TestDoReceive(WOLFSSH* ssh)
10507+
{
10508+
return DoReceive(ssh);
10509+
}
10510+
#endif
10511+
1050510512

1050610513
int DoProtoId(WOLFSSH* ssh)
1050710514
{

tests/include.am

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ check_PROGRAMS += tests/unit.test tests/api.test \
77
tests/regress.test
88

99
tests_unit_test_SOURCES = tests/unit.c tests/unit.h
10-
tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER $(AM_CPPFLAGS)
11-
tests_unit_test_LDADD = src/libwolfssh.la
12-
tests_unit_test_DEPENDENCIES = src/libwolfssh.la
10+
tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER -DWOLFSSH_TEST_INTERNAL $(AM_CPPFLAGS)
11+
tests_unit_test_LDADD = src/libwolfssh_test.la
12+
tests_unit_test_DEPENDENCIES = src/libwolfssh_test.la
1313

1414
tests_api_test_SOURCES = tests/api.c tests/api.h \
1515
examples/echoserver/echoserver.c

tests/unit.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <stdio.h>
3232
#include <wolfssh/ssh.h>
3333
#include <wolfssh/keygen.h>
34+
#include <wolfssh/internal.h>
35+
#include <wolfssl/wolfcrypt/hmac.h>
3436

3537
#define WOLFSSH_TEST_HEX2BIN
3638
#include <wolfssh/test.h>
@@ -285,6 +287,153 @@ static int test_Ed25519KeyGen(void)
285287
#endif
286288

287289

290+
#if defined(WOLFSSH_TEST_INTERNAL) && \
291+
(!defined(WOLFSSH_NO_HMAC_SHA1) || \
292+
!defined(WOLFSSH_NO_HMAC_SHA1_96) || \
293+
!defined(WOLFSSH_NO_HMAC_SHA2_256) || \
294+
!defined(WOLFSSH_NO_HMAC_SHA2_512))
295+
296+
/* Minimal SSH binary packet: uint32 length, padding_length, msgId, padding.
297+
* Same layout as tests/regress.c BuildPacket (8-byte aligned body). */
298+
static word32 BuildMacTestPacketPrefix(byte msgId, byte* out, word32 outSz)
299+
{
300+
byte padLen = 6;
301+
word32 packetLen = (word32)(1 + 1 + padLen);
302+
word32 need = UINT32_SZ + packetLen;
303+
304+
if (outSz < need)
305+
return 0;
306+
out[0] = (byte)(packetLen >> 24);
307+
out[1] = (byte)(packetLen >> 16);
308+
out[2] = (byte)(packetLen >> 8);
309+
out[3] = (byte)(packetLen);
310+
out[4] = padLen;
311+
out[5] = msgId;
312+
WMEMSET(out + 6, 0, padLen);
313+
return need;
314+
}
315+
316+
317+
static int test_DoReceive_VerifyMacFailure(void)
318+
{
319+
WOLFSSH_CTX* ctx = NULL;
320+
WOLFSSH* ssh = NULL;
321+
int ret = WS_SUCCESS;
322+
int result = 0;
323+
byte flatSeq[LENGTH_SZ];
324+
byte macKey[MAX_HMAC_SZ];
325+
Hmac hmac;
326+
word32 prefixLen;
327+
word32 totalLen;
328+
byte pkt[UINT32_SZ + 8 + MAX_HMAC_SZ];
329+
int i;
330+
struct {
331+
byte macId;
332+
int hmacType;
333+
byte macSz;
334+
byte keySz;
335+
} cases[] = {
336+
#ifndef WOLFSSH_NO_HMAC_SHA1
337+
{ ID_HMAC_SHA1, WC_SHA, WC_SHA_DIGEST_SIZE, WC_SHA_DIGEST_SIZE },
338+
#endif
339+
#ifndef WOLFSSH_NO_HMAC_SHA1_96
340+
{ ID_HMAC_SHA1_96, WC_SHA, SHA1_96_SZ, WC_SHA_DIGEST_SIZE },
341+
#endif
342+
#ifndef WOLFSSH_NO_HMAC_SHA2_256
343+
{ ID_HMAC_SHA2_256, WC_SHA256, WC_SHA256_DIGEST_SIZE,
344+
WC_SHA256_DIGEST_SIZE },
345+
#endif
346+
#ifndef WOLFSSH_NO_HMAC_SHA2_512
347+
{ ID_HMAC_SHA2_512, WC_SHA512, WC_SHA512_DIGEST_SIZE,
348+
WC_SHA512_DIGEST_SIZE },
349+
#endif
350+
};
351+
352+
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
353+
if (ctx == NULL)
354+
return -200;
355+
ssh = wolfSSH_new(ctx);
356+
if (ssh == NULL) {
357+
wolfSSH_CTX_free(ctx);
358+
return -201;
359+
}
360+
361+
WMEMSET(macKey, 0xA5, sizeof(macKey));
362+
363+
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
364+
prefixLen = BuildMacTestPacketPrefix(MSGID_IGNORE, pkt, sizeof(pkt));
365+
if (prefixLen == 0) {
366+
result = -202;
367+
goto done;
368+
}
369+
totalLen = prefixLen + cases[i].macSz;
370+
371+
ssh->peerEncryptId = ID_NONE;
372+
ssh->peerAeadMode = 0;
373+
ssh->peerBlockSz = MIN_BLOCK_SZ;
374+
ssh->peerMacId = cases[i].macId;
375+
ssh->peerMacSz = cases[i].macSz;
376+
WMEMCPY(ssh->peerKeys.macKey, macKey, cases[i].keySz);
377+
ssh->peerKeys.macKeySz = cases[i].keySz;
378+
ssh->peerSeq = 0;
379+
ssh->curSz = 0;
380+
ssh->processReplyState = PROCESS_INIT;
381+
ssh->error = 0;
382+
383+
flatSeq[0] = (byte)(ssh->peerSeq >> 24);
384+
flatSeq[1] = (byte)(ssh->peerSeq >> 16);
385+
flatSeq[2] = (byte)(ssh->peerSeq >> 8);
386+
flatSeq[3] = (byte)(ssh->peerSeq);
387+
ret = wc_HmacInit(&hmac, ssh->ctx->heap, INVALID_DEVID);
388+
if (ret != WS_SUCCESS) {
389+
result = -203;
390+
goto done;
391+
}
392+
ret = wc_HmacSetKey(&hmac, cases[i].hmacType,
393+
ssh->peerKeys.macKey, ssh->peerKeys.macKeySz);
394+
if (ret == WS_SUCCESS)
395+
ret = wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
396+
if (ret == WS_SUCCESS)
397+
ret = wc_HmacUpdate(&hmac, pkt, prefixLen);
398+
if (ret == WS_SUCCESS)
399+
ret = wc_HmacFinal(&hmac, pkt + prefixLen);
400+
wc_HmacFree(&hmac);
401+
if (ret != WS_SUCCESS) {
402+
result = -204;
403+
goto done;
404+
}
405+
406+
pkt[prefixLen] ^= 0x01;
407+
408+
ShrinkBuffer(&ssh->inputBuffer, 1);
409+
ret = GrowBuffer(&ssh->inputBuffer, totalLen);
410+
if (ret != WS_SUCCESS) {
411+
result = -205;
412+
goto done;
413+
}
414+
WMEMCPY(ssh->inputBuffer.buffer, pkt, totalLen);
415+
ssh->inputBuffer.length = totalLen;
416+
ssh->inputBuffer.idx = 0;
417+
418+
ret = wolfSSH_TestDoReceive(ssh);
419+
if (ret != WS_FATAL_ERROR) {
420+
result = -206;
421+
goto done;
422+
}
423+
if (ssh->error != WS_VERIFY_MAC_E) {
424+
result = -207;
425+
goto done;
426+
}
427+
}
428+
429+
done:
430+
wolfSSH_free(ssh);
431+
wolfSSH_CTX_free(ctx);
432+
return result;
433+
}
434+
#endif /* WOLFSSH_TEST_INTERNAL && any HMAC SHA variant enabled */
435+
436+
288437
/* Error Code And Message Test */
289438

290439
static int test_Errors(void)
@@ -355,6 +504,17 @@ int wolfSSH_UnitTest(int argc, char** argv)
355504
printf("KDF: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED"));
356505
testResult = testResult || unitResult;
357506

507+
#if defined(WOLFSSH_TEST_INTERNAL) && \
508+
(!defined(WOLFSSH_NO_HMAC_SHA1) || \
509+
!defined(WOLFSSH_NO_HMAC_SHA1_96) || \
510+
!defined(WOLFSSH_NO_HMAC_SHA2_256) || \
511+
!defined(WOLFSSH_NO_HMAC_SHA2_512))
512+
unitResult = test_DoReceive_VerifyMacFailure();
513+
printf("DoReceiveVerifyMac: %s\n",
514+
(unitResult == 0 ? "SUCCESS" : "FAILED"));
515+
testResult = testResult || unitResult;
516+
#endif
517+
358518
#ifdef WOLFSSH_KEYGEN
359519
#ifndef WOLFSSH_NO_RSA
360520
unitResult = test_RsaKeyGen();

wolfssh/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,6 +1323,7 @@ enum WS_MessageIdLimits {
13231323
#ifdef WOLFSSH_TEST_INTERNAL
13241324
WOLFSSH_API int wolfSSH_TestIsMessageAllowed(WOLFSSH* ssh, byte msg,
13251325
byte state);
1326+
WOLFSSH_API int wolfSSH_TestDoReceive(WOLFSSH* ssh);
13261327
#endif
13271328

13281329
/* dynamic memory types */

0 commit comments

Comments
 (0)