1. Regroup the session keys into a separate structure.

2. Separate sets of keys for client and server.
3. Store generated keys in handshake info record.
4. Copy session keys over when sending and receiving the
   New Keys message.
pull/17/head
John Safranek 2016-10-03 15:30:41 -07:00
parent 30c4a32611
commit 73e4e58795
3 changed files with 76 additions and 52 deletions

View File

@ -954,9 +954,13 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
} }
else { else {
ssh->handshake->encryptId = algoId; ssh->handshake->encryptId = algoId;
ssh->handshake->blockSz = ssh->ivClientSz = ssh->ivServerSz ssh->handshake->blockSz =
= BlockSzForId(algoId); ssh->handshake->clientKeys.ivSz =
ssh->encKeyClientSz = ssh->encKeyServerSz = KeySzForId(algoId); ssh->handshake->serverKeys.ivSz =
BlockSzForId(algoId);
ssh->handshake->clientKeys.encKeySz =
ssh->handshake->serverKeys.encKeySz =
KeySzForId(algoId);
} }
} }
@ -987,7 +991,9 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
else { else {
ssh->handshake->macId = algoId; ssh->handshake->macId = algoId;
ssh->handshake->macSz = MacSzForId(algoId); ssh->handshake->macSz = MacSzForId(algoId);
ssh->macKeyClientSz = ssh->macKeyServerSz = KeySzForId(algoId); ssh->handshake->clientKeys.macKeySz =
ssh->handshake->serverKeys.macKeySz =
KeySzForId(algoId);
} }
} }
} }
@ -1176,6 +1182,7 @@ static int DoNewKeys(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
ssh->peerMacId = ssh->handshake->macId; ssh->peerMacId = ssh->handshake->macId;
ssh->peerBlockSz = ssh->handshake->blockSz; ssh->peerBlockSz = ssh->handshake->blockSz;
ssh->peerMacSz = ssh->handshake->macSz; ssh->peerMacSz = ssh->handshake->macSz;
WMEMCPY(&ssh->clientKeys, &ssh->handshake->clientKeys, sizeof(Keys));
switch (ssh->peerEncryptId) { switch (ssh->peerEncryptId) {
case ID_NONE: case ID_NONE:
@ -1185,8 +1192,9 @@ static int DoNewKeys(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
case ID_AES128_CBC: case ID_AES128_CBC:
WLOG(WS_LOG_DEBUG, "DNK: peer using cipher aes128-cbc"); WLOG(WS_LOG_DEBUG, "DNK: peer using cipher aes128-cbc");
ret = wc_AesSetKey(&ssh->decryptCipher.aes, ret = wc_AesSetKey(&ssh->decryptCipher.aes,
ssh->encKeyClient, ssh->encKeyClientSz, ssh->clientKeys.encKey,
ssh->ivClient, AES_DECRYPTION); ssh->clientKeys.encKeySz,
ssh->clientKeys.iv, AES_DECRYPTION);
break; break;
default: default:
@ -1289,31 +1297,37 @@ int GenerateKey(uint8_t hashId, uint8_t keyId,
static int GenerateKeys(WOLFSSH* ssh) static int GenerateKeys(WOLFSSH* ssh)
{ {
Keys* cK;
Keys* sK;
if (ssh == NULL) if (ssh == NULL)
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
cK = &ssh->handshake->clientKeys;
sK = &ssh->handshake->serverKeys;
GenerateKey(0, 'A', GenerateKey(0, 'A',
ssh->ivClient, ssh->ivClientSz, cK->iv, cK->ivSz,
ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->k, ssh->kSz, ssh->h, ssh->hSz,
ssh->sessionId, ssh->sessionIdSz); ssh->sessionId, ssh->sessionIdSz);
GenerateKey(0, 'B', GenerateKey(0, 'B',
ssh->ivServer, ssh->ivServerSz, sK->iv, sK->ivSz,
ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->k, ssh->kSz, ssh->h, ssh->hSz,
ssh->sessionId, ssh->sessionIdSz); ssh->sessionId, ssh->sessionIdSz);
GenerateKey(0, 'C', GenerateKey(0, 'C',
ssh->encKeyClient, ssh->encKeyClientSz, cK->encKey, cK->encKeySz,
ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->k, ssh->kSz, ssh->h, ssh->hSz,
ssh->sessionId, ssh->sessionIdSz); ssh->sessionId, ssh->sessionIdSz);
GenerateKey(0, 'D', GenerateKey(0, 'D',
ssh->encKeyServer, ssh->encKeyServerSz, sK->encKey, sK->encKeySz,
ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->k, ssh->kSz, ssh->h, ssh->hSz,
ssh->sessionId, ssh->sessionIdSz); ssh->sessionId, ssh->sessionIdSz);
GenerateKey(0, 'E', GenerateKey(0, 'E',
ssh->macKeyClient, ssh->macKeyClientSz, cK->macKey, cK->macKeySz,
ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->k, ssh->kSz, ssh->h, ssh->hSz,
ssh->sessionId, ssh->sessionIdSz); ssh->sessionId, ssh->sessionIdSz);
GenerateKey(0, 'F', GenerateKey(0, 'F',
ssh->macKeyServer, ssh->macKeyServerSz, sK->macKey, sK->macKeySz,
ssh->k, ssh->kSz, ssh->h, ssh->hSz, ssh->k, ssh->kSz, ssh->h, ssh->hSz,
ssh->sessionId, ssh->sessionIdSz); ssh->sessionId, ssh->sessionIdSz);
@ -1325,17 +1339,17 @@ static int GenerateKeys(WOLFSSH* ssh)
printf("Session ID:\n"); printf("Session ID:\n");
DumpOctetString(ssh->sessionId, ssh->sessionIdSz); DumpOctetString(ssh->sessionId, ssh->sessionIdSz);
printf("A:\n"); printf("A:\n");
DumpOctetString(ssh->ivClient, ssh->ivClientSz); DumpOctetString(cK->iv, cK->ivSz);
printf("B:\n"); printf("B:\n");
DumpOctetString(ssh->ivServer, ssh->ivServerSz); DumpOctetString(sK->iv, sK->ivSz);
printf("C:\n"); printf("C:\n");
DumpOctetString(ssh->encKeyClient, ssh->encKeyClientSz); DumpOctetString(cK->encKey, cK->encKeySz);
printf("D:\n"); printf("D:\n");
DumpOctetString(ssh->encKeyServer, ssh->encKeyServerSz); DumpOctetString(sK->encKey, sK->encKeySz);
printf("E:\n"); printf("E:\n");
DumpOctetString(ssh->macKeyClient, ssh->macKeyClientSz); DumpOctetString(cK->macKey, cK->macKeySz);
printf("F:\n"); printf("F:\n");
DumpOctetString(ssh->macKeyServer, ssh->macKeyServerSz); DumpOctetString(sK->macKey, sK->macKeySz);
printf("\n"); printf("\n");
#endif /* SHOW_SECRETS */ #endif /* SHOW_SECRETS */
@ -2322,7 +2336,8 @@ static INLINE int CreateMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz,
uint8_t digest[SHA_DIGEST_SIZE]; uint8_t digest[SHA_DIGEST_SIZE];
wc_HmacSetKey(&hmac, SHA, wc_HmacSetKey(&hmac, SHA,
ssh->macKeyServer, ssh->macKeyServerSz); ssh->serverKeys.macKey,
ssh->serverKeys.macKeySz);
wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
wc_HmacUpdate(&hmac, in, inSz); wc_HmacUpdate(&hmac, in, inSz);
wc_HmacFinal(&hmac, digest); wc_HmacFinal(&hmac, digest);
@ -2335,7 +2350,8 @@ static INLINE int CreateMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz,
Hmac hmac; Hmac hmac;
wc_HmacSetKey(&hmac, SHA, wc_HmacSetKey(&hmac, SHA,
ssh->macKeyServer, ssh->macKeyServerSz); ssh->serverKeys.macKey,
ssh->serverKeys.macKeySz);
wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
wc_HmacUpdate(&hmac, in, inSz); wc_HmacUpdate(&hmac, in, inSz);
wc_HmacFinal(&hmac, mac); wc_HmacFinal(&hmac, mac);
@ -2347,7 +2363,8 @@ static INLINE int CreateMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz,
Hmac hmac; Hmac hmac;
wc_HmacSetKey(&hmac, SHA256, wc_HmacSetKey(&hmac, SHA256,
ssh->macKeyServer, ssh->macKeyServerSz); ssh->serverKeys.macKey,
ssh->serverKeys.macKeySz);
wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
wc_HmacUpdate(&hmac, in, inSz); wc_HmacUpdate(&hmac, in, inSz);
wc_HmacFinal(&hmac, mac); wc_HmacFinal(&hmac, mac);
@ -2376,7 +2393,7 @@ static INLINE int VerifyMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz,
WLOG(WS_LOG_DEBUG, "VerifyMac %s", IdToName(ssh->peerMacId)); WLOG(WS_LOG_DEBUG, "VerifyMac %s", IdToName(ssh->peerMacId));
WLOG(WS_LOG_DEBUG, "VM: inSz = %u", inSz); WLOG(WS_LOG_DEBUG, "VM: inSz = %u", inSz);
WLOG(WS_LOG_DEBUG, "VM: seq = %u", ssh->peerSeq); WLOG(WS_LOG_DEBUG, "VM: seq = %u", ssh->peerSeq);
WLOG(WS_LOG_DEBUG, "VM: keyLen = %u", ssh->macKeyClientSz); WLOG(WS_LOG_DEBUG, "VM: keyLen = %u", ssh->clientKeys.macKeySz);
switch (ssh->peerMacId) { switch (ssh->peerMacId) {
case ID_NONE: case ID_NONE:
@ -2384,7 +2401,8 @@ static INLINE int VerifyMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz,
case ID_HMAC_SHA1: case ID_HMAC_SHA1:
case ID_HMAC_SHA1_96: case ID_HMAC_SHA1_96:
wc_HmacSetKey(&hmac, SHA, ssh->macKeyClient, ssh->macKeyClientSz); wc_HmacSetKey(&hmac, SHA,
ssh->clientKeys.macKey, ssh->clientKeys.macKeySz);
wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
wc_HmacUpdate(&hmac, in, inSz); wc_HmacUpdate(&hmac, in, inSz);
wc_HmacFinal(&hmac, checkMac); wc_HmacFinal(&hmac, checkMac);
@ -2394,7 +2412,7 @@ static INLINE int VerifyMac(WOLFSSH* ssh, const uint8_t* in, uint32_t inSz,
case ID_HMAC_SHA2_256: case ID_HMAC_SHA2_256:
wc_HmacSetKey(&hmac, SHA256, wc_HmacSetKey(&hmac, SHA256,
ssh->macKeyClient, ssh->macKeyClientSz); ssh->clientKeys.macKey, ssh->clientKeys.macKeySz);
wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq)); wc_HmacUpdate(&hmac, flatSeq, sizeof(flatSeq));
wc_HmacUpdate(&hmac, in, inSz); wc_HmacUpdate(&hmac, in, inSz);
wc_HmacFinal(&hmac, checkMac); wc_HmacFinal(&hmac, checkMac);
@ -3002,6 +3020,7 @@ int SendNewKeys(WOLFSSH* ssh)
ssh->encryptId = ssh->handshake->encryptId; ssh->encryptId = ssh->handshake->encryptId;
ssh->macSz = ssh->handshake->macSz; ssh->macSz = ssh->handshake->macSz;
ssh->macId = ssh->handshake->macId; ssh->macId = ssh->handshake->macId;
WMEMCPY(&ssh->serverKeys, &ssh->handshake->serverKeys, sizeof(Keys));
switch (ssh->encryptId) { switch (ssh->encryptId) {
case ID_NONE: case ID_NONE:
@ -3011,8 +3030,9 @@ int SendNewKeys(WOLFSSH* ssh)
case ID_AES128_CBC: case ID_AES128_CBC:
WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-cbc"); WLOG(WS_LOG_DEBUG, "SNK: using cipher aes128-cbc");
ret = wc_AesSetKey(&ssh->encryptCipher.aes, ret = wc_AesSetKey(&ssh->encryptCipher.aes,
ssh->encKeyServer, ssh->encKeyServerSz, ssh->serverKeys.encKey,
ssh->ivServer, AES_ENCRYPTION); ssh->serverKeys.encKeySz,
ssh->serverKeys.iv, AES_ENCRYPTION);
break; break;
default: default:

View File

@ -125,23 +125,25 @@ void wolfSSH_CTX_free(WOLFSSH_CTX* ctx)
static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx) static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
{ {
HandshakeInfo* handshake; HandshakeInfo* handshake = NULL;
RNG* rng; RNG* rng = NULL;
void* heap;
WLOG(WS_LOG_DEBUG, "Entering SshInit()"); WLOG(WS_LOG_DEBUG, "Entering SshInit()");
if (ssh == NULL) if (ssh == NULL || ctx == NULL)
return ssh; return ssh;
heap = ctx->heap;
handshake = (HandshakeInfo*)WMALLOC(sizeof(HandshakeInfo), handshake = (HandshakeInfo*)WMALLOC(sizeof(HandshakeInfo),
ctx->heap, DYNTYPE_HS); heap, DYNTYPE_HS);
if (handshake == NULL) { rng = (RNG*)WMALLOC(sizeof(RNG), heap, DYNTYPE_RNG);
wolfSSH_free(ssh);
return NULL;
}
rng = (RNG*)WMALLOC(sizeof(RNG), ctx->heap, DYNTYPE_RNG); if (handshake == NULL || rng == NULL || wc_InitRng(rng) != 0) {
if (rng == NULL || wc_InitRng(rng) != 0) {
WLOG(WS_LOG_DEBUG, "SshInit: Cannot allocate memory.\n");
WFREE(handshake, heap, DYNTYPE_HS);
WFREE(rng, heap, DYNTYPE_RNG);
wolfSSH_free(ssh); wolfSSH_free(ssh);
return NULL; return NULL;
} }
@ -220,9 +222,11 @@ static void SshResourceFree(WOLFSSH* ssh, void* heap)
ShrinkBuffer(&ssh->outputBuffer, 1); ShrinkBuffer(&ssh->outputBuffer, 1);
ForceZero(ssh->k, ssh->kSz); ForceZero(ssh->k, ssh->kSz);
if (ssh->handshake) { if (ssh->handshake) {
WMEMSET(ssh->handshake, 0, sizeof(HandshakeInfo)); ForceZero(ssh->handshake, sizeof(HandshakeInfo));
WFREE(ssh->handshake, heap, DYNTYPE_HS); WFREE(ssh->handshake, heap, DYNTYPE_HS);
} }
ForceZero(&ssh->clientKeys, sizeof(Keys));
ForceZero(&ssh->serverKeys, sizeof(Keys));
if (ssh->rng) { if (ssh->rng) {
wc_FreeRng(ssh->rng); wc_FreeRng(ssh->rng);
WFREE(ssh->rng, heap, DYNTYPE_RNG); WFREE(ssh->rng, heap, DYNTYPE_RNG);
@ -244,11 +248,10 @@ static void SshResourceFree(WOLFSSH* ssh, void* heap)
void wolfSSH_free(WOLFSSH* ssh) void wolfSSH_free(WOLFSSH* ssh)
{ {
void* heap = ssh->ctx ? ssh->ctx->heap : NULL;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_free()"); WLOG(WS_LOG_DEBUG, "Entering wolfSSH_free()");
if (ssh) { if (ssh) {
void* heap = ssh->ctx ? ssh->ctx->heap : NULL;
SshResourceFree(ssh, heap); SshResourceFree(ssh, heap);
WFREE(ssh, heap, DYNTYPE_SSH); WFREE(ssh, heap, DYNTYPE_SSH);
} }

View File

@ -154,6 +154,16 @@ typedef struct Ciphers {
} Ciphers; } Ciphers;
typedef struct Keys {
uint8_t iv[AES_BLOCK_SIZE];
uint8_t ivSz;
uint8_t encKey[AES_BLOCK_SIZE];
uint8_t encKeySz;
uint8_t macKey[MAX_HMAC_SZ];
uint8_t macKeySz;
} Keys;
typedef struct HandshakeInfo { typedef struct HandshakeInfo {
uint8_t kexId; uint8_t kexId;
uint8_t pubKeyId; uint8_t pubKeyId;
@ -164,6 +174,8 @@ typedef struct HandshakeInfo {
uint8_t blockSz; uint8_t blockSz;
uint8_t macSz; uint8_t macSz;
Keys clientKeys;
Keys serverKeys;
Sha hash; Sha hash;
uint8_t e[257]; /* May have a leading zero, for unsigned. */ uint8_t e[257]; /* May have a leading zero, for unsigned. */
uint32_t eSz; uint32_t eSz;
@ -223,19 +235,8 @@ struct WOLFSSH {
uint8_t sessionId[SHA_DIGEST_SIZE]; uint8_t sessionId[SHA_DIGEST_SIZE];
uint32_t sessionIdSz; uint32_t sessionIdSz;
uint8_t ivClient[AES_BLOCK_SIZE]; Keys clientKeys;
uint8_t ivClientSz; Keys serverKeys;
uint8_t ivServer[AES_BLOCK_SIZE];
uint8_t ivServerSz;
uint8_t encKeyClient[AES_BLOCK_SIZE];
uint8_t encKeyClientSz;
uint8_t encKeyServer[AES_BLOCK_SIZE];
uint8_t encKeyServerSz;
uint8_t macKeyClient[MAX_HMAC_SZ];
uint8_t macKeyClientSz;
uint8_t macKeyServer[MAX_HMAC_SZ];
uint8_t macKeyServerSz;
HandshakeInfo* handshake; HandshakeInfo* handshake;
void* userAuthCtx; void* userAuthCtx;