Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Key completion callback #694

Merged
merged 4 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions examples/echoserver/echoserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ static int callbackReqFailure(WOLFSSH *ssh, void *buf, word32 sz, void *ctx)
return WS_SUCCESS;
}


static void *global_req(void *ctx)
{
int ret;
Expand Down Expand Up @@ -328,6 +329,50 @@ static void *global_req(void *ctx)
#endif


static void printKeyCompleteText(WOLFSSH* ssh, WS_Text id, const char* tag)
{
char str[200];
size_t strSz = sizeof(str);
size_t ret;

ret = wolfSSH_GetText(ssh, id, str, strSz);
if (ret == strSz) {
printf("\tString size was not large enough for %s\n", tag);
}
printf("\t%-30s : %s\n", tag, str);
}


static void callbackKeyingComplete(void* ctx)
{
WOLFSSH* ssh = (WOLFSSH*)ctx;

if (ssh != NULL) {
printf("Keying Complete:\n");
printKeyCompleteText(ssh, WOLFSSH_TEXT_KEX_ALGO,
"WOLFSSH_TEXT_KEX_ALGO");

printKeyCompleteText(ssh, WOLFSSH_TEXT_KEX_CURVE,
"WOLFSSH_TEXT_KEX_CURVE");

printKeyCompleteText(ssh, WOLFSSH_TEXT_KEX_HASH,
"WOLFSSH_TEXT_KEX_HASH");

printKeyCompleteText(ssh, WOLFSSH_TEXT_CRYPTO_IN_CIPHER,
"WOLFSSH_TEXT_CRYPTO_IN_CIPHER");

printKeyCompleteText(ssh, WOLFSSH_TEXT_CRYPTO_IN_MAC,
"WOLFSSH_TEXT_CRYPTO_IN_MAC");

printKeyCompleteText(ssh, WOLFSSH_TEXT_CRYPTO_OUT_CIPHER,
"WOLFSSH_TEXT_CRYPTO_OUT_CIPHER");

printKeyCompleteText(ssh, WOLFSSH_TEXT_CRYPTO_OUT_MAC,
"WOLFSSH_TEXT_CRYPTO_OUT_MAC");
}
}


#ifdef WOLFSSH_AGENT

static const char EnvNameAuthPort[] = "SSH_AUTH_SOCK";
Expand Down Expand Up @@ -2435,6 +2480,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
ES_ERROR("Couldn't allocate SSH CTX data.\n");
}

wolfSSH_SetKeyingCompletionCb(ctx, callbackKeyingComplete);
if (keyList) {
if (wolfSSH_CTX_SetAlgoListKey(ctx, keyList) != WS_SUCCESS) {
ES_ERROR("Error setting key list.\n");
Expand Down Expand Up @@ -2678,6 +2724,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
wolfSSH_MemoryConnPrintStats(heap);
#endif
wolfSSH_SetUserAuthCtx(ssh, &pwMapList);
wolfSSH_SetKeyingCompletionCbCtx(ssh, (void*)ssh);
/* Use the session object for its own highwater callback ctx */
if (defaultHighwater > 0) {
wolfSSH_SetHighwaterCtx(ssh, (void*)ssh);
Expand Down
13 changes: 9 additions & 4 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,8 @@ WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
#endif
#endif

ssh->keyingCompletionCtx = (void*)ssh;

if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS ||
BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS ||
BufferInit(&ssh->extDataBuffer, 0, ctx->heap) != WS_SUCCESS) {
Expand Down Expand Up @@ -3557,8 +3559,7 @@ static INLINE byte KeySzForId(byte id)
}
}


static INLINE enum wc_HashType HashForId(byte id)
INLINE enum wc_HashType HashForId(byte id)
{
switch (id) {

Expand Down Expand Up @@ -3649,7 +3650,7 @@ static INLINE enum wc_HashType HashForId(byte id)


#if !defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_ECDH)
static INLINE int wcPrimeForId(byte id)
int wcPrimeForId(byte id)
{
switch (id) {
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
Expand Down Expand Up @@ -3819,7 +3820,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
}
}
if (ret == WS_SUCCESS) {
ssh->handshake->kexId = algoId;
ssh->kexId = ssh->handshake->kexId = algoId;
ssh->handshake->kexHashId = HashForId(algoId);
}
/* Extension Info Flag */
Expand Down Expand Up @@ -5565,6 +5566,9 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
HandshakeInfoFree(ssh->handshake, ssh->ctx->heap);
ssh->handshake = NULL;
WLOG(WS_LOG_DEBUG, "Keying completed");

if (ssh->ctx->keyingCompletionCb)
ssh->ctx->keyingCompletionCb(ssh->keyingCompletionCtx);
}

return ret;
Expand Down Expand Up @@ -10530,6 +10534,7 @@ static int KeyAgreeDh_server(WOLFSSH* ssh, byte hashId, byte* f, word32* fSz)
&primeGroupSz, &generator, &generatorSz);

if (ret == WS_SUCCESS) {
ssh->primeGroupSz = primeGroupSz;
ret = wc_InitDhKey(privKey);
}
if (ret == 0)
Expand Down
214 changes: 214 additions & 0 deletions src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -2834,6 +2834,220 @@ int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel)
return eof;
}

