mirror of https://github.com/wolfSSL/wolfssh.git
1. Generates the session keys.
2. Starting to tie into the bulk encryption and MAC.pull/1/head
parent
917c6a84c4
commit
2d959d7bea
115
src/internal.c
115
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;
|
return WS_INVALID_ALGO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh->handshake->keyExchangeId = algoId;
|
ssh->handshake->kexId = algoId;
|
||||||
|
|
||||||
/* Server Host Key Algorithms */
|
/* Server Host Key Algorithms */
|
||||||
WLOG(WS_LOG_DEBUG, "DKI: 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;
|
return WS_INVALID_ALGO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh->handshake->publicKeyId = algoId;
|
ssh->handshake->pubKeyId = algoId;
|
||||||
|
|
||||||
/* Enc Algorithms - Client to Server */
|
/* Enc Algorithms - Client to Server */
|
||||||
WLOG(WS_LOG_DEBUG, "DKI: 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;
|
return WS_INVALID_ALGO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh->handshake->encryptionId = algoId;
|
ssh->handshake->encryptId = algoId;
|
||||||
ssh->handshake->blockSz = ssh->ivClientSz = ssh->ivServerSz
|
ssh->handshake->blockSz = ssh->ivClientSz = ssh->ivServerSz
|
||||||
= BlockSzForId(algoId);
|
= BlockSzForId(algoId);
|
||||||
ssh->encKeyClientSz = ssh->encKeyServerSz = KeySzForId(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;
|
return WS_INVALID_ALGO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh->handshake->integrityId = algoId;
|
ssh->handshake->macId = algoId;
|
||||||
ssh->handshake->macSz = MacSzForId(algoId);
|
ssh->handshake->macSz = MacSzForId(algoId);
|
||||||
ssh->macKeyClientSz = ssh->macKeyServerSz = KeySzForId(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,
|
static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId,
|
||||||
const uint8_t* k, uint32_t kSz,
|
const uint8_t* k, uint32_t kSz,
|
||||||
const uint8_t* h, uint32_t hSz,
|
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;
|
uint32_t blocks, remainder;
|
||||||
Sha sha;
|
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;
|
blocks = keySz / SHA_DIGEST_SIZE;
|
||||||
remainder = keySz % SHA_DIGEST_SIZE;
|
remainder = keySz % SHA_DIGEST_SIZE;
|
||||||
|
|
||||||
InitSha(&sha);
|
InitSha(&sha);
|
||||||
|
ShaUpdate(&sha, kSzFlat, LENGTH_SZ);
|
||||||
|
if (kPad) ShaUpdate(&sha, &pad, 1);
|
||||||
ShaUpdate(&sha, k, kSz);
|
ShaUpdate(&sha, k, kSz);
|
||||||
ShaUpdate(&sha, h, hSz);
|
ShaUpdate(&sha, h, hSz);
|
||||||
ShaUpdate(&sha, &keyId, sizeof(keyId));
|
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++) {
|
for (curBlock = 1; curBlock < blocks; curBlock++) {
|
||||||
InitSha(&sha);
|
InitSha(&sha);
|
||||||
|
ShaUpdate(&sha, kSzFlat, LENGTH_SZ);
|
||||||
|
if (kPad) ShaUpdate(&sha, &pad, 1);
|
||||||
ShaUpdate(&sha, k, kSz);
|
ShaUpdate(&sha, k, kSz);
|
||||||
ShaUpdate(&sha, h, hSz);
|
ShaUpdate(&sha, h, hSz);
|
||||||
ShaUpdate(&sha, key, runningKeySz);
|
ShaUpdate(&sha, key, runningKeySz);
|
||||||
|
@ -892,6 +917,8 @@ static int GenerateKey(uint8_t* key, uint32_t keySz, uint8_t keyId,
|
||||||
if (remainder > 0) {
|
if (remainder > 0) {
|
||||||
uint8_t lastBlock[SHA_DIGEST_SIZE];
|
uint8_t lastBlock[SHA_DIGEST_SIZE];
|
||||||
InitSha(&sha);
|
InitSha(&sha);
|
||||||
|
ShaUpdate(&sha, kSzFlat, LENGTH_SZ);
|
||||||
|
if (kPad) ShaUpdate(&sha, &pad, 1);
|
||||||
ShaUpdate(&sha, k, kSz);
|
ShaUpdate(&sha, k, kSz);
|
||||||
ShaUpdate(&sha, h, hSz);
|
ShaUpdate(&sha, h, hSz);
|
||||||
ShaUpdate(&sha, key, runningKeySz);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,6 +965,7 @@ static int DoPacket(WOLFSSH* ssh)
|
||||||
uint8_t padSz;
|
uint8_t padSz;
|
||||||
uint8_t msg;
|
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.
|
/* 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
|
* The beginning part of that data is the packet we want to
|
||||||
* decode. The remainder is the pad and the MAC. */
|
* decode. The remainder is the pad and the MAC. */
|
||||||
|
@ -944,6 +975,22 @@ static int DoPacket(WOLFSSH* ssh)
|
||||||
msg = buf[idx++];
|
msg = buf[idx++];
|
||||||
switch (msg) {
|
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:
|
case MSGID_KEXINIT:
|
||||||
{
|
{
|
||||||
uint8_t scratchLen[LENGTH_SZ];
|
uint8_t scratchLen[LENGTH_SZ];
|
||||||
|
@ -956,6 +1003,11 @@ static int DoPacket(WOLFSSH* ssh)
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case MSGID_KEXDH_INIT:
|
||||||
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1);
|
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,
|
/* 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;
|
uint8_t* output;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
uint8_t paddingSz;
|
uint8_t paddingSz;
|
||||||
|
uint8_t flatSeq[LENGTH_SZ];
|
||||||
|
|
||||||
output = ssh->outputBuffer.buffer;
|
output = ssh->outputBuffer.buffer;
|
||||||
idx = ssh->outputBuffer.length;
|
idx = ssh->outputBuffer.length;
|
||||||
paddingSz = ssh->paddingSz;
|
paddingSz = ssh->paddingSz;
|
||||||
|
c32toa(ssh->seq++, flatSeq);
|
||||||
|
|
||||||
/* Add the padding */
|
/* Add the padding */
|
||||||
WMEMSET(output + idx, 0, paddingSz);
|
WMEMSET(output + idx, 0, paddingSz);
|
||||||
idx += paddingSz;
|
idx += paddingSz;
|
||||||
|
|
||||||
/* Need to MAC the sequence number and the unencrypted packet */
|
/* Need to MAC the sequence number and the unencrypted packet */
|
||||||
switch (ssh->integrityId) {
|
switch (ssh->macId) {
|
||||||
case ID_NONE:
|
case ID_NONE:
|
||||||
break;
|
break;
|
||||||
#if 0
|
#if 0
|
||||||
case ID_HMAC_SHA1_96:
|
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;
|
break;
|
||||||
|
|
||||||
case ID_HMAC_SHA1:
|
case ID_HMAC_SHA1:
|
||||||
|
{
|
||||||
|
Hmac hmac;
|
||||||
|
|
||||||
|
HmacSetKey(&hmac, SHA, ssh->macKeyServer, ssh->macKeyServerSz);
|
||||||
|
HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
|
||||||
|
HmacUpdate(&hmac,);
|
||||||
|
HmacFinal(&hmac, );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
@ -1144,7 +1216,7 @@ static int BundlePacket(WOLFSSH* ssh)
|
||||||
ssh->seq++;
|
ssh->seq++;
|
||||||
|
|
||||||
/* Encrypt the packet */
|
/* Encrypt the packet */
|
||||||
switch (ssh->encryptionId) {
|
switch (ssh->encryptId) {
|
||||||
case ID_NONE:
|
case ID_NONE:
|
||||||
break;
|
break;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -1278,7 +1350,7 @@ int SendKexDhReply(WOLFSSH* ssh)
|
||||||
|
|
||||||
InitDhKey(&dhKey);
|
InitDhKey(&dhKey);
|
||||||
|
|
||||||
switch (ssh->handshake->keyExchangeId) {
|
switch (ssh->handshake->kexId) {
|
||||||
case ID_DH_GROUP1_SHA1:
|
case ID_DH_GROUP1_SHA1:
|
||||||
DhSetKey(&dhKey, dhPrimeGroup1, dhPrimeGroup1Sz,
|
DhSetKey(&dhKey, dhPrimeGroup1, dhPrimeGroup1Sz,
|
||||||
dhGenerator, dhGeneratorSz);
|
dhGenerator, dhGeneratorSz);
|
||||||
|
@ -1395,10 +1467,7 @@ int SendKexDhReply(WOLFSSH* ssh)
|
||||||
FreeRsaKey(&rsaKey);
|
FreeRsaKey(&rsaKey);
|
||||||
sigBlockSz = (LENGTH_SZ * 2) + 7 + sigSz;
|
sigBlockSz = (LENGTH_SZ * 2) + 7 + sigSz;
|
||||||
|
|
||||||
if (0)
|
GenerateKeys(ssh);
|
||||||
GenerateKeys(ssh);
|
|
||||||
else
|
|
||||||
GenerateKeys(NULL);
|
|
||||||
|
|
||||||
/* Get the buffer, copy the packet data, once f is laid into the buffer,
|
/* Get the buffer, copy the packet data, once f is laid into the buffer,
|
||||||
* add it to the hash and then add K. */
|
* 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
|
#define LINE_WIDTH 16
|
||||||
void DumpOctetString(const uint8_t* input, uint32_t inputSz)
|
void DumpOctetString(const uint8_t* input, uint32_t inputSz)
|
||||||
{
|
{
|
||||||
|
|
14
src/ssh.c
14
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->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */
|
||||||
ssh->ioWriteCtx = &ssh->wfd; /* set */
|
ssh->ioWriteCtx = &ssh->wfd; /* set */
|
||||||
ssh->blockSz = 8;
|
ssh->blockSz = 8;
|
||||||
ssh->keyExchangeId = ID_NONE;
|
ssh->encryptId = ID_NONE;
|
||||||
ssh->publicKeyId = ID_NONE;
|
ssh->macId = ID_NONE;
|
||||||
ssh->encryptionId = ID_NONE;
|
|
||||||
ssh->integrityId = ID_NONE;
|
|
||||||
ssh->rng = rng;
|
ssh->rng = rng;
|
||||||
ssh->kSz = sizeof(ssh->k);
|
ssh->kSz = sizeof(ssh->k);
|
||||||
ssh->handshake = handshake;
|
ssh->handshake = handshake;
|
||||||
handshake->keyExchangeId = ID_NONE;
|
handshake->kexId = ID_NONE;
|
||||||
handshake->publicKeyId = ID_NONE;
|
handshake->pubKeyId = ID_NONE;
|
||||||
handshake->encryptionId = ID_NONE;
|
handshake->encryptId = ID_NONE;
|
||||||
handshake->integrityId = ID_NONE;
|
handshake->macId = ID_NONE;
|
||||||
|
|
||||||
if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS ||
|
if (BufferInit(&ssh->inputBuffer, 0, ctx->heap) != WS_SUCCESS ||
|
||||||
BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS ||
|
BufferInit(&ssh->outputBuffer, 0, ctx->heap) != WS_SUCCESS ||
|
||||||
|
|
|
@ -90,6 +90,7 @@ enum {
|
||||||
#define PAD_LENGTH_SZ 1
|
#define PAD_LENGTH_SZ 1
|
||||||
#define BOOLEAN_SZ 1
|
#define BOOLEAN_SZ 1
|
||||||
#define MSG_ID_SZ 1
|
#define MSG_ID_SZ 1
|
||||||
|
#define SHA1_96_SZ (96/8)
|
||||||
|
|
||||||
|
|
||||||
WOLFSSH_LOCAL uint8_t NameToId(const char*, uint32_t);
|
WOLFSSH_LOCAL uint8_t NameToId(const char*, uint32_t);
|
||||||
|
@ -134,10 +135,10 @@ struct WOLFSSH_CTX {
|
||||||
|
|
||||||
|
|
||||||
typedef struct HandshakeInfo {
|
typedef struct HandshakeInfo {
|
||||||
uint8_t keyExchangeId;
|
uint8_t kexId;
|
||||||
uint8_t publicKeyId;
|
uint8_t pubKeyId;
|
||||||
uint8_t encryptionId;
|
uint8_t encryptId;
|
||||||
uint8_t integrityId;
|
uint8_t macId;
|
||||||
uint8_t kexPacketFollows;
|
uint8_t kexPacketFollows;
|
||||||
|
|
||||||
uint8_t blockSz;
|
uint8_t blockSz;
|
||||||
|
@ -172,10 +173,10 @@ struct WOLFSSH {
|
||||||
uint8_t connReset;
|
uint8_t connReset;
|
||||||
uint8_t isClosed;
|
uint8_t isClosed;
|
||||||
|
|
||||||
uint8_t keyExchangeId; /* not needed after handshake */
|
uint8_t encryptId;
|
||||||
uint8_t publicKeyId;
|
uint8_t macId;
|
||||||
uint8_t encryptionId;
|
uint8_t peerEncryptId;
|
||||||
uint8_t integrityId;
|
uint8_t peerMacId;
|
||||||
|
|
||||||
Buffer inputBuffer;
|
Buffer inputBuffer;
|
||||||
Buffer outputBuffer;
|
Buffer outputBuffer;
|
||||||
|
@ -219,6 +220,7 @@ WOLFSSH_LOCAL int ProcessClientVersion(WOLFSSH*);
|
||||||
WOLFSSH_LOCAL int SendServerVersion(WOLFSSH*);
|
WOLFSSH_LOCAL int SendServerVersion(WOLFSSH*);
|
||||||
WOLFSSH_LOCAL int SendKexInit(WOLFSSH*);
|
WOLFSSH_LOCAL int SendKexInit(WOLFSSH*);
|
||||||
WOLFSSH_LOCAL int SendKexDhReply(WOLFSSH*);
|
WOLFSSH_LOCAL int SendKexDhReply(WOLFSSH*);
|
||||||
|
WOLFSSH_LOCAL int SendNewKeys(WOLFSSH*);
|
||||||
|
|
||||||
|
|
||||||
enum AcceptStates {
|
enum AcceptStates {
|
||||||
|
@ -236,7 +238,8 @@ enum ClientStates {
|
||||||
CLIENT_BEGIN = 0,
|
CLIENT_BEGIN = 0,
|
||||||
CLIENT_VERSION_DONE,
|
CLIENT_VERSION_DONE,
|
||||||
CLIENT_ALGO_DONE,
|
CLIENT_ALGO_DONE,
|
||||||
CLIENT_KEXDHINIT_DONE
|
CLIENT_KEXDHINIT_DONE,
|
||||||
|
CLIENT_USING_KEYS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue