diff --git a/src/internal.c b/src/internal.c index 5f7ad6d..7ac5760 100644 --- a/src/internal.c +++ b/src/internal.c @@ -655,7 +655,7 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) return WS_INVALID_ALGO_ID; } - ssh->handshake->keyExchangeId = algoId; + ssh->handshake->kexId = algoId; /* Server Host Key Algorithms */ WLOG(WS_LOG_DEBUG, "DKI: Server Host Key Algorithms"); @@ -667,7 +667,7 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) return WS_INVALID_ALGO_ID; } - ssh->handshake->publicKeyId = algoId; + ssh->handshake->pubKeyId = algoId; /* Enc Algorithms - Client to Server */ WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Client to Server"); @@ -688,7 +688,7 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) return WS_INVALID_ALGO_ID; } - ssh->handshake->encryptionId = algoId; + ssh->handshake->encryptId = algoId; ssh->handshake->blockSz = ssh->ivClientSz = ssh->ivServerSz = BlockSzForId(algoId); ssh->encKeyClientSz = ssh->encKeyServerSz = KeySzForId(algoId); @@ -712,7 +712,7 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) return WS_INVALID_ALGO_ID; } - ssh->handshake->integrityId = algoId; + ssh->handshake->macId = algoId; ssh->handshake->macSz = MacSzForId(algoId); ssh->macKeyClientSz = ssh->macKeyServerSz = KeySzForId(algoId); @@ -850,6 +850,21 @@ static int DoKexDhInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) } +static int DoNewKeys(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx) +{ + (void)buf; + (void)len; + (void)idx; + + ssh->peerEncryptId = ssh->handshake->encryptId; + ssh->peerMacId = ssh->handshake->macId; + + ssh->clientState = CLIENT_USING_KEYS; + + return WS_SUCCESS; +} + + static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId, const uint8_t* k, uint32_t kSz, const uint8_t* h, uint32_t hSz, @@ -857,11 +872,19 @@ static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId, { uint32_t blocks, remainder; Sha sha; + uint8_t kPad = 0; + uint8_t pad = 0; + uint8_t kSzFlat[LENGTH_SZ]; + + if (k[0] & 0x80) kPad = 1; + c32toa(kSz, kSzFlat); blocks = keySz / SHA_DIGEST_SIZE; remainder = keySz % SHA_DIGEST_SIZE; InitSha(&sha); + ShaUpdate(&sha, kSzFlat, LENGTH_SZ); + if (kPad) ShaUpdate(&sha, &pad, 1); ShaUpdate(&sha, k, kSz); ShaUpdate(&sha, h, hSz); ShaUpdate(&sha, &keyId, sizeof(keyId)); @@ -882,6 +905,8 @@ static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId, for (curBlock = 1; curBlock < blocks; curBlock++) { InitSha(&sha); + ShaUpdate(&sha, kSzFlat, LENGTH_SZ); + if (kPad) ShaUpdate(&sha, &pad, 1); ShaUpdate(&sha, k, kSz); ShaUpdate(&sha, h, hSz); ShaUpdate(&sha, key, runningKeySz); @@ -892,6 +917,8 @@ static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId, if (remainder > 0) { uint8_t lastBlock[SHA_DIGEST_SIZE]; InitSha(&sha); + ShaUpdate(&sha, kSzFlat, LENGTH_SZ); + if (kPad) ShaUpdate(&sha, &pad, 1); ShaUpdate(&sha, k, kSz); ShaUpdate(&sha, h, hSz); ShaUpdate(&sha, key, runningKeySz); @@ -900,6 +927,9 @@ static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId, } } + printf("Key ID %c:", keyId); + DumpOctetString(key, keySz); + return 0; } @@ -935,6 +965,7 @@ static int DoPacket(WOLFSSH* ssh) uint8_t padSz; uint8_t msg; + WLOG(WS_LOG_DEBUG, "DoPacket sequence number: %d", ssh->peerSeq); /* 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. */ @@ -944,6 +975,22 @@ static int DoPacket(WOLFSSH* ssh) msg = buf[idx++]; switch (msg) { + case MSGID_DISCONNECT: + WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1); + break; + + case MSGID_IGNORE: + WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1); + break; + + case MSGID_UNIMPLEMENTED: + WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1); + break; + + case MSGID_DEBUG: + WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1); + break; + case MSGID_KEXINIT: { uint8_t scratchLen[LENGTH_SZ]; @@ -956,6 +1003,11 @@ static int DoPacket(WOLFSSH* ssh) } break; + case MSGID_NEWKEYS: + WLOG(WS_LOG_DEBUG, "Decoding MSGID_NEWKEYS (len = %d)", payloadSz - 1); + DoNewKeys(ssh, buf, payloadSz - 1, &idx); + break; + case MSGID_KEXDH_INIT: WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1); /* The mpint is 256 bytes long, the length is the standard 4 bytes, @@ -1116,24 +1168,44 @@ static int BundlePacket(WOLFSSH* ssh) uint8_t* output; uint32_t idx; uint8_t paddingSz; + uint8_t flatSeq[LENGTH_SZ]; output = ssh->outputBuffer.buffer; idx = ssh->outputBuffer.length; paddingSz = ssh->paddingSz; + c32toa(ssh->seq++, flatSeq); /* Add the padding */ WMEMSET(output + idx, 0, paddingSz); idx += paddingSz; /* Need to MAC the sequence number and the unencrypted packet */ - switch (ssh->integrityId) { + switch (ssh->macId) { case ID_NONE: break; #if 0 case ID_HMAC_SHA1_96: + { + Hmac hmac; + uint8_t digest[SHA_DIGEST_SIZE]; + + HmacSetKey(&hmac, SHA, ssh->macKeyServer, ssh->macKeyServerSz); + HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); + HmacUpdate(&sha,); + HmacFinal(&sha, digest); + WMEMCPY(, digest, SHA1_96_SIZE); + } break; case ID_HMAC_SHA1: + { + Hmac hmac; + + HmacSetKey(&hmac, SHA, ssh->macKeyServer, ssh->macKeyServerSz); + HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); + HmacUpdate(&hmac,); + HmacFinal(&hmac, ); + } break; #endif default: @@ -1144,7 +1216,7 @@ static int BundlePacket(WOLFSSH* ssh) ssh->seq++; /* Encrypt the packet */ - switch (ssh->encryptionId) { + switch (ssh->encryptId) { case ID_NONE: break; #if 0 @@ -1278,7 +1350,7 @@ int SendKexDhReply(WOLFSSH* ssh) InitDhKey(&dhKey); - switch (ssh->handshake->keyExchangeId) { + switch (ssh->handshake->kexId) { case ID_DH_GROUP1_SHA1: DhSetKey(&dhKey, dhPrimeGroup1, dhPrimeGroup1Sz, dhGenerator, dhGeneratorSz); @@ -1395,10 +1467,7 @@ int SendKexDhReply(WOLFSSH* ssh) FreeRsaKey(&rsaKey); sigBlockSz = (LENGTH_SZ * 2) + 7 + sigSz; - if (0) - GenerateKeys(ssh); - else - GenerateKeys(NULL); + GenerateKeys(ssh); /* Get the buffer, copy the packet data, once f is laid into the buffer, * add it to the hash and then add K. */ @@ -1454,6 +1523,30 @@ int SendKexDhReply(WOLFSSH* ssh) } +int SendNewKeys(WOLFSSH* ssh) +{ + uint8_t* output; + uint32_t idx = 0; + + PreparePacket(ssh, 1); + + output = ssh->outputBuffer.buffer; + idx = ssh->outputBuffer.length; + + output[idx] = MSGID_NEWKEYS; + + ssh->outputBuffer.length = idx; + + BundlePacket(ssh); + SendBuffered(ssh); + + ssh->encryptId = ssh->handshake->encryptId; + ssh->macId = ssh->handshake->macId; + + return WS_SUCCESS; +} + + #define LINE_WIDTH 16 void DumpOctetString(const uint8_t* input, uint32_t inputSz) { diff --git a/src/ssh.c b/src/ssh.c index 8e9efc0..8e15713 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -148,17 +148,15 @@ static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx) ssh->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */ ssh->ioWriteCtx = &ssh->wfd; /* set */ ssh->blockSz = 8; - ssh->keyExchangeId = ID_NONE; - ssh->publicKeyId = ID_NONE; - ssh->encryptionId = ID_NONE; - ssh->integrityId = ID_NONE; + ssh->encryptId = ID_NONE; + ssh->macId = ID_NONE; ssh->rng = rng; ssh->kSz = sizeof(ssh->k); ssh->handshake = handshake; - handshake->keyExchangeId = ID_NONE; - handshake->publicKeyId = ID_NONE; - handshake->encryptionId = ID_NONE; - handshake->integrityId = ID_NONE; + handshake->kexId = ID_NONE; + handshake->pubKeyId = ID_NONE; + handshake->encryptId = ID_NONE; + handshake->macId = ID_NONE; if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS || BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS || diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 71c0594..4028e9f 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -90,6 +90,7 @@ enum { #define PAD_LENGTH_SZ 1 #define BOOLEAN_SZ 1 #define MSG_ID_SZ 1 +#define SHA1_96_SZ (96/8) WOLFSSH_LOCAL uint8_t NameToId(const char*, uint32_t); @@ -134,10 +135,10 @@ struct WOLFSSH_CTX { typedef struct HandshakeInfo { - uint8_t keyExchangeId; - uint8_t publicKeyId; - uint8_t encryptionId; - uint8_t integrityId; + uint8_t kexId; + uint8_t pubKeyId; + uint8_t encryptId; + uint8_t macId; uint8_t kexPacketFollows; uint8_t blockSz; @@ -172,10 +173,10 @@ struct WOLFSSH { uint8_t connReset; uint8_t isClosed; - uint8_t keyExchangeId; /* not needed after handshake */ - uint8_t publicKeyId; - uint8_t encryptionId; - uint8_t integrityId; + uint8_t encryptId; + uint8_t macId; + uint8_t peerEncryptId; + uint8_t peerMacId; Buffer inputBuffer; Buffer outputBuffer; @@ -219,6 +220,7 @@ WOLFSSH_LOCAL int ProcessClientVersion(WOLFSSH*); WOLFSSH_LOCAL int SendServerVersion(WOLFSSH*); WOLFSSH_LOCAL int SendKexInit(WOLFSSH*); WOLFSSH_LOCAL int SendKexDhReply(WOLFSSH*); +WOLFSSH_LOCAL int SendNewKeys(WOLFSSH*); enum AcceptStates { @@ -236,7 +238,8 @@ enum ClientStates { CLIENT_BEGIN = 0, CLIENT_VERSION_DONE, CLIENT_ALGO_DONE, - CLIENT_KEXDHINIT_DONE + CLIENT_KEXDHINIT_DONE, + CLIENT_USING_KEYS };