mirror of https://github.com/wolfSSL/wolfssh.git
commit
4106ce3186
|
@ -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
|
||||
# | | |
|
||||
# +------+ | +---+
|
||||
# | | |
|
||||
|
|
|
@ -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;
|
||||
|
|
342
src/internal.c
342
src/internal.c
|
@ -382,8 +382,7 @@ static const NameIdPair NameIdMap[] = {
|
|||
|
||||
/* Encryption IDs */
|
||||
{ ID_AES128_CBC, "aes128-cbc" },
|
||||
{ ID_AES128_CTR, "aes128-ctr" },
|
||||
{ ID_AES128_GCM_WOLF, "aes128-gcm@wolfssl.com" },
|
||||
{ ID_AES128_GCM, "aes128-gcm@openssh.com" },
|
||||
|
||||
/* Integrity IDs */
|
||||
{ ID_HMAC_SHA1, "hmac-sha1" },
|
||||
|
@ -1070,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};
|
||||
|
@ -1109,7 +1108,7 @@ static INLINE uint8_t BlockSzForId(uint8_t id)
|
|||
{
|
||||
switch (id) {
|
||||
case ID_AES128_CBC:
|
||||
case ID_AES128_CTR:
|
||||
case ID_AES128_GCM:
|
||||
return AES_BLOCK_SIZE;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -1141,7 +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_CTR:
|
||||
case ID_AES128_GCM:
|
||||
return AES_BLOCK_SIZE;
|
||||
default:
|
||||
return 0;
|
||||
|
@ -1163,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;
|
||||
|
@ -1266,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1281,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");
|
||||
|
@ -1295,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;
|
||||
|
@ -1553,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) {
|
||||
|
@ -1568,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;
|
||||
|
@ -1783,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;
|
||||
|
@ -3026,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;
|
||||
|
@ -3033,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) {
|
||||
|
@ -3044,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:
|
||||
|
@ -3068,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;
|
||||
|
@ -3206,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;
|
||||
|
@ -3255,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)
|
||||
|
@ -3302,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";
|
||||
|
@ -3833,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) {
|
||||
|
@ -3848,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;
|
||||
|
|
|
@ -62,8 +62,7 @@ enum {
|
|||
|
||||
/* Encryption IDs */
|
||||
ID_AES128_CBC,
|
||||
ID_AES128_CTR,
|
||||
ID_AES128_GCM_WOLF,
|
||||
ID_AES128_GCM,
|
||||
|
||||
/* Integrity IDs */
|
||||
ID_HMAC_SHA1,
|
||||
|
@ -105,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
|
||||
|
@ -181,6 +183,7 @@ typedef struct HandshakeInfo {
|
|||
uint8_t macId;
|
||||
uint8_t hashId;
|
||||
uint8_t kexPacketFollows;
|
||||
uint8_t aeadMode;
|
||||
|
||||
uint8_t blockSz;
|
||||
uint8_t macSz;
|
||||
|
@ -231,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;
|
||||
|
|
|
@ -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*,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue