1. Starting to add in the Decryption and MAC Verification.

2. Fixed bug in getting the entire packet from the socket.
pull/1/head
John Safranek 2014-12-08 21:59:21 -08:00
parent 1c902a641e
commit 71bcd94c5f
4 changed files with 126 additions and 23 deletions

View File

@ -34,9 +34,9 @@
#include <wolfssh/ssh.h>
#include <wolfssh/internal.h>
#include <wolfssh/log.h>
#include <cyassl/ctaocrypt/aes.h>
#include <cyassl/ctaocrypt/asn.h>
#include <cyassl/ctaocrypt/rsa.h>
#include <cyassl/ctaocrypt/hmac.h>
/* convert opaque to 32 bit integer */
@ -124,6 +124,9 @@ const char* GetErrorString(int err)
case WS_BAD_FILE_E:
return "bad file";
case WS_DECRYPT_E:
return "decrypt error";
default:
return "Unknown error code";
}
@ -860,6 +863,21 @@ static int DoNewKeys(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
ssh->peerEncryptId = ssh->handshake->encryptId;
ssh->peerMacId = ssh->handshake->macId;
switch (ssh->peerEncryptId) {
case ID_NONE:
WLOG(WS_LOG_DEBUG, "DNK: peer using cipher none");
break;
case ID_AES128_CBC:
WLOG(WS_LOG_DEBUG, "DNK: peer using cipher aes128-cbc");
AesSetKey(&ssh->decryptCipher.aes, ssh->encKeyClient, ssh->encKeyClientSz, ssh->ivClient, AES_DECRYPTION);
break;
default:
WLOG(WS_LOG_DEBUG, "DNK: peer using cipher invalid");
break;
}
ssh->clientState = CLIENT_USING_KEYS;
return WS_SUCCESS;
@ -1122,6 +1140,8 @@ static int DoPacket(WOLFSSH* ssh)
/* Problem: len is equal to the amount of data left in the input buffer.
* The beginning part of that data is the packet we want to
* decode. The remainder is the pad and the MAC. */
/* Skip the packet_length field. */
idx += LENGTH_SZ;
padSz = buf[idx++];
payloadSz = ssh->curSz - PAD_LENGTH_SZ - padSz;
@ -1181,7 +1201,8 @@ static int DoPacket(WOLFSSH* ssh)
}
if (idx + padSz > len) {
return -1;
WLOG(WS_LOG_DEBUG, "Not enough data in buffer for pad.");
return WS_BUFFER_E;
}
idx += padSz;
@ -1190,12 +1211,46 @@ static int DoPacket(WOLFSSH* ssh)
}
static INLINE int Decrypt(WOLFSSH* ssh, uint8_t* plain, const uint8_t* input,
uint16_t sz)
{
int ret = WS_SUCCESS;
if (ssh == NULL || plain == NULL || input == NULL || sz == 0)
return WS_BAD_ARGUMENT;
switch (ssh->peerEncryptId) {
case ID_NONE:
WLOG(WS_LOG_DEBUG, "Decrypt none");
break;
case ID_AES128_CBC:
WLOG(WS_LOG_DEBUG, "Decrypt aes128-cbc");
if (AesCbcDecrypt(&ssh->decryptCipher.aes, plain, input, sz) < 0)
ret = WS_DECRYPT_E;
default:
WLOG(WS_LOG_DEBUG, "Decrypt invalid algo ID");
ret = WS_INVALID_ALGO_ID;
}
return ret;
}
static INLINE int VerifyMac(WOLFSSH* ssh)
{
(void)ssh;
/* Verify the buffer is big enough for the data plus the mac. */
return WS_SUCCESS;
}
int ProcessReply(WOLFSSH* ssh)
{
int ret = WS_FATAL_ERROR;
int readSz;
uint32_t readSz;
(void)readSz;
for (;;) {
switch (ssh->processReplyState) {
case PROCESS_INIT:
@ -1205,30 +1260,43 @@ int ProcessReply(WOLFSSH* ssh)
return ret;
}
ssh->processReplyState = PROCESS_PACKET_LENGTH;
WLOG(WS_LOG_DEBUG, "idx = %u, length = %u", ssh->inputBuffer.idx, ssh->inputBuffer.length);
/* Decrypt first block if encrypted */
/* Decrypt first block if encrypted */
ret = Decrypt(ssh,
ssh->inputBuffer.buffer + ssh->inputBuffer.idx,
ssh->inputBuffer.buffer + ssh->inputBuffer.idx,
readSz);
case PROCESS_PACKET_LENGTH:
/* Peek at the packet_length field. */
ato32(ssh->inputBuffer.buffer + ssh->inputBuffer.idx, &ssh->curSz);
ssh->inputBuffer.idx += LENGTH_SZ;
ssh->processReplyState = PROCESS_PACKET_FINISH;
case PROCESS_PACKET_FINISH:
WLOG(WS_LOG_DEBUG, "PR2: size = %d", ssh->curSz);
if ((ret = GetInputData(ssh, ssh->curSz)) < 0) {
readSz = ssh->curSz + LENGTH_SZ + ssh->macSz;
WLOG(WS_LOG_DEBUG, "PR2: size = %d", readSz);
if (readSz > 0) {
if ((ret = GetInputData(ssh, readSz)) < 0) {
return ret;
}
return ret;
ret = Decrypt(ssh,
ssh->inputBuffer.buffer + ssh->inputBuffer.idx + ssh->blockSz - LENGTH_SZ,
ssh->inputBuffer.buffer + ssh->inputBuffer.idx + ssh->blockSz - LENGTH_SZ,
ssh->curSz - ssh->blockSz);
ret = VerifyMac(ssh);
}
ssh->processReplyState = PROCESS_PACKET;
/* Decrypt rest of packet here */
/* Check MAC here. */
case PROCESS_PACKET:
if ( (ret = DoPacket(ssh)) < 0) {
return ret;
}
ssh->inputBuffer.idx += ssh->macSz;
break;
default:
@ -1349,8 +1417,8 @@ static int BundlePacket(WOLFSSH* ssh)
HmacSetKey(&hmac, SHA, ssh->macKeyServer, ssh->macKeyServerSz);
HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
HmacUpdate(&sha,);
HmacFinal(&sha, digest);
HmacUpdate(&hmac,);
HmacFinal(&hmac, digest);
WMEMCPY(, digest, SHA1_96_SIZE);
}
break;
@ -1371,8 +1439,6 @@ static int BundlePacket(WOLFSSH* ssh)
return WS_FATAL_ERROR;
}
ssh->seq++;
/* Encrypt the packet */
switch (ssh->encryptId) {
case ID_NONE:
@ -1706,6 +1772,21 @@ int SendNewKeys(WOLFSSH* ssh)
ssh->encryptId = ssh->handshake->encryptId;
ssh->macId = ssh->handshake->macId;
switch (ssh->encryptId) {
case ID_NONE:
WLOG(WS_LOG_DEBUG, "SNK: using cipher none");
break;
case ID_AES128_CBC:
WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-cbc");
AesSetKey(&ssh->encryptCipher.aes, ssh->encKeyServer, ssh->encKeyServerSz, ssh->ivServer, AES_ENCRYPTION);
break;
default:
WLOG(WS_LOG_DEBUG, "SNK: using cipher invalid");
break;
}
return WS_SUCCESS;
}

View File

@ -281,7 +281,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
case ACCEPT_BEGIN:
while (ssh->clientState < CLIENT_VERSION_DONE) {
if ( (ssh->error = ProcessClientVersion(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, "accept reply error: %d", ssh->error);
WLOG(WS_LOG_DEBUG, "accept reply error 1: %d", ssh->error);
return WS_FATAL_ERROR;
}
}
@ -296,7 +296,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
case SERVER_VERSION_SENT:
while (ssh->clientState < CLIENT_ALGO_DONE) {
if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, "accept reply error: %d", ssh->error);
WLOG(WS_LOG_DEBUG, "accept reply error 2: %d", ssh->error);
return WS_FATAL_ERROR;
}
}
@ -306,12 +306,22 @@ int wolfSSH_accept(WOLFSSH* ssh)
case SERVER_ALGO_SENT:
while (ssh->clientState < CLIENT_KEXDHINIT_DONE) {
if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, "accept reply error: %d", ssh->error);
WLOG(WS_LOG_DEBUG, "accept reply error 3: %d", ssh->error);
return WS_FATAL_ERROR;
}
}
SendKexDhReply(ssh);
break;
ssh->acceptState = SERVER_KEXDH_REPLY_SENT;
case SERVER_KEXDH_REPLY_SENT:
while (ssh->clientState < CLIENT_USING_KEYS) {
if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, "accept reply error 4: %d", ssh->error);
return WS_FATAL_ERROR;
}
}
SendNewKeys(ssh);
ssh->acceptState = SERVER_USING_KEYS;
}
return WS_FATAL_ERROR;