static const char* HashNameForId(byte id)
{
enum wc_HashType hash = HashForId(id);

if (hash == WC_HASH_TYPE_SHA)
return "SHA-1";

if (hash == WC_HASH_TYPE_SHA256)
return "SHA-256";

if (hash == WC_HASH_TYPE_SHA384)
return "SHA-384";

if (hash == WC_HASH_TYPE_SHA512)
return "SHA-512";

return "";
}

static const char* CurveNameForId(byte id)
{
#if !defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_ECDH)
switch (wcPrimeForId(id)) {
case ECC_SECP256R1:
return "nistp256";

case ECC_SECP384R1:
return "nistp384";

case ECC_SECP521R1:
return "nistp521";

#ifdef HAVE_CURVE25519
case ECC_X25519:
return "Curve25519";
#endif
}
#endif
return "";
}

static const char* CipherNameForId(byte id)
{
switch (id) {
case ID_AES128_CBC:
return "AES-128 CBC";

case ID_AES192_CBC:
return "AES-192 CBC";

case ID_AES256_CBC:
return "AES-256 CBC";

case ID_AES128_CTR:
return "AES-128 SDCTR";

case ID_AES192_CTR:
return "AES-192 SDCTR";

case ID_AES256_CTR:
return "AES-256 SDCTR";

case ID_AES128_GCM:
return "AES-128 GCM";

case ID_AES192_GCM:
return "AES-192 GCM";

case ID_AES256_GCM:
return "AES-256 GCM";
}

return "";
}

static const char* MacNameForId(byte macid, byte cipherid)
{
if (macid != ID_NONE) {
switch (macid) {
case ID_HMAC_SHA1:
return "HMAC-SHA-1";

case ID_HMAC_SHA1_96:
return "HMAC-SHA-1-96";

case ID_HMAC_SHA2_256:
return "HMAC-SHA-256";
}
}
else {
switch (cipherid) {
case ID_AES128_GCM:
return "AES128 GCM (in ETM mode)";

case ID_AES192_GCM:
return "AES192 GCM (in ETM mode)";

case ID_AES256_GCM:
return "AES256 GCM (in ETM mode)";
}
}

return "";
}

