examples: compare auth secrets in constant time

The echoserver and tpmcertserver userauth callbacks compare the stored
digest or password with wolfSSH_ConstantCompare(). The echoserver
callback now wipes its digest buffer on every return.

Issue: F-8858, F-12630
pull/1338/merge
John Safranek 2026-10-21 09:20:01 -07:00 committed by philljj
parent 908ccef52a
commit 057a756f33
2 changed files with 28 additions and 9 deletions

View File

@ -3598,13 +3598,14 @@ static int wsUserAuthResult(byte res,
static int userAuthWouldBlock = 0;
static int wsUserAuth(byte authType,
WS_UserAuthData* authData,
void* ctx)
/* authHash is WC_SHA256_DIGEST_SIZE bytes of scratch for the digest of the
* offered secret; the caller wipes it. */
static int wsUserAuthCheck(byte authType,
WS_UserAuthData* authData,
void* ctx, byte* authHash)
{
PwMapList* list;
PwMap* map;
byte authHash[WC_SHA256_DIGEST_SIZE] = {0};
int userFound = 0;
if (ctx == NULL) {
@ -3727,14 +3728,16 @@ static int wsUserAuth(byte authType,
if (authData->type == WOLFSSH_USERAUTH_PUBLICKEY) {
userFound = 1;
if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) {
if (wolfSSH_ConstantCompare(map->p, authHash,
WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
/* Hash mismatch: continue checking other registered keys
* for this user (a user may have multiple public keys). */
}
else if (authData->type == WOLFSSH_USERAUTH_PASSWORD) {
if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) {
if (wolfSSH_ConstantCompare(map->p, authHash,
WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
@ -3754,7 +3757,8 @@ static int wsUserAuth(byte authType,
}
/* do keyboard auth prompts */
if (WMEMCMP(map->p, authHash, WC_SHA256_DIGEST_SIZE) == 0) {
if (wolfSSH_ConstantCompare(map->p, authHash,
WC_SHA256_DIGEST_SIZE) == 0) {
return WOLFSSH_USERAUTH_SUCCESS;
}
else {
@ -3780,6 +3784,20 @@ static int wsUserAuth(byte authType,
}
static int wsUserAuth(byte authType,
WS_UserAuthData* authData,
void* ctx)
{
byte authHash[WC_SHA256_DIGEST_SIZE] = {0};
int ret;
ret = wsUserAuthCheck(authType, authData, ctx, authHash);
wc_ForceZero(authHash, sizeof(authHash));
return ret;
}
#ifdef WOLFSSH_SFTP
/*
* Sets the WOLFSSH object's default SFTP path to the value provided by

View File

@ -64,11 +64,12 @@ static int TpmCsUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
WOLFSSH_UNUSED(ctx);
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
const char* pw = (const char*)authData->sf.password.password;
const byte* pw = authData->sf.password.password;
word32 pwSz = authData->sf.password.passwordSz;
if (pwSz == (word32)XSTRLEN(TPMCS_PASSWORD)
&& XMEMCMP(pw, TPMCS_PASSWORD, pwSz) == 0) {
&& wolfSSH_ConstantCompare(pw,
(const byte*)TPMCS_PASSWORD, pwSz) == 0) {
ret = WOLFSSH_USERAUTH_SUCCESS;
}
}