Skip to content

Commit

Permalink
Merge pull request #694 from JacobBarthelmeh/544
Browse files Browse the repository at this point in the history
Key completion callback
  • Loading branch information
ejohnstown authored May 17, 2024
2 parents 5ef2bc5 + 9285a0a commit 5478fda
Show file tree
Hide file tree
Showing 5 changed files with 313 additions and 4 deletions.
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

0 comments on commit 5478fda

Please sign in to comment.