View File

@ -59,7 +59,8 @@ enum WS_ErrorCodes {
WS_UNIMPLEMENTED_E = -17,
WS_RSA_E = -18,
WS_BAD_FILE_E = -19,
WS_INVALID_ALGO_ID = -20
WS_INVALID_ALGO_ID = -20,
WS_DECRYPT_E = -21
};

View File

@ -34,6 +34,7 @@
#include <cyassl/ctaocrypt/sha.h>
#include <cyassl/ctaocrypt/random.h>
#include <cyassl/ctaocrypt/dh.h>
#include <cyassl/ctaocrypt/aes.h>
#if !defined (ALIGN16)
@ -135,6 +136,11 @@ struct WOLFSSH_CTX {
};
typedef struct Ciphers {
Aes aes;
} Ciphers;
typedef struct HandshakeInfo {
uint8_t kexId;
uint8_t pubKeyId;
@ -179,6 +185,9 @@ struct WOLFSSH {
uint8_t peerEncryptId;
uint8_t peerMacId;
Ciphers encryptCipher;
Ciphers decryptCipher;
Buffer inputBuffer;
Buffer outputBuffer;
RNG* rng;
@ -235,7 +244,9 @@ enum AcceptStates {
ACCEPT_CLIENT_ALGO_DONE,
SERVER_ALGO_SENT,
ACCEPT_CLIENT_KEXDH_INIT_DONE,
SERVER_KEXDH_ACCEPT_SENT
SERVER_KEXDH_REPLY_SENT,
SERVER_KEXDH_ACCEPT_SENT,
SERVER_USING_KEYS
};