Skip to content

Commit 8174aa9

Browse files
Add unit test for VerifyMac
1 parent 4ed01d3 commit 8174aa9

File tree

4 files changed

+170
-3
lines changed

4 files changed

+170
-3
lines changed

src/internal.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10475,6 +10475,13 @@ int DoReceive(WOLFSSH* ssh)
1047510475
return ret;
1047610476
}
1047710477

10478+
#ifdef WOLFSSH_TEST_INTERNAL
10479+
int wolfSSH_TestDoReceive(WOLFSSH* ssh)
10480+
{
10481+
return DoReceive(ssh);
10482+
}
10483+
#endif
10484+
1047810485

1047910486
int DoProtoId(WOLFSSH* ssh)
1048010487
{

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: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <wolfssh/ssh.h>
3333
#include <wolfssh/keygen.h>
3434
#include <wolfssh/internal.h>
35+
#include <wolfssl/wolfcrypt/hmac.h>
3536

3637
#define WOLFSSH_TEST_HEX2BIN
3738
#include <wolfssh/test.h>
@@ -285,6 +286,153 @@ static int test_Ed25519KeyGen(void)
285286
#endif
286287

287288

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

290438
static int test_Errors(void)
@@ -356,6 +504,17 @@ int wolfSSH_UnitTest(int argc, char** argv)
356504
printf("KDF: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED"));
357505
testResult = testResult || unitResult;
358506

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+
359518
#ifdef WOLFSSH_KEYGEN
360519
#ifndef WOLFSSH_NO_RSA
361520
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)