size_t wolfSSH_GetText(WOLFSSH *ssh, WS_Text id, char *str, size_t strSz)
{
int ret = 0;

#ifndef WOLFSSH_NO_DH
static const char standard_dh_format[] =
"%d-bit Diffie-Hellman with standard group %d";
#endif

if (!ssh || str == NULL || strSz <= 0)
return 0;

switch (id) {
case WOLFSSH_TEXT_KEX_HASH:
ret = WSNPRINTF(str, strSz, "%s", HashNameForId(ssh->kexId));
break;

case WOLFSSH_TEXT_KEX_CURVE:
ret = WSNPRINTF(str, strSz, "%s", CurveNameForId(ssh->kexId));
break;

case WOLFSSH_TEXT_CRYPTO_IN_CIPHER:
ret = WSNPRINTF(str, strSz, "%s",
CipherNameForId(ssh->peerEncryptId));
break;

case WOLFSSH_TEXT_CRYPTO_OUT_CIPHER:
ret = WSNPRINTF(str, strSz, "%s", CipherNameForId(ssh->encryptId));
break;

case WOLFSSH_TEXT_CRYPTO_IN_MAC:
ret = WSNPRINTF(str, strSz, "%s", MacNameForId(ssh->peerMacId,
ssh->peerEncryptId));
break;

case WOLFSSH_TEXT_CRYPTO_OUT_MAC:
ret = WSNPRINTF(str, strSz, "%s", MacNameForId(ssh->macId,
ssh->encryptId));
break;

case WOLFSSH_TEXT_KEX_ALGO:
switch (ssh->kexId) {
case ID_ECDH_SHA2_NISTP256:
case ID_ECDH_SHA2_NISTP384:
case ID_ECDH_SHA2_NISTP521:
case ID_ECDH_SHA2_ED25519:
case ID_ECDH_SHA2_ED25519_LIBSSH:
#ifndef WOLFSSH_NO_CURVE25519_SHA256
case ID_CURVE25519_SHA256:
#endif
ret = WSNPRINTF(str, strSz, "%s", "ECDH");
break;

#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
case ID_ECDH_NISTP256_KYBER_LEVEL1_SHA256:
ret = WSNPRINTF(str, strSz, "%s", "Kyber1");
break;
#endif

#ifndef WOLFSSH_NO_DH
case ID_DH_GROUP1_SHA1:
ret = WSNPRINTF(str, strSz, standard_dh_format,
ssh->primeGroupSz*8, 1);
break;

case ID_DH_GROUP14_SHA1:
case ID_DH_GROUP14_SHA256:
ret = WSNPRINTF(str, strSz, standard_dh_format,
ssh->primeGroupSz*8, 14);
break;

case ID_DH_GEX_SHA256:
ret = WSNPRINTF(str, strSz,
"%d-bit Diffie-Hellman with server-supplied group",
ssh->primeGroupSz*8);
break;
#endif /* !WOLFSSH_NO_DH */

case ID_EXTINFO_S:
ret = WSNPRINTF(str, strSz, "Server extensions KEX");
break;

case ID_EXTINFO_C:
ret = WSNPRINTF(str, strSz, "Client extensions KEX");
break;

}
break;
}

return ret < 0 ? 0 : (size_t)ret;
}

void wolfSSH_SetKeyingCompletionCb(WOLFSSH_CTX* ctx, WS_CallbackKeyingCompletion cb)
{
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_SetKeyingCompletionCb()");

if (ctx)
ctx->keyingCompletionCb = cb;
}

void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH* ssh, void* ctx)
{
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_SetKeyingCompletionCbCtx()");

if (ssh)
ssh->keyingCompletionCtx = ctx;
}


#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
!defined(NO_WOLFSSH_SERVER)
Expand Down
10 changes: 10 additions & 0 deletions wolfssh/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ struct WOLFSSH_CTX {
#ifdef WOLFSSH_AGENT
byte agentEnabled;
#endif /* WOLFSSH_AGENT */
WS_CallbackKeyingCompletion keyingCompletionCb;
};


Expand Down Expand Up @@ -725,6 +726,7 @@ struct WOLFSSH {
byte isClosed;
byte clientOpenSSH;

byte kexId;
byte blockSz;
byte encryptId;
byte macId;
Expand All @@ -735,6 +737,9 @@ struct WOLFSSH {
byte peerMacId;
byte peerMacSz;
byte peerAeadMode;
#ifndef WOLFSSH_NO_DH
word32 primeGroupSz;
#endif

Ciphers encryptCipher;
Ciphers decryptCipher;
Expand Down Expand Up @@ -853,6 +858,7 @@ struct WOLFSSH {
#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL)
word32 exitStatus;
#endif
void* keyingCompletionCtx;
};


Expand Down Expand Up @@ -989,6 +995,10 @@ WOLFSSH_LOCAL int SendChannelExitStatus(WOLFSSH* ssh, word32 channelId,
word32 exitStatus);
WOLFSSH_LOCAL int GenerateKey(byte, byte, byte*, word32, const byte*, word32,
const byte*, word32, const byte*, word32, byte doKeyPad);
#if !defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_ECDH)
WOLFSSH_LOCAL int wcPrimeForId(byte);
#endif
WOLFSSH_LOCAL enum wc_HashType HashForId(byte);


enum AcceptStates {
Expand Down
Loading
Loading