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

Callback on keying completion, plus wolfSSH_GetText. #544

Closed
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
15 changes: 11 additions & 4 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,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 @@ -2836,8 +2838,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 @@ -2920,7 +2921,7 @@ static INLINE enum wc_HashType HashForId(byte id)


#if !defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_ECDH)
static INLINE int wcPrimeForId(byte id)
INLINE int wcPrimeForId(byte id)
{
switch (id) {
#ifndef WOLFSSH_NO_ECDH_NISTP256_KYBER_LEVEL1_SHA256
Expand Down Expand Up @@ -3058,7 +3059,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
ret = WS_MATCH_KEX_ALGO_E;
}
else {
ssh->handshake->kexId = algoId;
ssh->kexId = ssh->handshake->kexId = algoId;
ssh->handshake->kexHashId = HashForId(algoId);
}
}
Expand Down Expand Up @@ -4513,6 +4514,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 @@ -9206,6 +9210,9 @@ int SendKexDhReply(WOLFSSH* ssh)
#endif

if (ret == WS_SUCCESS) {
#ifndef WOLFSSH_NO_DH
ssh->primeGroupSz = primeGroupSz;
#endif
ret = wc_InitDhKey(privKey);
}
if (ret == 0)
Expand Down
184 changes: 184 additions & 0 deletions src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,190 @@ 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;

if (!ssh)
return 0;

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

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:
ret = WSNPRINTF(str, strsz, "%s", "ECDH");
break;

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;
}
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 @@ -502,6 +502,7 @@ struct WOLFSSH_CTX {
#ifdef WOLFSSH_AGENT
byte agentEnabled;
#endif /* WOLFSSH_AGENT */
WS_CallbackKeyingCompletion keyingCompletionCb;
};


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

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

Ciphers encryptCipher;
Ciphers decryptCipher;
Expand Down Expand Up @@ -805,6 +810,7 @@ struct WOLFSSH {
word32 curX; /* current terminal width */
word32 curY; /* current terminal height */
#endif
void* keyingCompletionCtx;
};


Expand Down Expand Up @@ -936,6 +942,10 @@ WOLFSSH_LOCAL int SendChannelAgentRequest(WOLFSSH* ssh);
WOLFSSH_LOCAL int SendChannelSuccess(WOLFSSH*, word32, int);
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
33 changes: 33 additions & 0 deletions wolfssh/ssh.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,39 @@ WOLFSSH_API int wolfSSH_ReadKey_file(const char* name,
byte** out, word32* outSz, const byte** outType, word32* outTypeSz,
byte* isPrivate, void* heap);

typedef enum WS_Text {
WOLFSSH_TEXT_KEX_ALGO,
WOLFSSH_TEXT_KEX_CURVE,
WOLFSSH_TEXT_KEX_HASH,

WOLFSSH_TEXT_CRYPTO_IN_CIPHER,
WOLFSSH_TEXT_CRYPTO_IN_MAC,
WOLFSSH_TEXT_CRYPTO_OUT_CIPHER,
WOLFSSH_TEXT_CRYPTO_OUT_MAC,
} WS_Text;

/*
* Outputs the c-string representation of the data entry identified by the id to
* the character string str, writing no more than strsz bytes, including the
* terminating null byte ('\0').
*
* Returns the number of characters written (excluding the null byte used to end
* output to strings), unless the output was truncated, in which case the return
* value is the number of characters (excluding the terminating null byte) which
* would have been written to the final string if enough space had been
* available.
*
* Thus, a return value of strsz or more means that the output was truncated.
*/

WOLFSSH_API size_t wolfSSH_GetText(WOLFSSH *ssh, WS_Text id, char *str,
size_t strsz);

typedef void (*WS_CallbackKeyingCompletion)(void *);
WOLFSSH_API void wolfSSH_SetKeyingCompletionCb(WOLFSSH_CTX*,
WS_CallbackKeyingCompletion);
WOLFSSH_API void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH*,
void*);

#define WS_CHANNEL_ID_SELF 0
#define WS_CHANNEL_ID_PEER 1
Expand Down
Loading