Skip to content

Commit 3d3c2c0

Browse files
Add unit test for VerifyMac
1 parent 4ed01d3 commit 3d3c2c0

4 files changed

Lines changed: 169 additions & 3 deletions

File tree

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: 158 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,152 @@ 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+
ret = GrowBuffer(&ssh->inputBuffer, totalLen);
408+
if (ret != WS_SUCCESS) {
409+
result = -205;
410+
goto done;
411+
}
412+
WMEMCPY(ssh->inputBuffer.buffer, pkt, totalLen);
413+
ssh->inputBuffer.length = totalLen;
414+
ssh->inputBuffer.idx = 0;
415+
416+
ret = wolfSSH_TestDoReceive(ssh);
417+
if (ret != WS_FATAL_ERROR) {
418+
result = -206;
419+
goto done;
420+
}
421+
if (ssh->error != WS_VERIFY_MAC_E) {
422+
result = -207;
423+
goto done;
424+
}
425+
}
426+
427+
done:
428+
wolfSSH_free(ssh);
429+
wolfSSH_CTX_free(ctx);
430+
return result;
431+
}
432+
#endif /* WOLFSSH_TEST_INTERNAL && any HMAC SHA variant enabled */
433+
434+
288435
/* Error Code And Message Test */
289436

290437
static int test_Errors(void)
@@ -356,6 +503,17 @@ int wolfSSH_UnitTest(int argc, char** argv)
356503
printf("KDF: %s\n", (unitResult == 0 ? "SUCCESS" : "FAILED"));
357504
testResult = testResult || unitResult;
358505

506+
#if defined(WOLFSSH_TEST_INTERNAL) && \
507+
(!defined(WOLFSSH_NO_HMAC_SHA1) || \
508+
!defined(WOLFSSH_NO_HMAC_SHA1_96) || \
509+
!defined(WOLFSSH_NO_HMAC_SHA2_256) || \
510+
!defined(WOLFSSH_NO_HMAC_SHA2_512))
511+
unitResult = test_DoReceive_VerifyMacFailure();
512+
printf("DoReceiveVerifyMac: %s\n",
513+
(unitResult == 0 ? "SUCCESS" : "FAILED"));
514+
testResult = testResult || unitResult;
515+
#endif
516+
359517
#ifdef WOLFSSH_KEYGEN
360518
#ifndef WOLFSSH_NO_RSA
361519
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)