1. Generates the session keys.

2. Starting to tie into the bulk encryption and MAC.
pull/1/head
John Safranek 2014-09-12 21:00:16 -07:00
parent 917c6a84c4
commit 2d959d7bea
3 changed files with 122 additions and 28 deletions

View File

@ -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)
{

View File

@ -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 ||

View File

@ -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
};