1919#endif
2020
2121#include <wolfssh/ssh.h>
22+ #include <wolfssl/wolfcrypt/coding.h>
2223#include <configuration.h>
2324#include <auth.h>
2425
@@ -38,10 +39,9 @@ void Log(const char *const, ...) FMTCHECK;
3839void Log (const char * const fmt , ...)
3940{
4041 va_list vlist ;
41- char msgStr [WOLFSSH_DEFAULT_LOG_WIDTH ];
4242
4343 va_start (vlist , fmt );
44- WVSNPRINTF ( msgStr , sizeof ( msgStr ) , fmt , vlist );
44+ vfprintf ( stderr , fmt , vlist );
4545 va_end (vlist );
4646}
4747
@@ -494,11 +494,113 @@ static int test_CheckPasswordHashUnix(void)
494494}
495495#endif /* WOLFSSH_HAVE_LIBCRYPT || WOLFSSH_HAVE_LIBLOGIN */
496496
497+ #ifdef WOLFSSL_BASE64_ENCODE
498+ /* Build a mutable "ssh-rsa <base64(key)>" line; WSTRTOK mutates in place. */
499+ static int BuildAuthKeysLine (const byte * key , word32 keySz ,
500+ char * lineOut , word32 lineOutSz )
501+ {
502+ static const char prefix [] = "ssh-rsa " ;
503+ word32 prefixLen = (word32 )(sizeof (prefix ) - 1 );
504+ word32 b64Sz ;
505+
506+ if (lineOutSz <= prefixLen ) {
507+ return WS_BUFFER_E ;
508+ }
509+ WMEMCPY (lineOut , prefix , prefixLen );
510+ b64Sz = lineOutSz - prefixLen ;
511+ if (Base64_Encode_NoNl (key , keySz , (byte * )lineOut + prefixLen , & b64Sz )
512+ != 0 ) {
513+ return WS_FATAL_ERROR ;
514+ }
515+ /* Base64_Encode_NoNl does not null-terminate; do it ourselves. */
516+ if (prefixLen + b64Sz >= lineOutSz ) {
517+ return WS_BUFFER_E ;
518+ }
519+ lineOut [prefixLen + b64Sz ] = '\0' ;
520+ return WS_SUCCESS ;
521+ }
522+
523+ /* Negative-path coverage for CheckAuthKeysLine so mutation of the
524+ * ConstantCompare clause (the only substantive bytewise check after the
525+ * length comparison) does not survive the test suite. */
526+ static int test_CheckAuthKeysLine (void )
527+ {
528+ int ret = WS_SUCCESS ;
529+ /* Three equal-length payloads. keyB differs from keyA throughout;
530+ * keyALastByte differs from keyA only in the final byte -- this is the
531+ * case that kills a "delete the ConstantCompare" mutation, since the
532+ * length comparison alone would accept it. */
533+ static const char keyAStr [] = "wolfssh-auth-key-test-A-AAAAAAA" ;
534+ static const char keyBStr [] = "wolfssh-auth-key-test-B-BBBBBBB" ;
535+ const byte * keyA = (const byte * )keyAStr ;
536+ const byte * keyB = (const byte * )keyBStr ;
537+ const word32 keySz = (word32 )(sizeof (keyAStr ) - 1 );
538+ byte keyALastByte [sizeof (keyAStr ) - 1 ];
539+ char line [256 ];
540+ char lineCopy [256 ];
541+ int rc ;
542+
543+ WMEMCPY (keyALastByte , keyA , keySz );
544+ keyALastByte [keySz - 1 ] ^= 0x01 ;
545+
546+ ret = BuildAuthKeysLine (keyA , keySz , line , sizeof (line ));
547+ if (ret != WS_SUCCESS ) {
548+ return ret ;
549+ }
550+
551+ Log (" Testing scenario: matching key authenticates." );
552+ WMEMCPY (lineCopy , line , WSTRLEN (line ) + 1 );
553+ rc = CheckAuthKeysLine (lineCopy , (word32 )WSTRLEN (lineCopy ),
554+ keyA , keySz );
555+ if (rc == WSSHD_AUTH_SUCCESS ) {
556+ Log (" PASSED.\n" );
557+ }
558+ else {
559+ Log (" FAILED (rc=%d).\n" , rc );
560+ ret = WS_FATAL_ERROR ;
561+ }
562+
563+ if (ret == WS_SUCCESS ) {
564+ Log (" Testing scenario: different same-length key is rejected." );
565+ WMEMCPY (lineCopy , line , WSTRLEN (line ) + 1 );
566+ rc = CheckAuthKeysLine (lineCopy , (word32 )WSTRLEN (lineCopy ),
567+ keyB , keySz );
568+ if (rc == WSSHD_AUTH_FAILURE ) {
569+ Log (" PASSED.\n" );
570+ }
571+ else {
572+ Log (" FAILED (rc=%d).\n" , rc );
573+ ret = WS_FATAL_ERROR ;
574+ }
575+ }
576+
577+ if (ret == WS_SUCCESS ) {
578+ Log (" Testing scenario: same-length key differing in last byte is "
579+ "rejected." );
580+ WMEMCPY (lineCopy , line , WSTRLEN (line ) + 1 );
581+ rc = CheckAuthKeysLine (lineCopy , (word32 )WSTRLEN (lineCopy ),
582+ keyALastByte , keySz );
583+ if (rc == WSSHD_AUTH_FAILURE ) {
584+ Log (" PASSED.\n" );
585+ }
586+ else {
587+ Log (" FAILED (rc=%d).\n" , rc );
588+ ret = WS_FATAL_ERROR ;
589+ }
590+ }
591+
592+ return ret ;
593+ }
594+ #endif /* WOLFSSL_BASE64_ENCODE */
595+
497596const TEST_CASE testCases [] = {
498597 TEST_DECL (test_ConfigDefaults ),
499598 TEST_DECL (test_ParseConfigLine ),
500599 TEST_DECL (test_ConfigCopy ),
501600 TEST_DECL (test_ConfigFree ),
601+ #ifdef WOLFSSL_BASE64_ENCODE
602+ TEST_DECL (test_CheckAuthKeysLine ),
603+ #endif
502604#if defined(WOLFSSH_HAVE_LIBCRYPT ) || defined (WOLFSSH_HAVE_LIBLOGIN )
503605 TEST_DECL (test_CheckPasswordHashUnix ),
504606#endif
0 commit comments