From be57ef6b95be522f9c0dc1acf9c56e70a27b06b9 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 6 Jul 2017 16:24:18 -0700 Subject: [PATCH 1/3] 1. Bump the version numbers. 2. Remove some unused option strings and constants. They may be distracting. --- configure.ac | 4 ++-- src/internal.c | 4 ---- wolfssh/internal.h | 2 -- wolfssh/version.h | 4 ++-- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/configure.ac b/configure.ac index c2cf5782..f8a13cc6 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Copyright (C) 2014-2017 wolfSSL Inc. # All right reserved. -AC_INIT([wolfssh], [1.1.0], [http://wolfssl.com], [wolfssh]) +AC_INIT([wolfssh], [1.2.0], [http://wolfssl.com], [wolfssh]) AC_PREREQ([2.63]) AC_CONFIG_AUX_DIR([build-aux]) @@ -17,7 +17,7 @@ AC_ARG_PROGRAM AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_HEADERS([src/config.h]) -WOLFSSH_LIBRARY_VERSION=3:0:2 +WOLFSSH_LIBRARY_VERSION=3:1:2 # | | | # +------+ | +---+ # | | | diff --git a/src/internal.c b/src/internal.c index d33d0f53..ac3b5ac9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -382,8 +382,6 @@ static const NameIdPair NameIdMap[] = { /* Encryption IDs */ { ID_AES128_CBC, "aes128-cbc" }, - { ID_AES128_CTR, "aes128-ctr" }, - { ID_AES128_GCM_WOLF, "aes128-gcm@wolfssl.com" }, /* Integrity IDs */ { ID_HMAC_SHA1, "hmac-sha1" }, @@ -1109,7 +1107,6 @@ static INLINE uint8_t BlockSzForId(uint8_t id) { switch (id) { case ID_AES128_CBC: - case ID_AES128_CTR: return AES_BLOCK_SIZE; default: return 0; @@ -1141,7 +1138,6 @@ static INLINE uint8_t KeySzForId(uint8_t id) case ID_HMAC_SHA2_256: return SHA256_DIGEST_SIZE; case ID_AES128_CBC: - case ID_AES128_CTR: return AES_BLOCK_SIZE; default: return 0; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 63b8d712..a3668131 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -62,8 +62,6 @@ enum { /* Encryption IDs */ ID_AES128_CBC, - ID_AES128_CTR, - ID_AES128_GCM_WOLF, /* Integrity IDs */ ID_HMAC_SHA1, diff --git a/wolfssh/version.h b/wolfssh/version.h index 4c55d8a6..80237420 100644 --- a/wolfssh/version.h +++ b/wolfssh/version.h @@ -33,8 +33,8 @@ extern "C" { #endif -#define LIBWOLFSSH_VERSION_STRING "1.1.0" -#define LIBWOLFSSH_VERSION_HEX 0x01001000 +#define LIBWOLFSSH_VERSION_STRING "1.2.0" +#define LIBWOLFSSH_VERSION_HEX 0x01002000 #ifdef __cplusplus } From b86bb31cdd01a6b72196fd273d5c63956960f63a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 7 Jul 2017 09:17:48 -0700 Subject: [PATCH 2/3] 1. Added in the code needed for AES-GCM. 2. Deleted the unused wolfSSH_worker() prototype. --- src/internal.c | 338 +++++++++++++++++++++++++++++++++------------ wolfssh/internal.h | 7 + wolfssh/ssh.h | 1 - 3 files changed, 254 insertions(+), 92 deletions(-) diff --git a/src/internal.c b/src/internal.c index ac3b5ac9..9c30f42a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -382,6 +382,7 @@ static const NameIdPair NameIdMap[] = { /* Encryption IDs */ { ID_AES128_CBC, "aes128-cbc" }, + { ID_AES128_GCM, "aes128-gcm@openssh.com" }, /* Integrity IDs */ { ID_HMAC_SHA1, "hmac-sha1" }, @@ -1068,7 +1069,7 @@ static int DoNameList(uint8_t* idList, uint32_t* idListSz, } -static const uint8_t cannedEncAlgo[] = {ID_AES128_CBC}; +static const uint8_t cannedEncAlgo[] = {ID_AES128_GCM, ID_AES128_CBC}; static const uint8_t cannedMacAlgo[] = {ID_HMAC_SHA2_256, ID_HMAC_SHA1_96, ID_HMAC_SHA1}; static const uint8_t cannedKeyAlgo[] = {ID_SSH_RSA}; @@ -1107,6 +1108,7 @@ static INLINE uint8_t BlockSzForId(uint8_t id) { switch (id) { case ID_AES128_CBC: + case ID_AES128_GCM: return AES_BLOCK_SIZE; default: return 0; @@ -1138,6 +1140,7 @@ static INLINE uint8_t KeySzForId(uint8_t id) case ID_HMAC_SHA2_256: return SHA256_DIGEST_SIZE; case ID_AES128_CBC: + case ID_AES128_GCM: return AES_BLOCK_SIZE; default: return 0; @@ -1159,6 +1162,12 @@ static INLINE uint8_t HashForId(uint8_t id) } +static INLINE uint8_t AeadModeForId(uint8_t id) +{ + return (id == ID_AES128_GCM); +} + + static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) { int ret = WS_SUCCESS; @@ -1262,13 +1271,22 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) } else { ssh->handshake->encryptId = algoId; - ssh->handshake->blockSz = - ssh->handshake->clientKeys.ivSz = - ssh->handshake->serverKeys.ivSz = - BlockSzForId(algoId); + ssh->handshake->aeadMode = AeadModeForId(algoId); + ssh->handshake->blockSz = BlockSzForId(algoId); ssh->handshake->clientKeys.encKeySz = ssh->handshake->serverKeys.encKeySz = KeySzForId(algoId); + if (!ssh->handshake->aeadMode) { + ssh->handshake->clientKeys.ivSz = + ssh->handshake->serverKeys.ivSz = + ssh->handshake->blockSz; + } + else { + ssh->handshake->clientKeys.ivSz = + ssh->handshake->serverKeys.ivSz = + AEAD_NONCE_SZ; + ssh->handshake->macSz = ssh->handshake->blockSz; + } } } @@ -1277,7 +1295,7 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Client to Server"); listSz = 2; ret = DoNameList(list, &listSz, buf, len, &begin); - if (ret == WS_SUCCESS) { + if (ret == WS_SUCCESS && !ssh->aeadMode) { algoId = MatchIdLists(list, listSz, cannedMacAlgo, cannedMacAlgoSz); if (algoId == ID_UNKNOWN) { WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S"); @@ -1291,7 +1309,7 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Server to Client"); listSz = 2; ret = DoNameList(list, &listSz, buf, len, &begin); - if (ret == WS_SUCCESS) { + if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) { if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) { WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C"); ret = WS_INVALID_ALGO_ID; @@ -1549,6 +1567,7 @@ static int DoNewKeys(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) ssh->peerMacId = ssh->handshake->macId; ssh->peerBlockSz = ssh->handshake->blockSz; ssh->peerMacSz = ssh->handshake->macSz; + ssh->peerAeadMode = ssh->handshake->aeadMode; WMEMCPY(&ssh->clientKeys, &ssh->handshake->clientKeys, sizeof(Keys)); switch (ssh->peerEncryptId) { @@ -1564,6 +1583,13 @@ static int DoNewKeys(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) ssh->clientKeys.iv, AES_DECRYPTION); break; + case ID_AES128_GCM: + WLOG(WS_LOG_DEBUG, "DNK: peer using cipher aes128-gcm"); + ret = wc_AesGcmSetKey(&ssh->decryptCipher.aes, + ssh->clientKeys.encKey, + ssh->clientKeys.encKeySz); + break; + default: WLOG(WS_LOG_DEBUG, "DNK: peer using cipher invalid"); break; @@ -1779,37 +1805,40 @@ static int GenerateKeys(WOLFSSH* ssh) sK->encKey, sK->encKeySz, ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->sessionId, ssh->sessionIdSz); - if (ret == WS_SUCCESS) - ret = GenerateKey(hashId, 'E', - cK->macKey, cK->macKeySz, - ssh->k, ssh->kSz, ssh->h, ssh->hSz, - ssh->sessionId, ssh->sessionIdSz); - if (ret == WS_SUCCESS) - ret = GenerateKey(hashId, 'F', - sK->macKey, sK->macKeySz, - ssh->k, ssh->kSz, ssh->h, ssh->hSz, - ssh->sessionId, ssh->sessionIdSz); - + if (!ssh->handshake->aeadMode) { + if (ret == WS_SUCCESS) + ret = GenerateKey(hashId, 'E', + cK->macKey, cK->macKeySz, + ssh->k, ssh->kSz, ssh->h, ssh->hSz, + ssh->sessionId, ssh->sessionIdSz); + if (ret == WS_SUCCESS) + ret = GenerateKey(hashId, 'F', + sK->macKey, sK->macKeySz, + ssh->k, ssh->kSz, ssh->h, ssh->hSz, + ssh->sessionId, ssh->sessionIdSz); + } #ifdef SHOW_SECRETS - printf("\n** Showing Secrets **\nK:\n"); - DumpOctetString(ssh->k, ssh->kSz); - printf("H:\n"); - DumpOctetString(ssh->h, ssh->hSz); - printf("Session ID:\n"); - DumpOctetString(ssh->sessionId, ssh->sessionIdSz); - printf("A:\n"); - DumpOctetString(cK->iv, cK->ivSz); - printf("B:\n"); - DumpOctetString(sK->iv, sK->ivSz); - printf("C:\n"); - DumpOctetString(cK->encKey, cK->encKeySz); - printf("D:\n"); - DumpOctetString(sK->encKey, sK->encKeySz); - printf("E:\n"); - DumpOctetString(cK->macKey, cK->macKeySz); - printf("F:\n"); - DumpOctetString(sK->macKey, sK->macKeySz); - printf("\n"); + if (ret == WS_SUCCESS) { + printf("\n** Showing Secrets **\nK:\n"); + DumpOctetString(ssh->k, ssh->kSz); + printf("H:\n"); + DumpOctetString(ssh->h, ssh->hSz); + printf("Session ID:\n"); + DumpOctetString(ssh->sessionId, ssh->sessionIdSz); + printf("A:\n"); + DumpOctetString(cK->iv, cK->ivSz); + printf("B:\n"); + DumpOctetString(sK->iv, sK->ivSz); + printf("C:\n"); + DumpOctetString(cK->encKey, cK->encKeySz); + printf("D:\n"); + DumpOctetString(sK->encKey, sK->encKeySz); + printf("E:\n"); + DumpOctetString(cK->macKey, cK->macKeySz); + printf("F:\n"); + DumpOctetString(sK->macKey, sK->macKeySz); + printf("\n"); + } #endif /* SHOW_SECRETS */ return ret; @@ -3022,6 +3051,75 @@ static INLINE int VerifyMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz, } +static INLINE void AeadIncrementExpIv(uint8_t* iv) +{ + int i; + + iv += AEAD_IMP_IV_SZ; + + for (i = AEAD_EXP_IV_SZ-1; i >= 0; i--) { + if (++iv[i]) return; + } +} + + +static INLINE int EncryptAead(WOLFSSH* ssh, uint8_t* cipher, + const uint8_t* input, uint16_t sz, + uint8_t* authTag, const uint8_t* auth, + uint16_t authSz) +{ + int ret = WS_SUCCESS; + + if (ssh == NULL || cipher == NULL || input == NULL || sz == 0 || + authTag == NULL || auth == NULL || authSz == 0) + return WS_BAD_ARGUMENT; + + WLOG(WS_LOG_DEBUG, "EncryptAead %s", IdToName(ssh->encryptId)); + + if (ssh->encryptId == ID_AES128_GCM) { + ret = wc_AesGcmEncrypt(&ssh->encryptCipher.aes, cipher, input, sz, + ssh->serverKeys.iv, ssh->serverKeys.ivSz, + authTag, ssh->macSz, auth, authSz); + } + else + ret = WS_INVALID_ALGO_ID; + + AeadIncrementExpIv(ssh->serverKeys.iv); + ssh->txCount += sz; + + return ret; +} + + +static INLINE int DecryptAead(WOLFSSH* ssh, uint8_t* plain, + const uint8_t* input, uint16_t sz, + const uint8_t* authTag, const uint8_t* auth, + uint16_t authSz) +{ + int ret = WS_SUCCESS; + + if (ssh == NULL || plain == NULL || input == NULL || sz == 0 || + authTag == NULL || auth == NULL || authSz == 0) + return WS_BAD_ARGUMENT; + + WLOG(WS_LOG_DEBUG, "DecryptAead %s", IdToName(ssh->peerEncryptId)); + + if (ssh->peerEncryptId == ID_AES128_GCM) { + ret = wc_AesGcmDecrypt(&ssh->decryptCipher.aes, plain, input, sz, + ssh->clientKeys.iv, ssh->clientKeys.ivSz, + authTag, ssh->peerMacSz, auth, authSz); + } + else + ret = WS_INVALID_ALGO_ID; + + AeadIncrementExpIv(ssh->clientKeys.iv); + ssh->rxCount += sz; + HighwaterCheck(ssh, WOLFSSH_HWSIDE_RECEIVE); + + return ret; +} + + int DoReceive(WOLFSSH* ssh) { int ret = WS_FATAL_ERROR; @@ -3029,6 +3127,7 @@ int DoReceive(WOLFSSH* ssh) uint32_t readSz; uint8_t peerBlockSz = ssh->peerBlockSz; uint8_t peerMacSz = ssh->peerMacSz; + uint8_t aeadMode = ssh->peerAeadMode; for (;;) { switch (ssh->processReplyState) { @@ -3040,14 +3139,18 @@ int DoReceive(WOLFSSH* ssh) } ssh->processReplyState = PROCESS_PACKET_LENGTH; - /* Decrypt first block if encrypted */ - ret = Decrypt(ssh, - ssh->inputBuffer.buffer + ssh->inputBuffer.idx, - ssh->inputBuffer.buffer + ssh->inputBuffer.idx, - readSz); - if (ret != WS_SUCCESS) { - WLOG(WS_LOG_DEBUG, "PR: First decrypt fail"); - return ret; + if (!aeadMode) { + /* Decrypt first block if encrypted */ + ret = Decrypt(ssh, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx, + readSz); + if (ret != WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "PR: First decrypt fail"); + return ret; + } } case PROCESS_PACKET_LENGTH: @@ -3064,35 +3167,59 @@ int DoReceive(WOLFSSH* ssh) return ret; } - if (ssh->curSz + LENGTH_SZ - peerBlockSz > 0) { - ret = Decrypt(ssh, - ssh->inputBuffer.buffer + - ssh->inputBuffer.idx + peerBlockSz, - ssh->inputBuffer.buffer + - ssh->inputBuffer.idx + peerBlockSz, - ssh->curSz + LENGTH_SZ - peerBlockSz); + if (!aeadMode) { + if (ssh->curSz + LENGTH_SZ - peerBlockSz > 0) { + ret = Decrypt(ssh, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx + peerBlockSz, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx + peerBlockSz, + ssh->curSz + LENGTH_SZ - peerBlockSz); + } + else { + WLOG(WS_LOG_INFO, + "Not trying to decrypt short message."); + } + + /* Verify the buffer is big enough for the data and mac. + * Even if the decrypt step fails, verify the MAC anyway. + * This keeps consistent timing. */ + verifyResult = VerifyMac(ssh, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx, + ssh->curSz + LENGTH_SZ, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx + + LENGTH_SZ + ssh->curSz); + if (ret != WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "PR: Decrypt fail"); + return ret; + } + if (verifyResult != WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "PR: VerifyMac fail"); + return ret; + } } else { - WLOG(WS_LOG_INFO, "Not trying to decrypt short message."); - } + ret = DecryptAead(ssh, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx + + LENGTH_SZ, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx + + LENGTH_SZ, + ssh->curSz, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx + + ssh->curSz + LENGTH_SZ, + ssh->inputBuffer.buffer + + ssh->inputBuffer.idx, + LENGTH_SZ); - /* Verify the buffer is big enough for the data and mac. - * Even if the decrypt step fails, verify the MAC anyway. - * This keeps consistent timing. */ - verifyResult = VerifyMac(ssh, - ssh->inputBuffer.buffer + - ssh->inputBuffer.idx, - ssh->curSz + LENGTH_SZ, - ssh->inputBuffer.buffer + - ssh->inputBuffer.idx + - LENGTH_SZ + ssh->curSz); - if (ret != WS_SUCCESS) { - WLOG(WS_LOG_DEBUG, "PR: Decrypt fail"); - return ret; - } - if (verifyResult != WS_SUCCESS) { - WLOG(WS_LOG_DEBUG, "PR: VerifyMac fail"); - return ret; + if (ret != WS_SUCCESS) { + WLOG(WS_LOG_DEBUG, "PR: DecryptAead fail"); + return ret; + } } } ssh->processReplyState = PROCESS_PACKET; @@ -3202,7 +3329,8 @@ static int PreparePacket(WOLFSSH* ssh, uint32_t payloadSz) if (ret == WS_SUCCESS) { /* Minimum value for paddingSz is 4. */ paddingSz = ssh->blockSz - - (LENGTH_SZ + PAD_LENGTH_SZ + payloadSz) % ssh->blockSz; + ((ssh->aeadMode ? 0 : LENGTH_SZ) + + PAD_LENGTH_SZ + payloadSz) % ssh->blockSz; if (paddingSz < MIN_PAD_LENGTH) paddingSz += ssh->blockSz; ssh->paddingSz = paddingSz; @@ -3251,27 +3379,47 @@ static int BundlePacket(WOLFSSH* ssh) ret = WS_CRYPTO_FAILED; } - if (ret == WS_SUCCESS) { - idx += paddingSz; - ret = CreateMac(ssh, ssh->outputBuffer.buffer + ssh->packetStartIdx, - ssh->outputBuffer.length - - ssh->packetStartIdx + paddingSz, - output + idx); - } - else { - WLOG(WS_LOG_DEBUG, "BP: failed to add padding"); - } + if (!ssh->aeadMode) { + if (ret == WS_SUCCESS) { + idx += paddingSz; + ret = CreateMac(ssh, ssh->outputBuffer.buffer + ssh->packetStartIdx, + ssh->outputBuffer.length - + ssh->packetStartIdx + paddingSz, + output + idx); + } + else { + WLOG(WS_LOG_DEBUG, "BP: failed to add padding"); + } - if (ret == WS_SUCCESS) { - idx += ssh->macSz; - ret = Encrypt(ssh, - ssh->outputBuffer.buffer + ssh->packetStartIdx, - ssh->outputBuffer.buffer + ssh->packetStartIdx, - ssh->outputBuffer.length - - ssh->packetStartIdx + paddingSz); + if (ret == WS_SUCCESS) { + idx += ssh->macSz; + ret = Encrypt(ssh, + ssh->outputBuffer.buffer + ssh->packetStartIdx, + ssh->outputBuffer.buffer + ssh->packetStartIdx, + ssh->outputBuffer.length - + ssh->packetStartIdx + paddingSz); + } + else { + WLOG(WS_LOG_DEBUG, "BP: failed to generate mac"); + } } else { - WLOG(WS_LOG_DEBUG, "BP: failed to generate mac"); + if (ret == WS_SUCCESS) { + idx += paddingSz; + ret = EncryptAead(ssh, + ssh->outputBuffer.buffer + + ssh->packetStartIdx + LENGTH_SZ, + ssh->outputBuffer.buffer + + ssh->packetStartIdx + LENGTH_SZ, + ssh->outputBuffer.length - + ssh->packetStartIdx + paddingSz - + LENGTH_SZ, + output + idx, + ssh->outputBuffer.buffer + + ssh->packetStartIdx, + LENGTH_SZ); + idx += ssh->macSz; + } } if (ret == WS_SUCCESS) @@ -3298,7 +3446,7 @@ static INLINE void CopyNameList(uint8_t* buf, uint32_t* idx, } -static const char cannedEncAlgoNames[] = "aes128-cbc"; +static const char cannedEncAlgoNames[] = "aes128-gcm@openssh.com,aes128-cbc"; static const char cannedMacAlgoNames[] = "hmac-sha2-256,hmac-sha1-96," "hmac-sha1"; static const char cannedKeyAlgoNames[] = "ssh-rsa"; @@ -3829,6 +3977,7 @@ int SendNewKeys(WOLFSSH* ssh) ssh->encryptId = ssh->handshake->encryptId; ssh->macSz = ssh->handshake->macSz; ssh->macId = ssh->handshake->macId; + ssh->aeadMode = ssh->handshake->aeadMode; WMEMCPY(&ssh->serverKeys, &ssh->handshake->serverKeys, sizeof(Keys)); switch (ssh->encryptId) { @@ -3844,6 +3993,13 @@ int SendNewKeys(WOLFSSH* ssh) ssh->serverKeys.iv, AES_ENCRYPTION); break; + case ID_AES128_GCM: + WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-gcm"); + ret = wc_AesGcmSetKey(&ssh->encryptCipher.aes, + ssh->serverKeys.encKey, + ssh->serverKeys.encKeySz); + break; + default: WLOG(WS_LOG_DEBUG, "SNK: using cipher invalid"); ret = WS_INVALID_ALGO_ID; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index a3668131..77c0c6b2 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -62,6 +62,7 @@ enum { /* Encryption IDs */ ID_AES128_CBC, + ID_AES128_GCM, /* Integrity IDs */ ID_HMAC_SHA1, @@ -103,6 +104,9 @@ enum { #define UINT32_SZ 4 #define SSH_PROTO_SZ 7 /* "SSH-2.0" */ #define SSH_PROTO_EOL_SZ 2 /* Just the CRLF */ +#define AEAD_IMP_IV_SZ 4 +#define AEAD_EXP_IV_SZ 8 +#define AEAD_NONCE_SZ (AEAD_IMP_IV_SZ+AEAD_EXP_IV_SZ) #ifndef DEFAULT_HIGHWATER_MARK #define DEFAULT_HIGHWATER_MARK ((1024 * 1024 * 1024) - (32 * 1024)) #endif @@ -179,6 +183,7 @@ typedef struct HandshakeInfo { uint8_t macId; uint8_t hashId; uint8_t kexPacketFollows; + uint8_t aeadMode; uint8_t blockSz; uint8_t macSz; @@ -229,10 +234,12 @@ struct WOLFSSH { uint8_t encryptId; uint8_t macId; uint8_t macSz; + uint8_t aeadMode; uint8_t peerBlockSz; uint8_t peerEncryptId; uint8_t peerMacId; uint8_t peerMacSz; + uint8_t peerAeadMode; Ciphers encryptCipher; Ciphers decryptCipher; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 9348867f..934799dc 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -133,7 +133,6 @@ WOLFSSH_API int wolfSSH_stream_read(WOLFSSH*, uint8_t*, uint32_t); WOLFSSH_API int wolfSSH_stream_send(WOLFSSH*, uint8_t*, uint32_t); WOLFSSH_API int wolfSSH_channel_read(WOLFSSH_CHANNEL*, uint8_t*, uint32_t); WOLFSSH_API int wolfSSH_channel_send(WOLFSSH_CHANNEL*, uint8_t*, uint32_t); -WOLFSSH_API int wolfSSH_worker(WOLFSSH*); WOLFSSH_API int wolfSSH_TriggerKeyExchange(WOLFSSH*); WOLFSSH_API void wolfSSH_GetStats(WOLFSSH*, From 686184d34d463730e9fb0dece1aa44dead30dad6 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 11 Jul 2017 09:33:33 -0700 Subject: [PATCH 3/3] Update echoserver for an option to allow multiple connections or single connections to ease memory testing. --- examples/echoserver/echoserver.c | 112 +++++++++++++++++++++++++++++-- 1 file changed, 108 insertions(+), 4 deletions(-) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index a95116fa..b418a379 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -111,6 +111,75 @@ typedef struct { #endif +#define MY_EX_USAGE 2 + +extern int myoptind; +extern char* myoptarg; + +static INLINE int mygetopt(int argc, char** argv, const char* optstring) +{ + static char* next = NULL; + + char c; + char* cp; + + if (myoptind == 0) + next = NULL; /* we're starting new/over */ + + if (next == NULL || *next == '\0') { + if (myoptind == 0) + myoptind++; + + if (myoptind >= argc || argv[myoptind][0] != '-' || + argv[myoptind][1] == '\0') { + myoptarg = NULL; + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + if (strcmp(argv[myoptind], "--") == 0) { + myoptind++; + myoptarg = NULL; + + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + next = argv[myoptind]; + next++; /* skip - */ + myoptind++; + } + + c = *next++; + /* The C++ strchr can return a different value */ + cp = (char*)strchr(optstring, c); + + if (cp == NULL || c == ':') + return '?'; + + cp++; + + if (*cp == ':') { + if (*next != '\0') { + myoptarg = next; + next = NULL; + } + else if (myoptind < argc) { + myoptarg = argv[myoptind]; + myoptind++; + } + else + return '?'; + } + + return c; +} + + static INLINE WS_NORETURN void err_sys(const char* msg) { printf("server error: %s\n", msg); @@ -663,18 +732,45 @@ static int wsUserAuth(uint8_t authType, } -int main(void) +static void ShowUsage(void) +{ + printf("echoserver %s\n", LIBWOLFSSH_VERSION_STRING); + printf("-h Help, print this usage\n"); + printf("-m Allow multiple connections\n"); +} + + +int main(int argc, char** argv) { WOLFSSH_CTX* ctx = NULL; PwMapList pwMapList; SOCKET_T listenFd = 0; uint32_t defaultHighwater = EXAMPLE_HIGHWATER_MARK; uint32_t threadCount = 0; + int multipleConnections = 0; + char ch; #ifdef DEBUG_WOLFSSH wolfSSH_Debugging_ON(); #endif + while ((ch = mygetopt(argc, argv, "hm")) != -1) { + switch (ch) { + case 'h' : + ShowUsage(); + exit(EXIT_SUCCESS); + + case 'm' : + multipleConnections = 1; + break; + + default: + ShowUsage(); + exit(MY_EX_USAGE); + } + } + myoptind = 0; /* reset for test cases */ + if (wolfSSH_Init() != WS_SUCCESS) { fprintf(stderr, "Couldn't initialize wolfSSH.\n"); exit(EXIT_FAILURE); @@ -721,7 +817,7 @@ int main(void) if (listen(listenFd, 5) != 0) err_sys("tcp listen failed"); - for (;;) { + do { SOCKET_T clientFd = 0; SOCKADDR_IN_T clientAddr; SOCKLEN_T clientAddrSz = sizeof(clientAddr); @@ -759,8 +855,13 @@ int main(void) threadCtx->id = threadCount++; pthread_create(&thread, 0, server_worker, threadCtx); - pthread_detach(thread); - } + + if (multipleConnections) + pthread_detach(thread); + else + pthread_join(thread, NULL); + + } while (multipleConnections); PwMapListDelete(&pwMapList); wolfSSH_CTX_free(ctx); @@ -771,3 +872,6 @@ int main(void) return 0; } + +int myoptind = 0; +char* myoptarg = NULL;